Traefik v3 changed HostRegexp syntax from named capture groups to standard regex. Added low priority to avoid matching specific routes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
159 lines
3.7 KiB
YAML
159 lines
3.7 KiB
YAML
log:
|
|
level: INFO
|
|
|
|
entryPoints:
|
|
web:
|
|
# http
|
|
address: ':80'
|
|
http:
|
|
# https://doc.traefik.io/traefik/routing/entrypoints/#entrypoint
|
|
redirections:
|
|
entryPoint:
|
|
to: web-secure
|
|
|
|
web-secure:
|
|
# https
|
|
address: ':443'
|
|
|
|
flower:
|
|
address: ':5555'
|
|
|
|
certificatesResolvers:
|
|
letsencrypt:
|
|
# https://doc.traefik.io/traefik/https/acme/#lets-encrypt
|
|
acme:
|
|
email: 'admin@smoothschedule.com'
|
|
storage: /etc/traefik/acme/acme.json
|
|
# HTTP challenge for individual domains
|
|
httpChallenge:
|
|
entryPoint: web
|
|
|
|
letsencrypt-dns:
|
|
# DNS challenge for wildcard certificates (*.smoothschedule.com)
|
|
acme:
|
|
email: 'admin@smoothschedule.com'
|
|
storage: /etc/traefik/acme/acme.json
|
|
dnsChallenge:
|
|
provider: cloudflare
|
|
resolvers:
|
|
- "1.1.1.1:53"
|
|
- "8.8.8.8:53"
|
|
|
|
http:
|
|
routers:
|
|
# Main domain and www
|
|
web-secure-router:
|
|
rule: 'Host(`smoothschedule.com`) || Host(`www.smoothschedule.com`)'
|
|
entryPoints:
|
|
- web-secure
|
|
middlewares:
|
|
- csrf
|
|
service: nginx
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
# Platform subdomain (admin dashboard)
|
|
platform-router:
|
|
rule: 'Host(`platform.smoothschedule.com`)'
|
|
entryPoints:
|
|
- web-secure
|
|
middlewares:
|
|
- csrf
|
|
service: nginx
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
# API subdomain
|
|
api-router:
|
|
rule: 'Host(`api.smoothschedule.com`)'
|
|
entryPoints:
|
|
- web-secure
|
|
middlewares:
|
|
- csrf
|
|
service: django
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
# Email autoconfiguration subdomains
|
|
# These need host rewriting because Django's tenant middleware doesn't recognize them
|
|
autoconfig-router:
|
|
rule: 'Host(`autoconfig.smoothschedule.com`)'
|
|
entryPoints:
|
|
- web-secure
|
|
middlewares:
|
|
- email-autoconfig-host
|
|
service: django
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
autodiscover-router:
|
|
rule: 'Host(`autodiscover.smoothschedule.com`)'
|
|
entryPoints:
|
|
- web-secure
|
|
middlewares:
|
|
- email-autoconfig-host
|
|
service: django
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
# Wildcard subdomain router for tenant subdomains
|
|
# Uses DNS challenge for wildcard certificate (*.smoothschedule.com)
|
|
# Routes to nginx which serves the frontend SPA and proxies /api/ to Django
|
|
subdomain-router:
|
|
rule: 'HostRegexp(`^[a-z0-9-]+\\.smoothschedule\\.com$`)'
|
|
priority: 1
|
|
entryPoints:
|
|
- web-secure
|
|
middlewares:
|
|
- csrf
|
|
service: nginx
|
|
tls:
|
|
certResolver: letsencrypt-dns
|
|
domains:
|
|
- main: "smoothschedule.com"
|
|
sans:
|
|
- "*.smoothschedule.com"
|
|
|
|
flower-secure-router:
|
|
rule: 'Host(`smoothschedule.com`)'
|
|
entryPoints:
|
|
- flower
|
|
service: flower
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
middlewares:
|
|
csrf:
|
|
# https://doc.traefik.io/traefik/master/middlewares/http/headers/#hostsproxyheaders
|
|
# https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
|
|
headers:
|
|
hostsProxyHeaders: ['X-CSRFToken']
|
|
|
|
email-autoconfig-host:
|
|
# Rewrite Host header so Django tenant middleware routes to API/public schema
|
|
headers:
|
|
customRequestHeaders:
|
|
Host: 'api.smoothschedule.com'
|
|
|
|
services:
|
|
django:
|
|
loadBalancer:
|
|
servers:
|
|
- url: http://django:5000
|
|
|
|
flower:
|
|
loadBalancer:
|
|
servers:
|
|
- url: http://flower:5555
|
|
|
|
nginx:
|
|
loadBalancer:
|
|
servers:
|
|
- url: http://nginx:80
|
|
|
|
providers:
|
|
# https://doc.traefik.io/traefik/master/providers/file/
|
|
file:
|
|
filename: /etc/traefik/traefik.yml
|
|
watch: true
|