--- # Example of a SNAC + Traefik stack on Docker Swarm mode # SNAC behind Traefik v3 reverse proxy # including Let's Encrypt certificates, HTTP security headers # and caching */s/* (SNAC static files) for 24h with souin. # # docker stack deploy -c snac_stack.yml snac services: traefik: image: traefik:v3 hostname: '{{.Node.Hostname}}' ports: # listen on host ports without ingress network - target: 80 published: 80 protocol: tcp mode: host - target: 443 published: 443 protocol: tcp mode: host - target: 443 published: 443 protocol: udp # for HTTP3 mode: host networks: - proxy volumes: - /opt/docker/traefik/traefik.yml:/etc/traefik/traefik_config.yml # main Traefik static configuration - /opt/docker/traefik/dynamic:/etc/traefik/dynamic # for Traefik dynamic configuration files - /opt/docker/acme:/acme # directory for certificate storage files - /opt/docker/traefik/log:/var/log - /var/run/docker.sock:/var/run/docker.sock:ro - /usr/share/zoneinfo/America/Sao_Paulo:/etc/localtime:ro # Change this to another or comment/remove to use UTC - /etc/timezone:/etc/timezone:ro # Comment/remove to use UTC environment: - TZ=America/Sao_Paulo # Change it to another or comment/remove to use UTC deploy: mode: global placement: constraints: - node.role==manager labels: - traefik.enable=true - traefik.http.routers.mydashboard.rule=Host(`traefik.example.net`) # for Traefik dashboard - traefik.http.routers.mydashboard.service=api@internal - traefik.http.routers.mydashboard.middlewares=traefik_auth,traefik_retry - traefik.http.services.mydashboard.loadbalancer.server.port=1337 - traefik.http.middlewares.traefik_retry.retry.attempts=3 - traefik.http.middlewares.traefik_retry.retry.initialinterval=200ms # How to generate a password hash: echo $(htpasswd -nB desired_username) | sed -e s/\\$/\\$\\$/g - traefik.http.middlewares.traefik_auth.basicauth.users=desired_username:PASTE_THE_PASSWORD_HASH_HERE resources: limits: cpus: "2" memory: 1g reservations: memory: 256m snac: image: codeberg.org/daltux/snac:2.82-dev_daltux3 hostname: '{{.Node.Hostname}}' restart: unless-stopped security_opt: - no-new-privileges:true volumes: - /opt/snac:/data networks: - proxy depends_on: - traefik environment: - TZ=America/Sao_Paulo # Change this to your own or comment/remove it to use UTC. deploy: mode: replicated replicas: 1 labels: - traefik.enable=true - traefik.http.services.snac.loadbalancer.server.port=8001 - traefik.http.routers.snac.rule=Host(`snac.example.net`) - traefik.http.routers.snac.priority=1 - traefik.http.routers.snac.middlewares=snac_headers@swarm,traefik_retry@swarm - "traefik.http.routers.snac_static.rule=Host(`snac.example.net`) && PathRegexp(`^/.+/s/.+`)" - "traefik.http.routers.snac_static.priority=2" - "traefik.http.routers.snac_static.middlewares=snac_headers@swarm,snac_cache_static@swarm,traefik_retry@swarm" - traefik.http.middlewares.snac_headers.headers.stsSeconds=31536000 - traefik.http.middlewares.snac_headers.headers.stsIncludeSubdomains=false - traefik.http.middlewares.snac_headers.headers.stsPreload=false - traefik.http.middlewares.snac_headers.headers.customFrameOptionsValue=SAMEORIGIN - traefik.http.middlewares.snac_headers.headers.contentTypeNosniff=true - traefik.http.middlewares.snac_headers.headers.browserXssFilter=true - traefik.http.middlewares.snac_headers.headers.referrerPolicy=strict-origin-when-cross-origin - "traefik.http.middlewares.snac_headers.headers.contentSecurityPolicy=default-src 'self'; base-uri 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; form-action 'self'; img-src https: data:; font-src 'self'; media-src https: data:; connect-src 'none'; frame-src 'none'; frame-ancestors 'none';" - traefik.http.middlewares.snac_cache_static.plugin.souin.api.souin=true - traefik.http.middlewares.snac_cache_static.plugin.souin.log_level=info - traefik.http.middlewares.snac_cache_static.plugin.souin.default_cache.ttl=1440m - traefik.http.middlewares.snac_cache_static.plugin.souin.default_cache.allowed_http_verbs=GET,HEAD - traefik.http.middlewares.snac_cache_static.plugin.souin.default_cache.stale=1h - traefik.http.middlewares.snac_cache_static.plugin.souin.default_cache.etag=true - "traefik.http.middlewares.snac_cache_static.plugin.souin.default_cache.default_cache_control=public, max-age=86400" resources: limits: cpus: "3" memory: 1g reservations: memory: 256m networks: proxy: name: proxy driver: overlay attachable: true external: true