I am a noob here trying to configure safe external access to various home services (jellyfin, homeassistant, etc.). I can’t figure out how to get Traefik to work properly, and I don’t know where in the process the issue is. The stripped down relevant pieces of my docker compose file is as follows:
networks:
mediastack:
name: mediastack
driver: bridge
ipam:
driver: default
config:
- subnet: ${DOCKER_SUBNET:?err}
gateway: ${DOCKER_GATEWAY:?err}
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
networks:
- mediastack
user: root
environment:
- TZ=${TIMEZONE:?err}
- CF_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN:?err}
ports:
- ${REVERSE_PROXY_PORT_HTTP:?err}:80
- ${REVERSE_PROXY_PORT_HTTPS:?err}:443
- ${WEBUI_PORT_TRAEFIK:?err}:8080
- ${METRICS_PORT_TRAEFIK:?err}:8082
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ${FOLDER_FOR_DATA:?err}/logs/traefik:/var/log
- ${FOLDER_FOR_DATA:?err}/traefik:/etc/traefik
- ${FOLDER_FOR_DATA:?err}/traefik/letsencrypt:/letsencrypt
labels:
- traefik.enable=true
# ROUTERS
- traefik.http.routers.traefik.service=api@internal
- traefik.http.routers.traefik.rule=Host(`traefik.${CLOUDFLARE_DNS_ZONE:?err}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
- traefik.http.routers.traefik.entrypoints=secureweb
- traefik.http.routers.traefik.middlewares=authentik-forwardauth@file,security-headers@file,traefik-bouncer@file
# SERVICES
- traefik.http.services.traefik.loadbalancer.server.scheme=http
- traefik.http.services.traefik.loadbalancer.server.port=8080
# MIDDLEWARES
traefik-certs-dumper:
image: ldez/traefik-certs-dumper:latest
container_name: traefik-certs-dumper
restart: always
networks:
- mediastack
user: ${PUID:?err}:${PGID:?err}
entrypoint: sh -c '
while ! [ -e /data/acme.json ]
|| ! [ `jq ".[] | .Certificates | length" /data/acme.json | jq -s "add" ` != 0 ]; do
sleep 1
; done
&& traefik-certs-dumper file --version v2 --watch
--source /data/acme.json --dest /certs'
volumes:
- ${FOLDER_FOR_DATA:?err}/traefik/letsencrypt:/data:ro
- ${FOLDER_FOR_DATA:?err}/traefik-certs-dumper:/certs
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
restart: always
networks:
- mediastack
user: ${PUID:?err}:${PGID:?err}
environment:
- TZ=${TIMEZONE:?err}
ports:
- 127.0.0.1:${CROWDSEC_PORT:?err}:8080
- 6060:6060 # Provides Metrics for Prometheus
- 7422:7422 # Provides WAF AppSec
depends_on:
- traefik
volumes:
- ${FOLDER_FOR_DATA:?err}/crowdsec:/etc/crowdsec
- ${FOLDER_FOR_DATA:?err}/crowdsec/data:/var/lib/crowdsec/data/
- ${FOLDER_FOR_DATA:?err}/logs:/logs:ro
postgresql:
image: docker.io/library/postgres:latest
container_name: postgresql
restart: unless-stopped
networks:
- mediastack
user: ${PUID:?err}:${PGID:?err}
ports:
- ${POSTGRESQL_PORT:?err}:5432
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
volumes:
- ${FOLDER_FOR_DATA:?err}/postgresql:/var/lib/postgresql
environment:
- TZ=${TIMEZONE:?err}
- POSTGRES_DB=${AUTHENTIK_DATABASE:?err}
- POSTGRES_USER=${POSTGRESQL_USERNAME:?err}
- POSTGRES_PASSWORD=${POSTGRESQL_PASSWORD:?err}
My .env includes:
WEBUI_PORT_TRAEFIK=8080
REVERSE_PROXY_PORT_HTTP=81
REVERSE_PROXY_PORT_HTTPS=5443
CROWDSEC_PORT=9080
METRICS_PORT_TRAEFIK=8083
I have 3 files related to Traefik (with my domain obscured below):
traefik-static.yaml
global:
checkNewVersion: true
sendAnonymousUsage: true
log:
level: INFO # Options are: TRACE , DEBUG , INFO , WARN , ERROR , FATAL , and PANIC
accessLog:
filePath: /var/log/access.log
format: json
api:
dashboard: true
insecure: true
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: secureweb
scheme: https
permanent: true
secureweb:
address: :443
http:
tls:
options: default
certResolver: letsencrypt
domains:
- main: example.com
sans:
- "*.example.com"
metrics:
address: :8083
metrics:
prometheus:
entryPoint: metrics
manualRouting: true
headerLabels:
useragent: User-Agent
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
providers:
docker:
exposedByDefault: false
file:
directory: /etc/traefik
watch: true
certificatesResolvers:
letsencrypt:
acme:
storage: /letsencrypt/acme.json
keyType: EC384
caServer: https://acme-v02.api.letsencrypt.org/directory
dnsChallenge:
provider: cloudflare
resolvers:
- 1.1.1.1:53
- 1.0.0.1:53
propagation:
delayBeforeChecks: 2s
experimental:
plugins:
crowdsec-bouncer-traefik-plugin:
moduleName:
version: v1.4.2
traefik-dynamic.yaml
tls:
stores:
default:
defaultGeneratedCert:
resolver: letsencrypt
domain:
main: ``example.com
sans:
- "*.example.com"
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true
http:
middlewares:
security-headers:
headers:
accessControlAllowCredentials: true
accessControlAllowHeaders: "*"
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlAllowOriginList:
- ``https://example.com
- https://*.example.com
accessControlMaxAge: 100
addVaryHeader: true
browserXssFilter: true
stsSeconds: 63072000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
frameDeny: true
customFrameOptionsValue: SAMEORIGIN
contentTypeNosniff: true
# contentSecurityPolicy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'none'
referrerPolicy: strict-origin-when-cross-origin
permissionsPolicy: camera=(), microphone=(), geolocation=(), payment=(), usb=()
authentik-forwardauth:
forwardAuth:
address: ``http://authentik:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- 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
traefik-bouncer:
plugin:
crowdsec-bouncer-traefik-plugin:
enabled: true
defaultDecisionSeconds: 60
crowdsecMode: live
crowdsecAppsecEnabled: false
crowdsecAppsecHost: crowdsec:7422
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: true
crowdsecLapiKey: j9beWrQh3moZwdLhr2u1vKzpxsyiDALtDKtZSTMeoWE
crowdsecLapiHost: crowdsec:8080
crowdsecLapiScheme: http
crowdsecLapiTLSInsecureVerify: false
forwardedHeadersTrustedIPs:
- ********/8
- ********/12
- ********/16
clientTrustedIPs:
- ********/8
- ********/12
- ********/16
and traefik-internal.yaml
http:
routers:
gateway: # Ubiquiti Dream Machine
rule: "Host(`example.com`)"
service: gateway
entryPoints:
- secureweb
tls:
certResolver: letsencrypt
middlewares:
- authentik-forwardauth@file
- security-headers@file
- traefik-bouncer@file
services:
gateway:
loadBalancer:
servers:
- url: "**********" # Ubiquiti Web UI - HTTPS
passHostHeader: true
serversTransport: insecure-no-verify
serversTransports:
insecure-no-verify:
insecureSkipVerify: true
I can run the containers, and pull up the Traefik web UI, which shows everything as working. When I jump onto the Traefik container and run traefik –ping healthcheckit is constantly saying that a port is in use and that it can’t create the entrypoint.
When I have the Traefik container up and running and do sudo lsof -i -P -n | grep :5443 or for 8083, I get multiple docker lines listening to the port.
![]()
Everytime I try and tweak something, it lists a different port as the issue, but I think the problem is that Traefik is duplicating many of the ports due to some issue in my configuration from one of the files above.
Is there something obvious I need to fix here? I tried so many different things at this point I hope I didn’t create new headaches for myself once this part is sorted out.