services: traefik: image: traefik:latest container_name: traefik restart: unless-stopped security_opt: - no-new-privileges:true ports: - "80:80" - "443:443" - "2222:2222" # Gitea SSH networks: - traefik-public environment: - TZ=Europe/Berlin entrypoint: /entrypoint-custom.sh volumes: # Docker socket for service discovery - /var/run/docker.sock:/var/run/docker.sock:ro # SSL certificates - traefik-certs:/letsencrypt # Logs - traefik-logs:/logs # Custom entrypoint script - ./entrypoint.sh:/entrypoint-custom.sh:ro secrets: - acme_email labels: # Enable Traefik for itself - "traefik.enable=true" # Dashboard - BasicAuth protected - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.michaelschiemer.de`)" - "traefik.http.routers.traefik-dashboard.entrypoints=websecure" - "traefik.http.routers.traefik-dashboard.tls=true" - "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt" - "traefik.http.routers.traefik-dashboard.service=api@internal" - "traefik.http.routers.traefik-dashboard.middlewares=traefik-auth" # BasicAuth for dashboard (password: admin) - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$Of2wG3O5$$y8X1vEoIp9vpvx64mIalk/" # Global HTTP to HTTPS redirect (excludes ACME challenge) - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`) && !PathPrefix(`/.well-known/acme-challenge`)" - "traefik.http.routers.http-catchall.entrypoints=web" - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" - "traefik.http.routers.http-catchall.priority=1" - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true" healthcheck: test: ["CMD", "traefik", "healthcheck", "--ping"] interval: 30s timeout: 10s retries: 3 start_period: 10s networks: traefik-public: external: true name: traefik-public volumes: traefik-certs: name: traefik-certs traefik-logs: name: traefik-logs secrets: acme_email: file: ./secrets/acme_email.txt