Compare commits

...

3 Commits

Author SHA1 Message Date
cebd955b3d 2025-11-10 11:34:56 +00:00
ea7a373bc4 Fix Traefik SSL certificate issues
- Fixed volume mount syntax for Swarm (use long-form bind mount syntax)
- Fixed Portainer TLS label syntax (tls.certresolver instead of tls.certificatesResolvers)
- These changes resolve SSL errors and certificate mounting issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 11:32:49 +00:00
3871e30abd Configure Traefik for public-facing access with frostlabs.me domains
- Fixed certificatesResolvers configuration in static.yml (moved out of tls section)
- Added DNS resolvers to Cloudflare ACME challenge configuration
- Added persistent volume mount for Let's Encrypt certificates
- Updated Outline service labels to use flow.frostlabs.me with proper cert resolver
- Updated Authentik service labels to use auth.frostlabs.me with proper cert resolver
- Added security headers and rate limiting middlewares to dynamic.yml
- Added example templates for public-facing service configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 11:27:47 +00:00
6 changed files with 73 additions and 22 deletions

View File

@@ -26,6 +26,19 @@ http:
- websecure - websecure
service: unraid service: unraid
tls: {} tls: {}
# Public-facing services (*.frostlabs.me)
# Example: To add a public service, uncomment and customize:
# my-public-service:
# rule: "Host(`myapp.frostlabs.me`)"
# entryPoints:
# - websecure
# service: my-service-name
# tls:
# certResolver: cloudflare
# middlewares:
# - authentik # Optional: Add authentication
# emby: # emby:
# rule: "Host(`movies.swarm.home`)" # rule: "Host(`movies.swarm.home`)"
# entryPoints: # entryPoints:
@@ -38,6 +51,7 @@ http:
# MIDDLEWARES SECTION # MIDDLEWARES SECTION
#----------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------
middlewares: middlewares:
# Authentik forward auth for protecting services
authentik: authentik:
forwardAuth: forwardAuth:
address: "http://authentik_server:9000/outpost.goauthentik.io/auth/traefik" address: "http://authentik_server:9000/outpost.goauthentik.io/auth/traefik"
@@ -48,3 +62,22 @@ http:
- X-authentik-email - X-authentik-email
- X-authentik-name - X-authentik-name
- X-authentik-uid - X-authentik-uid
# Security headers for public-facing services
security-headers:
headers:
frameDeny: true
browserXssFilter: true
contentTypeNosniff: true
sslRedirect: true
forceSTSHeader: true
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
# Rate limiting for public services
rate-limit:
rateLimit:
average: 100
period: 1s
burst: 50

View File

@@ -41,14 +41,16 @@ providers:
watch: true watch: true
# Certificate resolvers # Certificate resolvers
tls: certificatesResolvers:
certificatesResolvers: cloudflare:
cloudflare: acme:
acme: email: john.allisonwin@outlook.com
email: john.allisonwin@outlook.com storage: /certificates/acme.json
storage: /certificates/acme.json dnsChallenge:
dnsChallenge: provider: cloudflare
provider: cloudflare resolvers:
- 1.1.1.1:53
- 8.8.8.8:53
# Logging # Logging
log: log:

View File

@@ -40,9 +40,11 @@ services:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.swarm.network=homelab" - "traefik.swarm.network=homelab"
- "traefik.http.routers.outline.rule=Host(`flow.swarm.home`)" # Public-facing domain with Let's Encrypt certificate
- "traefik.http.routers.outline.rule=Host(`flow.frostlabs.me`)"
- "traefik.http.routers.outline.entrypoints=websecure" - "traefik.http.routers.outline.entrypoints=websecure"
- "traefik.http.routers.outline.tls=true" - "traefik.http.routers.outline.tls=true"
- "traefik.http.routers.outline.tls.certresolver=cloudflare"
- "traefik.http.services.outline.loadbalancer.server.port=3000" - "traefik.http.services.outline.loadbalancer.server.port=3000"
depends_on: depends_on:
- redis - redis

View File

@@ -61,9 +61,11 @@ services:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.swarm.network=homelab" - "traefik.swarm.network=homelab"
# Public-facing domain with Let's Encrypt certificate
- "traefik.http.routers.authentik.rule=Host(`auth.frostlabs.me`)" - "traefik.http.routers.authentik.rule=Host(`auth.frostlabs.me`)"
- "traefik.http.routers.authentik.entrypoints=websecure" - "traefik.http.routers.authentik.entrypoints=websecure"
- "traefik.http.routers.authentik.tls=certificatesResolvers=cloudflare" - "traefik.http.routers.authentik.tls=true"
- "traefik.http.routers.authentik.tls.certresolver=cloudflare"
- "traefik.http.services.authentik.loadbalancer.server.port=9000" - "traefik.http.services.authentik.loadbalancer.server.port=9000"
depends_on: depends_on:

View File

@@ -14,9 +14,11 @@ services:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.swarm.network=homelab" - "traefik.swarm.network=homelab"
# Public-facing domain with Let's Encrypt certificate
- "traefik.http.routers.portainer.rule=Host(`portainer.frostlabs.me`)" - "traefik.http.routers.portainer.rule=Host(`portainer.frostlabs.me`)"
- "traefik.http.routers.portainer.entrypoints=websecure" - "traefik.http.routers.portainer.entrypoints=websecure"
- "traefik.http.routers.portainer.tls.certificatesResolvers=cloudflare" - "traefik.http.routers.portainer.tls=true"
- "traefik.http.routers.portainer.tls.certresolver=cloudflare"
- "traefik.http.services.portainer.loadbalancer.server.port=9000" - "traefik.http.services.portainer.loadbalancer.server.port=9000"
agent: agent:

View File

@@ -9,10 +9,20 @@ services:
environment: environment:
- CF_DNS_API_TOKEN_FILE=/run/secrets/cloudflare_api_token - CF_DNS_API_TOKEN_FILE=/run/secrets/cloudflare_api_token
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - type: bind
# source: /var/run/docker.sock
- /home/doc/projects/swarm/conf/traefik-conf/static.yml:/etc/traefik/traefik.yml:ro target: /var/run/docker.sock
- /home/doc/projects/swarm/conf/traefik-conf/dynamic.yml:/etc/traefik/dynamic/dynamic.yml:rw read_only: true
- type: bind
source: /home/doc/projects/swarm/conf/traefik-conf/static.yml
target: /etc/traefik/traefik.yml
read_only: true
- type: bind
source: /home/doc/projects/swarm/conf/traefik-conf/dynamic.yml
target: /etc/traefik/dynamic/dynamic.yml
- type: bind
source: /home/doc/projects/swarm-data/appdata/traefik/certificates/acme.json
target: /certificates/acme.json
secrets: secrets:
- cloudflare_api_token - cloudflare_api_token
networks: networks:
@@ -28,7 +38,7 @@ services:
replicas: 1 replicas: 1
placement: placement:
constraints: constraints:
- node.hostname == p0 - node.hostname == p0
networks: networks:
homelab: homelab: