Le but de cette documentation est de vous fournir un fichier .yml clé en main pour installer le CMS Ghost avec Traefik.


Mise à jour : 18/11/2021

  • mise à jour des fichiers .yml de traefik (suppression des .toml)
  • mise à jour du fichier docker-compose.yml
  • suppression des variables d’environnement (fichier .env)

Contexte

Ghost est un CMS pour propulser des sites web type « blog », un peu comme ComputerZ Solutions ;). Cet outil nécessite une base de données SQL dans laquelle y seront stockées toutes les données (pages, posts et configurations).

logo ghost 4

Installation

Quelques pré-requis avant de se lancer : avoir Docker (pour Ubuntu ou CentOS 7) et docker-compose installé sur votre machine. J’utilise le chemin « /srv/docker » sur mon serveur et y ait créé un dossier « conf » où sont stockés les fichiers de configuration pour les différents services, un dossier « traefikdynamic » pour les configurations personnalisés pour Traefik et enfin un dossier « logs » pour Traefik.

De plus, il est important de créer le fichier acme.json dans le dossier « conf » avec les droits nécessaires avant de créer les conteneurs :

touch /srv/docker/conf/acme.json
chmod 0600 /srv/docker/conf/acme.json
---
version: '3.7'
services:
  traefik:
    image: traefik:2.5
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./conf/acme.json:/acme.json
      - ./conf/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./conf/traefikdynamic:/etc/traefik/dynamic:ro
      - ./logs/traefik.log:/etc/traefik/applog.log
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      TRAEFIK_PILOT_DASHBOARD: false
      TZ: "Europe/Paris"

  sqlghost:
    image: mariadb:10.5
    restart: unless-stopped
    volumes:
      - ./conf/custom-mysql.cnf:/etc/mysql/conf.d/custom-mysql.cnf
      - /etc/localtime:/etc/localtime:ro
      - datasqlghost:/var/lib/mysql
      - datasqlghostlog:/var/log/mysql
    environment:
      MYSQL_ROOT_PASSWORD: "password"
      MYSQL_USER: "sqluser"
      MYSQL_PASSWORD: "sqlpassword
      MYSQL_DATABASE: "ghostdb"
      TZ: "Europe/Paris"

  ghost:
    image: ghost:4
    restart: unless-stopped
    volumes:
      - ./conf/config.production.json:/var/lib/ghost/config.production.json:ro
      - /etc/localtime:/etc/localtime:ro
      - dataghost:/var/lib/ghost/content
    depends_on:
      - sqlghost
    environment:
      TZ: "Europe/Paris"

volumes:
  dataghost:
  datasqlghost:

Seul le conteneur Ghost a des labels correspondant pour Traefik : avec ces quelques lignes, Ghost sera accessible depuis le web et automatiquement géré en SSL via Traefik.

Vous remarquerez aussi des volumes complémentaires comme /etc/timezone et /etc/localtime, utilisé pour être en relation avec le serveur hôte (qui est à l’heure via NTP) et donc avoir un horodatage cohérent.

Avant de lancer les conteneurs, vous devez encore créer des fichiers, notamment deux pour Traefik :

---
global:
  sendAnonymousUsage: false
  checkNewVersion: false

api:
  dashboard: true

pilot:
  dashboard: false

log:
  filePath: "/etc/traefik/applog.log"
  format: json
  level: "ERROR"

providers:
  docker:
    endpoint: unix:///var/run/docker.sock
    exposedByDefault: false
    watch: true
    swarmMode: false
  file:
    directory: "/etc/traefik/dynamic"
    watch: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
#      caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      caServer: https://acme-v02.api.letsencrypt.org/directory
      storage: acme.json
      keyType: EC256
      httpChallenge:
        entryPoint: web

Le fichier de configuration Traefik se décompose sous forme de blocs. Tout est assez explicite, je ne vais pas faire une description pour chaque ligne.

Le second fichier traefik_dynamic.yml est à placer dans un dossier « traefikdynamic », dans le dossier « conf » précédement initialisé.

---
tls:
  options:
    default:
      minVersion: VersionTLS12
      sniStrict: true
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384

http:
  middlewares:
    compression:
      compress:
        excludedContentTypes:
          - text/event-stream

    security:
      headers:
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        accessControlMaxAge: 100
        addVaryHeader: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        frameDeny: true
        sslRedirect: true
        sslForceHost: true
        stsPreload: true
        customFrameOptionsValue: SAMEORIGIN
        referrerPolicy: "same-origin"
        featurePolicy: "camera 'none'; microphone 'none'; payment 'none'; usb 'none';"
        stsSeconds: 315360000
        hostsProxyHeaders:
          - "X-Forwarded-Host"

    authentification:
      basicAuth:
        users:
        - admin:$2y$10$byzmasKak2LLmvY86KcnGO0pX8UaaNDxQZMJW.wMmaoHRhjNXqOwG # admin/admin, use "https://bcrypt.fr" to encrypt your password


  services:
    sc-ghost:
      loadBalancer:
        servers:
        - url: "http://ghost:2368"

  routers:
    rt-traefik:
      entryPoints:
      - websecure
      middlewares:
      - authentification
      service: [email protected]
      rule: Host (`traefik.czs.local`)
      tls:
        certResolver: letsencrypt

    rt-ghost:
      entryPoints:
      - websecure
      middlewares:
      - security
      - compression
      service: sc-ghost
      rule: Host (`ghost.czs.local`)
      tls:
        certResolver: letsencrypt

Ghost a aussi besoin d’un fichier de configuration pour être exploitable. Suivez bien le formalisme du fichier config.production.json requis :

{
    "url": "https://ghost.czs.local",
    "server": {
      "port": 2368,
      "host": "0.0.0.0"
    },
    "database": {
      "client": "mysql",
      "connection": {
        "host": "sqlghost",
        "user": "ghost",
        "port": "3306",
        "password": "sqlghostuserpassword",
        "database": "ghost"
      }
    },
    "privacy": {
      "useUpdateCheck": false,
      "useGravatar": false,
      "useRpcPing": false,
      "useStructuredData": true
    },
    "process": "systemd",
    "paths": {
      "contentPath": "/var/lib/ghost/content"
    }
}

Maintenant que vos fichiers sont créés, vous pouvez initier un docker-compose up -d et voir la magie s’opérer… 🙂 Le site web sera accessible au nom de domaine stipulé dans la configuration, Traefik effectuera automatiquement la redirection avec du HTTPS et un certificat provenant de Let’s Encrypt.

Vous pouvez trouver l’ensemble des scripts et code de cette page à cette adresse Github.

Auteur

Bercé par l'informatique depuis mon plus jeune âge, je transforme ma passion en expertise.

Écrire un commentaire