Outline: Vous avez dit documentation ?

L'équivalent open-source à Notion

Outline: Vous avez dit documentation ?
Photo by Julia Joppien / Unsplash

Maintenant que l'on a un reverse proxy aux petits oignions, nous allons pouvoir construire une petite stack utile.

Et ca commence par ... la documentation ! Et oui, s'il y a bien une chose que la plupart des dev n'aime pas trop c'est la doc...
En revanche, on ne peut nier son utilité, intérêt. Mais surtout au delà de l'utilité pour les tech, une documentation tel qu'Outline (ou Notion ou équivalent) permet également à la direction ou aux RH d'y produire des document à destination des collaborateurs.

Et bien sur, un doc permet d'alimenter un model AI... Teasing, on verra ça une prochaine fois 😄

Outline

Donc outline est un équivalent open-source à Notion

Outline screenshot

Vraiment simple à utiliser, il possède pas mal d'options.

  • Workspace: vous pouvez créer des Espace de travail pour isoler certaines information
  • Intégration Google/Github/Webhook.

Installation

Facile grâce à notre petite infra 😏

On commence par créer un .env, en sachant que j'ai fait le choix d'utiliser Google pour l'authentification, et de stocker dans le serveur S3 de mon provider.

APP_NAME=outline
APP_DNS=outline.dns.com

# Outline
DEFAULT_LANGUAGE=fr_FR
SECRET_KEY=<openssl rand -hex 32>
UTILS_SECRET=<openssl rand -hex 32>

# Postgres
DB_NAME=outline
DB_USER=<openssl rand -hex 16>
DB_PASS=<openssl rand -hex 32>

# Object Storage
S3_ACCESS_KEY_ID=<ton-access-key>
S3_SECRET_ACCESS_KEY=<ton-secret-key>
S3_REGION=<ta-region>
S3_UPLOAD_BUCKET_URL=<bucket-url>
S3_UPLOAD_BUCKET_NAME=<bucket-name>
UPLOAD_MAX_SIZE=26214400

# Google OAuth2
GOOGLE_CLIENT_ID=<client-id>
GOOGLE_CLIENT_SECRET=<secret-key>

# SMTP
SMTP_HOST=pro1.mail.ovh.net
SMTP_PORT=587
SMTP_USERNAME=outline@dns.com
SMTP_PASSWORD=<mon-super-mot-de-passe>
SMTP_REPLY_EMAIL=outline@dns.com

Je vous invite bien sur à regarder la doc (RTFM), car vous n'êtes bien sur pas obligé d'utiliser Google pour l'authent, ou le stockage S3.

Et maintenant le docker-compose.yml

name: outline

services:
  outline:
    image: docker.getoutline.com/outlinewiki/outline:latest
    container_name: ${APP_NAME}
    environment:
      - URL=https://${APP_DNS}
      - PORT=3000
      - FORCE_HTTPS=false
      - LOG_LEVEL=info
      - NODE_ENV=production
      - SECRET_KEY=${SECRET_KEY}
      - UTILS_SECRET=${UTILS_SECRET}
      - REDIS_URL=redis://redis:6379
      - DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@outline-postgres:5432/${DB_NAME}
      - DATABASE_URL_TEST=postgres://${DB_USER}:${DB_PASS}@outline-postgres:5432/${DB_NAME}-test
      - FILE_STORAGE=s3
      - FILE_STORAGE_UPLOAD_MAX_SIZE=${UPLOAD_MAX_SIZE}
      - AWS_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY}
      - AWS_REGION=${S3_REGION}
      - AWS_S3_UPLOAD_BUCKET_URL=${S3_BUCKET_URL}
      - AWS_S3_UPLOAD_BUCKET_NAME=${S3_BUCKET_NAME}
      - AWS_S3_UPLOAD_MAX_SIZE=${UPLOAD_MAX_SIZE}
      - AWS_S3_FORCE_PATH_STYLE=true
      - AWS_S3_ACL=private
      - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
      - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
      - ENABLE_UPDATES=true
      - WEB_CONCURRENCY=1
      - MAXIMUM_IMPORT_SIZE=5120000
      - DEFAULT_LANGUAGE=${DEFAULT_LANGUAGE}
      - RATE_LIMITER_ENABLED=true
      - RATE_LIMITER_REQUESTS=1000
      - RATE_LIMITER_DURATION_WINDOW=60
      - DEVELOPMENT_UNSAFE_INLINE_CSP=false
      - PGSSLMODE=disable
      - SMTP_HOST=${SMTP_HOST}
      - SMTP_PORT=${SMTP_PORT}
      - SMTP_USERNAME=${SMTP_USERNAME}
      - SMTP_PASSWORD=${SMTP_PASSWORD}
      - SMTP_FROM_EMAIL=${SMTP_USERNAME}
      - SMTP_REPLY_EMAIL=${SMTP_REPLY_EMAIL}
      - SMTP_SECURE=true
    volumes:
      - outline_data:/var/lib/outline/data
    depends_on:
      - outline-postgres
    networks:
      - internal
      - web
    labels:
      - traefik.enable=true
      - traefik.http.routers.${APP_NAME}.rule=Host(`${APP_DNS}`)
      - traefik.http.routers.${APP_NAME}.entrypoints=websecure
      - traefik.http.routers.${APP_NAME}.service=${APP_NAME}
      - traefik.http.services.${APP_NAME}.loadbalancer.server.port=3000

  redis:
    restart: on-failure
    image: redis
    networks:
      - internal

  outline-postgres:
    image: postgres
    container_name: outline-postgres
    environment:
      - PGUSER=${DB_USER}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASS}
      - POSTGRES_DB=${DB_NAME}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - internal
    healthcheck:
      test: ["CMD", "pg_isready"]
      interval: 30s
      timeout: 20s
      retries: 3
 
  outline-db-backup:
    image: tiredofit/db-backup
    container_name: outline-db-backup
    depends_on:
      - outline-postgres
    environment:
      - DB_TYPE=postgres
      - DB_HOST=outline-postgres
      - DB_NAME=${DB_NAME}
      - DB_USER=${DB_USER}
      - DB_PASS=${DB_PASS}
      - DB_DUMP_FREQ=720
      - DB_CLEANUP_TIME=72000
      - CHECKSUM=SHA1
      - COMPRESSION=GZIP
      - SPLIT_DB=true
      - CONTAINER_ENABLE_MONITORING=false
    volumes:
      - ./backups:/backup
    networks:
      - internal
    restart: unless-stopped

volumes:
  outline_data:
  postgres_data:

networks:
  internal:
  web:
    external: true

Et voilà, je vous laisse démarrer vos containers docker compose up -d. Un fois le service démarrer il devrait être dispo, sous le nom de domaine choisi, avec son certificat SSL Letsencrypt.

Bon documentation à toi 😃