Files
the-other-dude/infrastructure/reverse-proxy-examples/traefik/traefik-dynamic.yaml.example

94 lines
3.3 KiB
Plaintext

# The Other Dude — Traefik dynamic configuration example
#
# This config assumes:
# - TOD frontend runs on FRONTEND_HOST:3000
# - TOD API runs on API_HOST:8001
# - WinBox worker Xpra ports are on WORKER_HOST:10100-10119
# - Traefik entrypoints: web (80) and websecure (443)
#
# Replace tod.example.com and upstream addresses with your values.
#
# For Docker-based Traefik, labels can replace this file.
# This example uses file provider for clarity.
http:
routers:
# ── Xpra (Remote WinBox) ────────────────────────────────────────
# Must be higher priority than the frontend catch-all.
# Each Xpra port needs its own service since Traefik doesn't
# support dynamic port extraction from path regex.
# Shown for port 10100; duplicate for 10101-10119 as needed.
tod-xpra-10100:
rule: "Host(`tod.example.com`) && PathPrefix(`/xpra/10100/`)"
entryPoints: [websecure]
service: tod-xpra-10100
middlewares: [xpra-strip, xpra-headers]
tls:
certResolver: letsencrypt
priority: 30
# ── API ─────────────────────────────────────────────────────────
tod-api:
rule: "Host(`tod.example.com`) && PathPrefix(`/api/`)"
entryPoints: [websecure]
service: tod-api
middlewares: [security-headers]
tls:
certResolver: letsencrypt
priority: 20
# ── Frontend (SPA) ──────────────────────────────────────────────
tod-frontend:
rule: "Host(`tod.example.com`)"
entryPoints: [websecure]
service: tod-frontend
middlewares: [security-headers]
tls:
certResolver: letsencrypt
priority: 10
services:
tod-xpra-10100:
loadBalancer:
servers:
- url: "http://YOUR_TOD_HOST:10100"
# Add tod-xpra-10101 through tod-xpra-10119 as needed
tod-api:
loadBalancer:
servers:
- url: "http://YOUR_TOD_HOST:8001"
tod-frontend:
loadBalancer:
servers:
- url: "http://YOUR_TOD_HOST:3000"
middlewares:
xpra-strip:
# Strip /xpra/{port} prefix before forwarding
stripPrefixRegex:
regex: ["^/xpra/[0-9]+"]
xpra-headers:
headers:
# Relaxed CSP for Xpra HTML5 client (inline scripts + eval)
customResponseHeaders:
Content-Security-Policy: "default-src 'self' 'unsafe-inline' 'unsafe-eval' ws: wss: data: blob:; frame-ancestors 'self';"
X-Content-Type-Options: "nosniff"
# IMPORTANT: Disable compression for Xpra — compressing WebSocket
# binary frames corrupts mouse/keyboard coordinate data.
security-headers:
headers:
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: "strict-origin-when-cross-origin"
customResponseHeaders:
X-Frame-Options: "SAMEORIGIN"
# IMPORTANT: Disable Traefik's built-in compression for Xpra routes.
# If using --entrypoints.websecure.http.middlewares=compress@...,
# exclude the xpra router or WebSocket binary frames will be corrupted.