Joplin+Traefik+LetsEncryptLE docker-compose working docker-compose.yml

Here's my docker-compose with joplin/traefik/letsencrypt in case some found it useful. It gives you an "A" rate on https://www.ssllabs.com/ssltest/. (if I should post elsewhere please point me)

docker-compose.yml

services:

  traefik:
    image: "traefik:v2.2"
    container_name: "traefik"
    restart: always
    command:
      - "--log.level=INFO"
      #- "--api.insecure=true"
      - "--api.insecure=false"
      - "--providers.docker"
      - "--providers.file.directory=/etc/traefik/dynamic"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=xxxx@xxxx.coom"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      # The Web UI (enabled if --api.insecure=true)
      - "8080:8080"
    volumes:
      - "/srv/traefik/letsencrypt:/letsencrypt"
      - "/srv/traefik/conf/traefik-conf.yml:/etc/traefik/dynamic/traefik-conf.yaml"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
  joplin-db:
    image: postgres:16
    volumes:
      - /srv/joplin/data/postgres:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    restart: unless-stopped
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_DB=${POSTGRES_DATABASE}
  joplin-app:
    image: joplin/server:latest
    depends_on:
      - joplin-db
    ports:
      - "22300:22300"
    restart: unless-stopped
    environment:
      - APP_PORT=22300
      - APP_BASE_URL=${APP_BASE_URL}
      - DB_CLIENT=pg
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DATABASE=${POSTGRES_DATABASE}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PORT=${POSTGRES_PORT}
      - POSTGRES_HOST=joplin-db
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.joplin.rule=Host(`joplin.xxxxxxx.net`)"
      - "traefik.http.routers.joplin.entrypoints=websecure"
      - "traefik.http.routers.joplin.tls=true"
      - "traefik.http.routers.joplin.tls.certresolver=myresolver"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto = http"
      - "traefik.http.routers.joplin.service=joplin-server"
      - "traefik.http.services.joplin-server.loadbalancer.passhostheader=true"
      - "traefik.http.services.joplin-server.loadbalancer.server.port=22300"

traefik-conf.yaml

tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_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

Any suggestions?

I've dedicated some time to upgrade to latest Traefik version and introduce some headers configuration to get the A+ rate. Also cleaned some code

docker-compose.yml

services:
  traefik:
    image: "traefik:3.4.1"
    container_name: "traefik"
    restart: always
    command:
      # Static conf
      - "--log.level=INFO"
      - "--providers.docker"
      - "--providers.file.directory=/etc/traefik/dynamic" # Path for dynamic configuration
      - "--providers.file.watch=true" # Watch for changes in dynamic configuration
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # Global redirecto from HTTP to HTTPS
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      # Resolver conf for Let's Encrypt
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=xxxx@xxxx.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/srv/traefik/letsencrypt:/letsencrypt"
      - "/srv/traefik/conf/traefik-conf.yml:/etc/traefik/dynamic/traefik-conf.yaml"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  joplin-db:
    image: postgres:16
    volumes:
      - /srv/joplin/data/postgres:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    restart: unless-stopped
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_DB=${POSTGRES_DATABASE}
  
  joplin-app:
    image: joplin/server:latest
    depends_on:
      - joplin-db
    ports:
      - "22300:22300"
    restart: unless-stopped
    environment:
      - APP_PORT=22300
      - APP_BASE_URL=${APP_BASE_URL}
      - DB_CLIENT=pg
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DATABASE=${POSTGRES_DATABASE}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PORT=${POSTGRES_PORT}
      - POSTGRES_HOST=joplin-db
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.joplin.rule=Host(`joplin.xxxxxxxx.net`)"
      - "traefik.http.routers.joplin.entrypoints=websecure"
      - "traefik.http.routers.joplin.tls=true"
      - "traefik.http.routers.joplin.tls.certresolver=myresolver"
      - "traefik.http.routers.joplin.service=joplin-server"
      
      # Apply general middleware for security headers
      - "traefik.http.routers.joplin.middlewares=secure-headers@file"
      
      # Service configuration
      - "traefik.http.services.joplin-server.loadbalancer.passhostheader=true"
      - "traefik.http.services.joplin-server.loadbalancer.server.port=22300"

traefik-conf.yml

tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
http:
  middlewares:
    secure-headers:
      headers:
        stsSeconds: 31536000
        stsIncludeSubdomains: true
        stsPreload: true
        frameDeny: true
        contentTypeNosniff: true
        browserXssFilter: true