feat: add Traefik as alternative reverse proxy (--profile traefik)#1224
feat: add Traefik as alternative reverse proxy (--profile traefik)#1224lraphael wants to merge 1 commit intocoleam00:devfrom
Conversation
Add Traefik v3 as an alternative to Caddy for HTTPS reverse proxying. The existing --profile cloud (Caddy) remains unchanged — Traefik is purely additive via --profile traefik. - Add traefik.yml (static config) and traefik-dynamic.yml (middlewares) - Add traefik service to docker-compose.yml with separate profile - Add Traefik labels to app and auth-service containers - Update auth-service /verify to use absolute redirects (X-Forwarded-Host) so it works behind both Caddy and Traefik - Document Traefik-specific env vars (ACME_EMAIL, TRAEFIK_BASIC_AUTH) in .env.example Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis pull request introduces Traefik as an alternative reverse proxy option for cloud deployments alongside the existing Caddy setup. It adds static and dynamic Traefik configuration files, Docker Compose service definitions with routing labels, updates environment documentation, and modifies the auth-service redirect logic to use absolute URLs with protocol and host headers. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Traefik
participant AuthService
participant AppService
Client->>Traefik: HTTP/HTTPS request (Host: domain)
alt Authentication Required (Form-Auth)
Traefik->>AuthService: forwardAuth to /verify
AuthService-->>Traefik: Unauthenticated? Redirect to login
Traefik-->>Client: 302 to login page
Client->>AuthService: POST login credentials
AuthService-->>Client: Set auth cookie
end
Client->>Traefik: Authenticated request
Traefik->>AppService: Route to backend (port 3000)
AppService-->>Traefik: Response
Traefik-->>Client: Response + security headers
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
traefik-dynamic.yml (1)
7-14: Good security header configuration.The security headers follow best practices:
- HSTS with 1-year max-age and
includeSubDomainsX-Frame-Options: DENYprevents clickjacking- Server header cleared to reduce information disclosure
Optional enhancement: Consider adding
preloadto the HSTS header if you plan to submit the domain to the HSTS preload list:Strict-Transport-Security: "max-age=31536000; includeSubDomains; preload"This is only recommended after confirming HTTPS works correctly across all subdomains.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@traefik-dynamic.yml` around lines 7 - 14, The Strict-Transport-Security header under the security-headers -> headers -> customResponseHeaders currently uses "max-age=31536000; includeSubDomains"; if you plan to enroll the site in the HSTS preload list, update the Strict-Transport-Security value to include "; preload" (e.g., append preload to the existing directive) in the configuration for security-headers so the header becomes max-age=31536000; includeSubDomains; preload; confirm HTTPS works across all subdomains before making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@traefik-dynamic.yml`:
- Around line 7-14: The Strict-Transport-Security header under the
security-headers -> headers -> customResponseHeaders currently uses
"max-age=31536000; includeSubDomains"; if you plan to enroll the site in the
HSTS preload list, update the Strict-Transport-Security value to include ";
preload" (e.g., append preload to the existing directive) in the configuration
for security-headers so the header becomes max-age=31536000; includeSubDomains;
preload; confirm HTTPS works across all subdomains before making this change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 77dc5fe8-5f51-4752-aea2-42733bad6c79
📒 Files selected for processing (5)
.env.exampleauth-service/server.jsdocker-compose.ymltraefik-dynamic.ymltraefik.yml
|
Related to #1174 — overlapping area or partial fix. |
Motivation
Caddy is a great default for simple setups, but many self-hosters and teams already run Traefik as their central reverse proxy — it's the most widely used cloud-native reverse proxy in the Docker/Kubernetes ecosystem (30k+ GitHub stars, default in tools like Portainer, Rancher, and most Docker Compose template collections).
Adding Traefik as an option means users don't have to run two reverse proxies or maintain custom Traefik-to-Caddy forwarding rules. It also brings:
This PR is purely additive — the existing
--profile cloud(Caddy) is completely unchanged. No breaking changes.Summary
--profile traefiktraefik.yml(static config: entrypoints, Let's Encrypt ACME, Docker provider)traefik-dynamic.yml(middlewares: security headers, compression, basic auth, form auth)appandauth-servicecontainers indocker-compose.ymlauth-service/server.js/verifyendpoint to use absolute redirects viaX-Forwarded-Host/X-Forwarded-Proto— required for Traefik compatibility, still works with CaddyACME_EMAIL,TRAEFIK_BASIC_AUTH) in.env.exampleUsage
Traefik requires
DOMAINandACME_EMAILset in.env.Auth support
Both authentication options work with both proxies:
CADDY_BASIC_AUTHin.envTRAEFIK_BASIC_AUTH+ middleware intraefik-dynamic.yml--profile auth)forward_authin CaddyfileforwardAuthmiddleware + labelsTest plan
docker compose configvalidates for all 8 profile combinations/api/health)--profile cloudauth-service/server.jsSummary by CodeRabbit
New Features
Bug Fixes
Documentation