Hello,
Today I have two proxmox servers (server A and B) on the same network.
On both server, I do have dockers running. Only one (serverA) is running Traefik v3.4.4.
On serverA, I only have Traefik (access external services - web server and homeassistant) and the docker code-server running all well. On the serverB I have dockers like Authentik, uptime-kuma running. How to make traefik managing dockers on both servers ?
Thx
Join the servers to a Docker Swarm and use providers.swarm.
Or manually use a dynamic config file.
Recent Traefik even allows loadbalancer.server.url on labels.
Hello, I will choose the dynamic config file from Traefik.
At the moment I am trying to make working "uptime-kuma" to test the config. Of course, it doesn't work. I do have a Gateway time-out error 504. It make sense because how do you manage the local docker networks ? Traefik can use the local docker network of the serverA but not on the serverB anymore where uptime-kuma docker is.
If you want Traefik to proxy/forward requests to a target service on another host, it needs to be able to connect.
So the target service needs to publish ports outside of the local Docker network.
Docker Swarm is the alternative, because it can create Docker overlay networks, that span across multiple nodes.
Hello, things are working except for Authentik where have a 404 error.
services:
postgresql:
image: docker.io/library/postgres:16-alpine
container_name: authentik-postgresql
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
volumes:
- $BASE/authentik1/database:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASS}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_DB: ${POSTGRES_DB}
user: "${UID}:${GID}"
networks:
- intern_net
- ext_net
redis:
image: docker.io/library/redis:alpine
container_name: authentik-redis
command: -- save 60 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
user: "${UID}:${GID}"
volumes:
- $BASE/authentik1/redis/data:/data
networks:
- ext_net
- intern_net
server:
image: ghcr.io/goauthentik/server:2025.6.3
container_name: authentik-server
restart: unless-stopped
command: server
user: "${UID}:${GID}"
mem_limit: 4G
ports:
- "${COMPOSE_PORT_HTTP:-9001}:9001"
- "${COMPOSE_PORT_HTTPS:-9443}:9443"
cpuset: 0-0
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${POSTGRES_USER}
AUTHENTIK_POSTGRESQL__NAME: ${POSTGRES_DB}
AUTHENTIK_POSTGRESQL__PASSWORD: ${POSTGRES_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_ERROR_REPORTING__ENABLED: true
AUTHENTIK_EMAIL__HOST: ${AUTHENTIK_EMAIL__HOST}
AUTHENTIK_EMAIL__PORT: ${AUTHENTIK_EMAIL__PORT}
AUTHENTIK_EMAIL__USERNAME: ${AUTHENTIK_EMAIL__USERNAME}
AUTHENTIK_EMAIL__PASSWORD: ${AUTHENTIK_EMAIL__PASSWORD}
AUTHENTIK_EMAIL__USE_TLS: ${AUTHENTIK_EMAIL__USE_TLS}
AUTHENTIK_EMAIL__USE_SSL: ${AUTHENTIK_EMAIL__USE_SSL}
AUTHENTIK_EMAIL__TIMEOUT: ${AUTHENTIK_EMAIL__TIMEOUT}
AUTHENTIK_EMAIL__FROM: ${AUTHENTIK_EMAIL__FROM}
volumes:
- $BASE/authentik1/media:/media
- $BASE/authentik1/custom-templates:/templates
labels:
- "traefik.enable=true"
#- "traefik.http.services.authentik.loadbalancer.server.port=9001"
- "traefik.http.routers.authentik.entrypoints=https-external"
- "traefik.http.routers.authentik.rule=Host(`authentik.ext_net.org`)"
- "traefik.http.routers.authentik.tls=true"
- "traefik.http.routers.authentik.tls.certresolver=dns-cloudflare"
- "traefik.http.routers.authentik.service=authentik"
- "traefik.http.routers.authentik-outpost.rule=Host(`authentik.ext_net.org`)"
- "traefik.http.routers.authentik-outpost.entrypoints=https-external"
- "traefik.http.routers.authentik-outpost.tls=true"
- "traefik.http.routers.authentik-outpost.tls.certresolver=dns-cloudflare"
- "traefik.docker.network=ext_net"
depends_on:
- postgresql
- redis
networks:
- ext_net
- intern_net
worker:
image: ghcr.io/goauthentik/server:2025.6.3
container_name: authentik-worker
restart: unless-stopped
command: worker
#- '--host=tcp://worker-docker-socket-proxy:2375'
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${POSTGRES_USER}
AUTHENTIK_POSTGRESQL__NAME: ${POSTGRES_DB}
AUTHENTIK_POSTGRESQL__PASSWORD: ${POSTGRES_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_ERROR_REPORTING__ENABLED: true
user: root
volumes:
#- /var/run/docker.sock:/var/run/docker.sock
- $BASE/authentik1/media:/media
- $BASE/authentik1/certs:/certs
- $BASE/authentik1/custom-templates:/templates
depends_on:
- postgresql
- redis
- dockerproxy
networks:
- ext_net
- socket-worker
- intern_net
dockerproxy:
image: wollomatic/socket-proxy:1.7.0
read_only: true
container_name: worker-docker-socket-proxy
restart: unless-stopped
user: 65534:110 # change group 999 to docker gid
mem_limit: 128M
cap_drop:
- ALL
security_opt:
- no-new-privileges
command:
- -loglevel=info # change to info in prod
- -allowfrom=*
- -listenip=0.0.0.0
- -shutdowngracetime=5
- -allowGET=/containers/.*
- -watchdoginterval=600
- -stoponwatchdog
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket-worker
geoipupdate:
image: maxmindinc/geoipupdate:v7.1
container_name: geoipupdate
restart: unless-stopped
networks:
- ext_net
- intern_net
volumes:
- $BASE/authentik1/geoip/data:/usr/share/GeoIP
environment:
GEOIPUPDATE_EDITION_IDS: ${GEOIPUPDATE_EDITION_IDS}
GEOIPUPDATE_FREQUENCY: ${GEOIPUPDATE_FREQUENCY}
GEOIPUPDATE_ACCOUNT_ID: ${GEOIPUPDATE_ACCOUNT_ID}
GEOIPUPDATE_LICENSE_KEY: ${GEOIPUPDATE_LICENSE_KEY}
#- GEOIPUPDATE_VERBOSE=1 #for debugging shows output in "docker compose up" logs
volumes:
geoip:
driver: local
database:
driver: local
redis:
driver: local
networks:
ext_net:
external: true
socket-worker:
driver: bridge
internal: true
intern_net:
driver: bridge
internal: true
My dynamic file:
http:
middlewares:
default-whitelist:
ipWhiteList:
sourceRange:
- 173.245.48.0/20
- 103.21.244.0/22
- 103.22.200.0/22
- 103.31.4.0/22
- 141.101.64.0/18
- 108.162.192.0/18
- 190.93.240.0/20
- 188.114.96.0/20
- 197.234.240.0/22
- 198.41.128.0/17
- 162.158.0.0/15
- 104.16.0.0/13
- 104.24.0.0/14
- 172.64.0.0/13
- 131.0.72.0/22
- 2400:cb00::/32
- 2606:4700::/32
- 2803:f800::/32
- 2405:b500::/32
- 2405:8100::/32
- 2a06:98c0::/29
- 2c0f:f248::/32
https-redirectscheme:
redirectScheme:
scheme: https
permanent: true
secured:
chain:
middlewares:
- default-whitelist
crowdsec-bouncer:
forwardauth:
address: http://bouncer-traefik:8080/api/v1/forwardAuth
trustForwardHeader: true
# https://github.com/goauthentik/authentik/issues/2366
authentik:
forwardAuth:
address: "http://ip_proxmox_server:9001/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-entitlements
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
my-traefik-get-real-ip:
plugin:
traefik-get-real-ip:
Proxy:
- proxyHeadername: X-From-Cdn
proxyHeadervalue: cdn1
realIP: X-Forwarded-For
- proxyHeadername: X-From-Cdn
proxyHeadervalue: cdn2
realIP: Client-Ip
- overwriteXFF: "true"
proxyHeadername: X-From-Cdn
proxyHeadervalue: cdn3
realIP: Cf-Connecting-Ip
- proxyHeadername: '*'
realIP: RemoteAddr
#region routers
routers:
authentik:
entryPoints:
- "https-external"
rule: "Host(`authentik.domain.org`) && PathPrefix(`/outpost.goauthentik.io/`)"
priority: 15
service: authentik
secure-webserver:
entryPoints:
- "https-external"
rule: "Host(`www.domain.org`)"
middlewares:
- https-redirectscheme
tls: {}
service: secure-webserver
blogger:
entryPoints:
- "https-external"
rule: "Host(`blogger.domain.org`)"
middlewares:
- https-redirectscheme
#- authentik
tls: {}
service: blogger
homeassistant:
entryPoints:
- "https-external"
rule: "Host(`haoss.domain.org`)"
middlewares:
- https-redirectscheme
#- authentik
tls: {}
service: homeassistant
homeassistant-r:
entryPoints:
- "http-external"
rule: "Host(`remote-ha.domain.org`)"
middlewares:
- https-redirectscheme
#- authentik
tls: {}
service: homeassistant-r
uptime-kuma:
entryPoints:
- "https-external"
rule: "Host(`uptime-kuma.domain.org`)"
middlewares:
- https-redirectscheme
- authentik
tls: {}
service: uptime-kuma
gotify:
entryPoints:
- "https-external"
rule: "Host(`gotify.domain.org`)"
middlewares:
- https-redirectscheme
#- authentik
tls: {}
service: gotify
it-tools:
entryPoints:
- "https-external"
rule: "Host(`it-tools.domain.org`)"
middlewares:
- https-redirectscheme
#- authentik
tls: {}
service: it-tools
immich:
entryPoints:
- "https-external"
rule: "Host(`immich.domain.org`)"
middlewares:
- https-redirectscheme
#- authentik
tls: {}
service: immich
#region services
services:
# service Proxmox
# service web
authentik:
loadBalancer:
servers:
- url: "http://ip_proxmox_server:9001/outpost.goauthentik.io"
secure-webserver:
loadBalancer:
servers:
- url: "http://XXX.XXX.XXX.28:80"
passHostHeader: true
blogger:
loadBalancer:
servers:
- url: "http://XXX.XXX.XXX.28"
passHostHeader: true
homeassistant:
loadBalancer:
servers:
- url: "http://XXX.XXX.XXX.26:8123"
passHostHeader: true
homeassistant-r:
loadBalancer:
servers:
- url: "http://XXX.XXX.XXX.61:8123"
passHostHeader: true
uptime-kuma:
loadBalancer:
servers:
- url: "http://ip_proxmox_server:3001"
passHostHeader: true
gotify:
loadBalancer:
servers:
- url: "http://ip_proxmox_server:8084"
passHostHeader: true
it-tools:
loadBalancer:
servers:
- url: "http://ip_proxmox_server:8080"
passHostHeader: true
immich:
loadBalancer:
servers:
- url: "http://ip_proxmox_server:2283"
passHostHeader: true
# services servitudes
From the previous config, I have add the published ports number in the Authentik config file:
ports:
- "${COMPOSE_PORT_HTTP:-9001}:9001"
- "${COMPOSE_PORT_HTTPS:-9443}:9443"
And replace (removed the docker name) the URL of the authentik services in the Traefik dynamic file:
authentik:
forwardAuth:
address: "http://ip_proxmox_server:9001/outpost.goauthentik.io/auth/traefik"
and
authentik:
loadBalancer:
servers:
- url: "http://ip_proxmox_server:9001/outpost.goauthentik.io"
Thx
You can’t have two similar:
How should Traefik know which one to use?
You probably need one extended by path:
Host() && PathPrefix()
labels:
- "traefik.enable=true"
#- "traefik.port: 9001"
#- "traefik.http.services.authentik.loadbalancer.server.port=9001"
- "traefik.http.routers.authentik.entrypoints=https-external"
- "traefik.http.routers.authentik.rule=Host(`authentik.domain.org`) && PathPrefix(`/`)"
- "traefik.http.routers.authentik.tls=true"
- "traefik.http.routers.authentik.tls.certresolver=dns-cloudflare"
- "traefik.http.routers.authentik.service=authentik"
- "traefik.http.routers.authentik-outpost.rule=Host(`authentik.domain.org`) && PathPrefix(`/outpost.goauthentik.io/`)"
- "traefik.http.routers.authentik-outpost.entrypoints=https-external"
- "traefik.http.routers.authentik-outpost.tls=true"
- "traefik.http.routers.authentik-outpost.tls.certresolver=dns-cloudflare"
- "traefik.docker.network=proxy"
Still 404
Thinking about it, why even have two routers on one container, when they go to the same port?
Enable and check Traefik access log in JSON format (doc), what’s the output during requests?
{"ClientAddr":"104.23.217.3:24886","ClientHost":"104.23.217.3","ClientPort":"24886","ClientUsername":"-","DownstreamContentSize":19,"DownstreamStatus":404,"Duration":30097,"GzipRatio":0,"OriginContentSize":0,"OriginDuration":0,"OriginStatus":0,"Overhead":30097,"RequestAddr":"authentik.domain.org","RequestContentSize":0,"RequestCount":163832,"RequestHost":"authentik.domain.org","RequestMethod":"GET","RequestPath":"/if/flow/initial-setup","RequestPort":"-","RequestProtocol":"HTTP/2.0","RequestScheme":"https","RetryAttempts":0,"StartLocal":"2025-07-22T17:31:20.509247985+03:00","StartUTC":"2025-07-22T14:31:20.509247985Z","TLSCipher":"TLS_CHACHA20_POLY1305_SHA256","TLSVersion":"1.3","entryPointName":"https-external","level":"info","msg":"","time":"2025-07-22T17:31:20+03:00"}
{"ClientAddr":"104.23.223.32:14584","ClientHost":"104.23.223.32","ClientPort":"14584","ClientUsername":"-","DownstreamContentSize":19,"DownstreamStatus":404,"Duration":45010,"GzipRatio":0,"OriginContentSize":0,"OriginDuration":0,"OriginStatus":0,"Overhead":45010,"RequestAddr":"authentik.domain.org","RequestContentSize":0,"RequestCount":163834,"RequestHost":"authentik.domain.org","RequestMethod":"GET","RequestPath":"/","RequestPort":"-","RequestProtocol":"HTTP/2.0","RequestScheme":"https","RetryAttempts":0,"StartLocal":"2025-07-22T17:31:34.829038808+03:00","StartUTC":"2025-07-22T14:31:34.829038808Z","TLSCipher":"TLS_CHACHA20_POLY1305_SHA256","TLSVersion":"1.3","entryPointName":"https-external","level":"info","msg":"","time":"2025-07-22T17:31:34+03:00"}
means the error does not come from the target service, but only from Traefik itself.
Check Traefik dashboard or debug log if the router is recognized.
Router details:
rule:
Host(authentik.domain.org) && PathPrefix(/outpost.goauthentik.io/)
Name:
authentik@file
EntryPoints:
https-external
Service:
Authentik
Priority:
15
There is no TLS configured
RequestPath doesn’t match. So it seems no matching router is found by Traefik. So the request is not forwarded/proxied anywhere.
The router doesn’t need any TLS if it’s already set on the entrypoint.
Hi, I have move authentik to the same server than Traefik.
It worked.
Thx a lot for your big effort.