Problem Summary
I'm experiencing redirect loops and 404 errors when trying to access my Excalidraw service through Traefik. The service works internally https://excalidraw.local.mydomain.com
but fails when accessed via the public domain https://excalidraw.mydomain.com
.
Architecture
- Main Traefik: External-facing reverse proxy (handles public traffic & source of true) at
10.66.0.99
- Local Traefik: Internal services proxy (runs on TrueNAS server) at
10.66.0.100
- Excalidraw: Docker container running on TrueNAS at
10.66.0.100
Doing this away so i don't need to expose port on TrueNAS for Apps
Expected Behavior
- User visits
https://excalidraw.mydomain.com
- Main Traefik routes request to TrueNAS Traefik
https://excalidraw.local.mydomain.com
- TrueNAS Traefik get's Excalidraw APP
- Excalidraw interface loads correctly
Actual Behavior
- Main Traefik: Shows redirect loop (HTTP 301 responses)
- TrueNAS Traefik: Returns 404 errors for some requests
- Service is unreachable from external domain
Error Logs
Main Traefik (showing redirect loop):
10.66.0.99 - - [16/Sep/2025:10:46:49 +0000] "GET / HTTP/2.0" 301 17 "-" "-" 426 "excalidraw@file" "http://excalidraw.local.mydomain.com:80" 7ms 10.66.0.99 - - [16/Sep/2025:10:46:49 +0000] "GET / HTTP/2.0" 301 17 "-" "-" 427 "excalidraw@file" "http://excalidraw.local.mydomain.com:80" 8ms [repeated multiple times...]
TrueNAS Traefik (showing 404s):
10.66.0.100 - - [16/Sep/2025:10:38:32 +0000] "GET / HTTP/2.0" 404 19 "-" "-" 77 "-" "-" 0ms 10.20.0.100 - - [16/Sep/2025:10:38:32 +0000] "GET /favicon.ico HTTP/2.0" 404 19 "-" "-" 78 "-" "-" 0ms
Configuration Files
Main Traefik Configuration
docker-compose.yaml:
secrets:
cf-token:
file: ./cf-token
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
secrets:
- cf-token
env_file:
- .env
networks:
- proxy
ports:
- 80:80
- 81:81
- 443:443
- 444:444
environment:
- TRAEFIK_DASHBOARD_CREDENTIALS=${TRAEFIK_DASHBOARD_CREDENTIALS}
- CF_DNS_API_TOKEN_FILE=/run/secrets/cf-token
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /home/ubuntu/docker/traefik/traefik.yaml:/traefik.yaml:ro
- /home/ubuntu/docker/traefik/acme.json:/acme.json
- /home/ubuntu/docker/traefik/config.yaml:/config.yaml:ro
- /home/ubuntu/docker/traefik/logs:/var/log/traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.mydomain.com`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefikmydomain.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain.com"
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.mydomain.com"
- "traefik.http.routers.traefik-secure.service=api@internal"
networks:
proxy:
external: true
traefik.yaml:
api:
dashboard: true
debug: true
entryPoints:
http:
address: ":80"
http:
redirections:
entrypoint:
to: https
scheme: https
https:
address: ":443"
http-external:
address: ":81"
http:
redirections:
entrypoint:
to: https-external
scheme: https
https-external:
address: ":444"
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yaml
certificatesResolvers:
cloudflare:
acme:
caServer: acme-staging-v02.api.letsencrypt.org/directory
email: ...
storage: acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
log:
level: "INFO"
filePath: "/var/log/traefik/traefik.log"
accessLog:
filePath: "/var/log/traefik/access.log"
config.yaml:
http:
middlewares:
default-security-headers:
headers:
customBrowserXSSValue: 0
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: false
referrerPolicy: strict-origin-when-cross-origin
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 3153600
contentSecurityPolicy: default-src 'self'; script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src
'self' data:; connect-src 'self' wss:;
customRequestHeaders:
X-Forwarded-Proto: https
https-redirectscheme:
redirectScheme:
scheme: https
permanent: true
routers:
excalidraw:
entryPoints:
- https
rule: Host(`excalidraw.mydomain.com`)
middlewares:
- default-security-headers
- https-redirectscheme
tls: {}
service: excalidraw
services:
excalidraw:
loadBalancer:
servers:
- url: https://excalidraw.local.mydomain.com
passHostHeader: true
TrueNAS Traefik Configuration
docker-compose.yaml:
secrets:
cf-token:
file: ./cf-token
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
secrets:
- cf-token
env_file:
- .env
networks:
- proxy
ports:
- 80:80
- 81:81
- 443:443
- 444:444
environment:
- TRAEFIK_DASHBOARD_CREDENTIALS=${TRAEFIK_DASHBOARD_CREDENTIALS}
- CF_DNS_API_TOKEN_FILE=/run/secrets/cf-token
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /mnt/temp/apps/docker/traefik/traefik.yaml:/traefik.yaml:ro
- /mnt/temp/apps/docker/traefik/acme.json:/acme.json
- /mnt/temp/apps/docker/traefik/config.yaml:/config.yaml:ro
- /mnt/temp/apps/docker/traefik/logs:/var/log/traefik
labels:
- traefik.enable=true
- traefik.http.routers.traefik.entrypoints=http
- traefik.http.routers.traefik.rule=Host(`traefik.local.mydomain.com`)
- traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}
- traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https
- traefik.http.routers.traefik.middlewares=traefik-https-redirect
- traefik.http.routers.traefik-secure.entrypoints=https
- traefik.http.routers.traefik-secure.rule=Host(`traefik.local.mydomain.com`)
- traefik.http.routers.traefik-secure.middlewares=traefik-auth
- traefik.http.routers.traefik-secure.tls=true
- traefik.http.routers.traefik-secure.tls.certresolver=cloudflare
- traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain.com
- traefik.http.routers.traefik-secure.tls.domains[0].sans=*.local.mydomain.com
- traefik.http.routers.traefik-secure.service=api@internal
networks:
proxy:
external: true
traefik.yaml:
api:
dashboard: true
debug: true
entryPoints:
http:
address: :80
http:
middlewares:
- crowdsec-bouncer@file
redirections:
entrypoint:
to: https
scheme: https
https:
address: :443
http:
middlewares:
- crowdsec-bouncer@file
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: false
file:
filename: /config.yaml
certificatesResolvers:
cloudflare:
acme:
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
email: ...
storage: acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- 1.1.1.1:53
- 1.0.0.1:53
log:
level: INFO
filePath: /var/log/traefik/traefik.log
accessLog:
filePath: /var/log/traefik/access.log
config.yaml:
http:
middlewares:
default-security-headers:
headers:
customBrowserXSSValue: 0
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: false
referrerPolicy: strict-origin-when-cross-origin
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 3153600
contentSecurityPolicy: default-src 'self'
customRequestHeaders:
X-Forwarded-Proto: https
https-redirectscheme:
redirectScheme:
scheme: https
permanent: true
crowdsec-bouncer:
forwardauth:
address: http://bouncer-traefik:8080/api/v1/forwardAuth
trustForwardHeader: true
Excalidraw (Runing on TrueNAS)
docker-compose.yaml:
services:
excalidraw:
image: excalidraw/excalidraw:latest
container_name: excalidraw
restart: on-failure
security_opt:
- no-new-privileges:true
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.excalidraw.entrypoints=http
- traefik.http.routers.excalidraw.rule=Host(`excalidraw.local.mydomain.com`)
- traefik.http.middlewares.excalidraw-https-redirect.redirectscheme.scheme=https
- traefik.http.routers.excalidraw.middlewares=excalidraw-https-redirect
- traefik.http.routers.excalidraw-secure.entrypoints=https
- traefik.http.routers.excalidraw-secure.rule=Host(`excalidraw.local.mydomain.com`)
- traefik.http.routers.excalidraw-secure.tls=true
- traefik.http.routers.excalidraw-secure.service=excalidraw
- traefik.http.services.excalidraw.loadbalancer.server.port=80
- traefik.docker.network=proxy
networks:
proxy:
external: true
Questions
- Should I remove the
https-redirectscheme
middleware since I already have automatic redirect in entryPoints? - What should the service URL be - How should Main Traefik point to TrueNAS Traefik
- Do I need to configure the Excalidraw route on both Traefik instances or just one?
- Is there a network connectivity issue between the two Traefik instances?
Environment
- Traefik Version: Latest
- Docker Setup: Both Traefik instances running in Docker
- Network: Internal network
- SSL: Let's Encrypt via Cloudflare DNS challenge
Any help troubleshooting this setup would be greatly appreciated!