One traefik with two differents proxmox servers?

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.