Files

To use traefik in your own setup please create all files and place them in a folder on your server. Here an example for /opt/docker/proxy/:

/opt/docker/proxy/
├── -rw-r--r-- docker-compose.yml
├── secrets
│   ├── -rw------- acme.json
│   └── -rw------- hetzner_key
└── traefik
    ├── -rw------- dynamic.yaml
    └── -rw------- static.yaml

docker-compose.yaml

The DNS-01 challenge can be used to generate and renew ACME certificates by provisioning a DNS record. Docker variables can be found here.

In compose a network called proxy is used, so other container can join it. To create it docker create network proxy needs to be executed.

The files static.yaml, dynamic.yaml & acme.json are mounted into the container.

version: "3.9"

# external network so other services can join it
networks:
  proxy:
    external: true

# Only if using DNS-01 challenge
# Use your own provider (https://doc.traefik.io/traefik/v2.8/https/acme/)
secrets:
  hetzner:
    file: ./secrets/hetzner_key

services:
  traefik:
    # update version if needed
    image: traefik:2.9
    container_name: traefik
    restart: always
    # Only if using DNS-01 challenge
    secrets:
      - hetzner
    environment:
      - TZ=Europe/Berlin
      # Only if using DNS-01 challenge
      - HETZNER_API_KEY_FILE=/run/secrets/hetzner
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/static.yaml:/etc/traefik/traefik.yaml
      - ./traefik/dynamic.yaml:/dynamic.yaml
      - ./secrets/acme.json:/acme.json
    ports:
      - "80:80"
      - "443:443"
      # this will expose the dashboard on localhost only
      - "127.0.0.1:8080:8080"
    networks:
      - proxy

static.yaml

The provided default values will always expect proxy to be the docker network and create a Host based on the docker compose service name. In the example it will create grafana.example.com automatically without adding a label.

global:
  checkNewVersion: true
  sendAnonymousUsage: false
serversTransport:
  # if you are using nextcloud the local connection can be used with tls
  insecureSkipVerify: true
entryPoints:
  web:
    address: :80
    http:
      # redirect all http traffic to https
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: :443
    http:
      # always use the configured resolver and add secure headers
      middlewares: ["secure-headers@file"]
      tls:
        certResolver: "hetzner"
providers:
  file:
    filename: "dynamic.yaml"
  docker:
    exposedByDefault: false
    # this is the docker network
    network: "proxy"
    # this rule will publish the service with name of the docker by default
    defaultRule: 'Host(`{{ index .Labels "com.docker.compose.service"}}.example.de`)'
# if you dont want to use the dashboard remove
api:
  dashboard: true
  insecure: true
# i am using hetzner DNS challenge
# https://doc.traefik.io/traefik/https/acme/
certificatesResolvers:
  hetzner:
    acme:
      email: "mail@example.de"
      storage: "acme.json"
      dnsChallenge:
        provider: "hetzner"

dynamic.yaml

http:
  middlewares:
    # secure headers middleware
    # check your service with https://dnschecker.org/
    secure-headers:
      headers:
        frameDeny: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 63072000
        customFrameOptionsValue: "SAMEORIGIN"
        referrerPolicy: "strict-origin"

tls:
  options:
    default:
      sniStrict: true
      minVersion: "VersionTLS12"
      cipherSuites:
        - "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"

Example service

This will create two services that will be published with traefik. The first service will be automatically published with the domain whoami.example.de. This automatic creation of a domain can be overwritten as shown in the second service.

version: "3.9"

networks:
  proxy:
    external: true

services:
  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
    networks:
      - proxy

  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.custom.rule=Host(`custom.example.de`)"
    networks:
      - proxy

DNS

Add the record whoami.example.de and custom.example.de to the dns records of the domain and point it to the server. Make sure ports 80 & 443 are open on the server as traefik will listen on them.