Traefik
This guide on Traefik will demonstrate how the application is set up and how to use this reverse proxy tool. The examples used in this document are basic configurations. This set‑up includes using Authelia as middleware.
INFO
Traefik is a leading modern reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically.
First, ensure that you have created a custom Docker network; we will discuss why this is the preferred method further into the guide. For this example, we will use the custom Docker network called "proxy".
docker network create proxyLet's create the folder to add this Compose file to. You might save your app's data in another location, so adjust the path accordingly.
mkdir -p /opt/appdata/traefikTraefik needs a file called acme.json to store the SSL certificate information, and this needs to be secure. We'll create this file and change the permissions accordingly.
touch /opt/appdata/traefik/acme.json; chmod 600 /opt/appdata/traefik/acme.jsonDocker Compose
WARNING
It is crucial all containers used with Traefik share a common network. In this case proxy is being used. They must all be defined under networks: at the bottom of each Compose file.
version: "3"
services:
traefik:
container_name: traefik
image: traefik:latest
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/appdata/traefik/files:/etc/traefik/
networks:
- proxy
labels:
traefik.enable: true
traefik.http.routers.api.rule: Host(`traefik.DOMAIN.COM`)
traefik.http.routers.api.entryPoints: https
traefik.http.routers.api.service: api@internal
traefik.http.routers.api.middlewares: auth@file
environment:
CF_DNS_API_TOKEN: CLOUDFLARE_API_KEY_HERE # required when Let's Encrypt cannot contact the IP to verify the domain
restart: unless-stopped
networks:
proxy:
driver: bridge
external: trueTraefik Configuration
A configuration file called traefik.yml can be created. This will host most of the configuration needed for Traefik to run. Any changes to this file will require the container to be restarted for them to apply. Once this configuration is set, it is uncommon for it to be edited very frequently.
global:
checkNewVersion: true
sendAnonymousUsage: false
serversTransport:
insecureSkipVerify: true
forwardingTimeouts:
dialTimeout: 1s
entryPoints:
# Not used in apps, but redirect everything from HTTP to HTTPS
http:
address: :80
forwardedHeaders:
trustedIPs: &trustedIps
- 100.64.0.0/10 # Tailscale network
- 172.19.0.0/16 # Docker network
- 173.245.48.0/20 # List of CF IPs
- 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/12
- 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
http:
redirections:
entryPoint:
to: https
scheme: https
# HTTPS endpoint, with domain wildcard
https:
address: :443
forwardedHeaders:
trustedIPs: *trustedIps
http:
tls:
certResolver: letsencrypt
domains:
- main: domain.xyz
sans:
- '*.domain.xyz'
- main: domain2.com
sans:
- '*.domain2.com'
- main: domain3.lol
sans:
- '*.domain3.lol'
- main: domain4.co.uk
sans:
- '*.domain4.co.uk'
middlewares:
- securityHeaders@file
providers:
providersThrottleDuration: 2s
# File provider for connecting things that are outside of Docker / defining middleware
file:
filename: /etc/traefik/config.yml
watch: true
# Docker provider for connecting all apps that are inside the Docker network
docker:
watch: true
network: proxy
defaultRule: "Host(`{{ lower (trimPrefix `/` .ContainerName )}}.domain.xyz`)" # .ContainerName uses container name
exposedByDefault: true
# Enable Traefik UI
api:
dashboard: true
insecure: true
# Log level INFO|DEBUG|ERROR
log:
level: error
# Use Let's Encrypt to generate SSL certificates
certificatesResolvers:
letsencrypt:
acme:
email: traefik@domain.xyz
storage: /etc/traefik/acme.json
dnsChallenge:
provider: cloudflare
# Used to make sure the dns challenge is propagated to the rights dns servers
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"With the example above, Traefik is set to automatically detect the name of the Docker container and use it as the subdomain. This is set as the container_name in the docker-compose.yml. Setting the subdomain explicitly is shown later in the container labels step.
Configuration file
Next, create a config.yml. The path to this file is set within traefik.yml. In this configuration file we need to define the routes and services that Traefik will control.
Some of the routes below are defined here because they are not Docker applications.
http:
## Manually proxy apps that are not on docker network
routers:
unraid: # UNRAID
entryPoints:
- https
rule: 'Host(`unraid.domain.xyz`) || Host(`drogon.domain.xyz`)'
service: unraid
middlewares: # Enable authelia
- "auth"
router: # Router
entryPoints:
- https
rule: 'Host(`router.domain.xyz`)'
service: router
middlewares:
- "auth"
homebridge: # homebridge
entryPoints:
- https
rule: 'Host(`homebridge.domain.xyz`)'
service: homebridge
middlewares:
- "auth"
services:
unraid:
loadBalancer:
servers:
- url: http://192.168.0.10:2610
router:
loadBalancer:
servers:
- url: http://192.168.0.1
rtsp-relay:
loadBalancer:
servers:
- url: http://192.168.0.10:8700
homebridge:
loadBalancer:
servers:
- url: http://192.168.0.10:8581
## Middlewares ##
middlewares:
auth:
forwardauth:
address: http://auth:9091/api/verify?rd=https://auth.DOMAIN.COM/ # replace auth with your Authelia container name
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups
- Remote-Name
- Remote-Email
# Authelia basic auth guard
auth-basic:
forwardauth:
address: http://auth:9091/api/verify?auth=basic # replace auth with your Authelia container name
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups
- Remote-Name
- Remote-Email
# Security headers
securityHeaders:
headers:
customResponseHeaders:
X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex"
server: ""
X-Forwarded-Proto: "https"
sslProxyHeaders:
X-Forwarded-Proto: https
referrerPolicy: "strict-origin-when-cross-origin"
hostsProxyHeaders:
- "X-Forwarded-Host"
customRequestHeaders:
X-Forwarded-Proto: "https"
contentTypeNosniff: true
browserXssFilter: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsSeconds: 63072000
stsPreload: true
# Only use secure ciphers - https://ssl-config.mozilla.org/#server=traefik&version=2.6.0&config=intermediate&guideline=5.6
tls:
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_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
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305In this file we are mainly passing the middleware to force all traffic to Authelia before any further action is taken by Traefik, and defining TLS and other security headers that are relevant.
Container example
Below is a working example of Vaultwarden being protected by Authelia and routed through vault.domain.com.
version: "3"
services:
vaultwarden:
image: 'vaultwarden/server:latest'
container_name: vaultwarden
restart: unless-stopped
volumes:
- /opt/appdata/vaultwarden/files:/data
ports:
- 8099:80
networks:
- proxy
labels:
traefik.enable: true
traefik.http.routers.vaultwarden.entryPoints: https
traefik.http.routers.vaultwarden.middlewares: auth@file
traefik.http.routers.vaultwarden.rule: Host(`vault.DOMAIN.COM`)
traefik.http.services.vaultwarden.loadbalancer.server.port: 80
networks:
proxy:
driver: bridge
external: trueFirst, we need to ensure the network is set up correctly, specifying proxy and declaring this network at the bottom under networks. Once that's done we can move on to the labels.
Enable Traefik
This label simply enables Traefik to see this container and bring it into the load balancers and proxy.
traefik.enable: trueForce HTTPS
The following label ensures that all traffic is forwarded to https. If traffic is not secure, it will not touch it.
Probably not needed as the config forces everything from HTTP→ HTTPS.
traefik.http.routers.vaultwarden.entryPoints: httpsForce middleware
This middleware label is required to ensure that all traffic to this container is checked with auth@file, where auth is defined as a middleware within config.yml. If you don't want Authelia to sit in front of your site, don't include this in the labels of your container.
traefik.http.routers.vaultwarden.middlewares: auth@fileCustom subdomain
If you don't wish Traefik to use the container_name as the subdomain, you can specify the domain in the format below. Ensure the subdomain exists on your DNS server. In this case I am using Cloudflare.
traefik.http.routers.vaultwarden.rule: Host(`vault.DOMAIN.COM`)