Traefik Setup

mkdir -p data/configurations
touch docker-compose.yml
touch data/traefik.yml
touch data/acme.json
touch data/configurations/dynamic.yml
chmod 600 data/acme.json

Docker-compose.yml

version: '3.7'

services:
  traefik:
    image: traefik:v2.4
    container_name: traefik
    restart: always
    security_opt:
      - no-new-privileges:true
    ports:
      - 80:80
      - 443:443
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
      # Add folder with dynamic configuration yml
      - ./data/configurations:/configurations
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.traefik-secure.entrypoints=websecure"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik.yourdomain`)"
      - "traefik.http.routers.traefik-secure.middlewares=user-auth@file"
      - "traefik.http.routers.traefik-secure.service=api@internal"

networks:
  proxy:
    external: true

~/data/traefik.yml

api:
  dashboard: true

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure

  websecure:
    address: :443
    http:
      middlewares:
        - secureHeaders@file
        - nofloc@file
      tls:
        certResolver: letsencrypt

pilot:
  dashboard: false

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /configurations/dynamic.yml

certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@yourdomain
      storage: acme.json
      keyType: EC384
      httpChallenge:
        entryPoint: web

  buypass:
    acme:
      email: admin@yourdomain
      storage: acme.json
      caServer: https://api.buypass.com/acme/directory
      keyType: EC256
      httpChallenge:
        entryPoint: web

~/data/configurations/dynamic.yml

# Dynamic configuration
http:
  middlewares:
    nofloc:
      headers:
        customResponseHeaders:
          Permissions-Policy: "interest-cohort=()"
    secureHeaders:
      headers:
        sslRedirect: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 31536000   

    # UserName : admin
    # Password : qwer1234    
    user-auth:
      basicAuth:
        users:
          - "admin:$apr1$tm53ra6x$FntXd6jcvxYM/YH0P2hcc1"

tls:
  options:
    default:
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
      minVersion: VersionTLS12

⚠️ For generating basicAuth

echo $(htpasswd -nbB user password) | sed -e 's/\\$/\\$\\$/g'

Ghost config

mkdir -p ghost-blog/ghost/content
touch ghost-blog/docker-compose.yml
touch ghost-blog/ghost/config.production.json

docker-compose.yml

version: '3.7'

services:
  ghost:
    image: ghost:3-alpine
    container_name: ghost
    environment:
      NODE_ENV: production
    volumes:
      - ./ghost/content:/var/lib/ghost/content
      - ./ghost/config.production.json:/var/lib/ghost/config.production.json
    networks:
      - proxy
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.ghost-secure.entrypoints=websecure"
      - "traefik.http.routers.ghost-secure.rule=Host(`blog.yourdomain`)"
      - "traefik.http.routers.ghost-secure.service=ghost-service"
      - "traefik.http.services.ghost-service.loadbalancer.server.port=2368"

networks:
  proxy:
    external: true

config.production.json

 {
  "url": "https://blog.yourdomain",
  "server": {
    "port": 2368,
    "host": "0.0.0.0"
  },
  "database": {
    "client": "sqlite3",
    "connection": {
      "filename": "/var/lib/ghost/content/data/ghost.db"
    }
  },
  "mail": {
    "transport": "Direct"
  },
  "logging": {
    "path": "/var/lib/ghost/content/logs/",
    "level": "info",
    "rotation": {
      "enabled": true,
      "count": 15,
      "period": "1d"
    },
    "transports": ["stdout", "file"]
  },
  "paths": {
    "contentPath": "/var/lib/ghost/content"
  }
}

OPTIONAL

"mail": {
    "from": "'Ghost Support' <YOUR_EMAIL>",
    "transport": "SMTP",
    "options": {
        "host": "smtp.exmail.qq.com",
        "port": 465,
        "secureConnection": true,
        "auth": {
          "user": "YOUR_EMAIL",
          "pass": "YOUR_EMAIL_PASSWORD"
        }
    }
}