This should mostly work, ive commented out the oauth, but when you get it working unauthenticated, add that in after, and configure it with your preferred email auth (i use google)
In cloudflare:
- get your API keys, and put whatever combo you need in the .env file
- create your *.domain.com address and add in your public IP address
- create some non-routable subdomains (i use *.disk.domain, and *.desktop.domain in this setup) and give them non-routable internal Ip addresses (ie your LAN ip addresses)
On your router
- ensure port 80 and 443 are NAT to your server hosting traefik
- Possibly setup auto refresh of public IP address in cloudflare
there is some logic here to allow you to access docker services internally with or without oauth with the middleware that is commented out, and the oauth service
.env <-- put this next to your docker-compose files)
DOMAINNAME=yourdomain.com
# Whatever combo you need here, put in the compose for acme
CF_DNS_API_TOKEN=Cloudflaretokens
CF_API_EMAIL=Cloudflaretokens
CF_API_KEY=Cloudflaretokens
# I use google, and it needs these for the middleware
GOOGLE_CLIENT_ID=someid.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=R-somesecret
GOOGLE_APP_ID=1234567890
OAUTH_SECRET=anythingyouwant
MY_EMAIL=papina@domain.com,anothergmail@gmail.com
docker-compose.yml
version: "3.7"
services:
# This is a traefik setup for internet access
traefik:
image: traefik:latest
container_name: "traefik"
restart: unless-stopped
volumes:
# Traefik requires access to docker.sock to read docker labels
- /var/run/docker.sock:/var/run/docker.sock:ro # Access to Docker
- ./traefik/acme.json:/acme.json # SSL certificates
- ./traefik/rules:/rules # Traefik configuration
- ./traefik/logs:/logs # keep logs
environment:
# Required for Cloudflare, replace with whatever DNS providers API key are required
# https://go-acme.github.io/lego/dns/cloudflare/
- CF_API_EMAIL=${CF_API_EMAIL}
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
- CF_API_KEY =${CF_API_KEY}
# For file provider rules, we need a variable we can use
- DOMAINNAME=${DOMAINNAME}
ports:
- 80:80
- 443:443
command:
# Traefik settings to get a Dashboard, and log settings
- "--api.dashboard=true"
- "--api=true"
- "--api.insecure=true"
- "--log.filePath=/logs/traefik.json"
- "--log.format=json"
- "--log.level=INFO"
- "--serversTransport.insecureSkipVerify=true"
# EntryPoints ports and redirecton to SSL
- "--entryPoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--entryPoints.web.http.redirections.entryPoint.to=websecure"
- "--entryPoints.web.http.redirections.entryPoint.scheme=https"
# Use the Cloudflare ENV variables to Authenticate to Cloudflare and update DNS
- "--certificatesResolvers.myresolver.acme.storage=/acme.json"
- "--certificatesResolvers.myresolver.acme.email=your.email@gmail.com"
- "--certificatesResolvers.myresolver.acme.dnsChallenge=true"
- "--certificatesResolvers.myresolver.acme.dnschallenge.provider=cloudflare" # Using Cloudflare here
# Attach SSL Certs to domains
- "--entryPoints.websecure.http.tls.certresolver=myresolver"
- "--entrypoints.websecure.http.tls.domains[0].main=${DOMAINNAME}"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.${DOMAINNAME}"
- "--entrypoints.websecure.http.tls.domains[1].main=*.disk.${DOMAINNAME}"
- "--entrypoints.websecure.http.tls.domains[2].main=*.desktop.${DOMAINNAME}"
# Setup the docker provider, and basic rules to grab the docker service name as the host name
- "--providers.docker=true"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedByDefault=true"
- "--providers.docker.defaultRule=Host(`{{ index .Labels \"com.docker.compose.service\" }}.${DOMAINNAME}`) || Host(`{{ index .Labels \"com.docker.compose.service\" }}.disk.${DOMAINNAME}`)"
# Setup the file provider so we can add dynamic rules as YAML files, eg OAUTH middleware chains
- "--providers.file.directory=/rules"
- "--providers.file.watch=true"
# Now set some defaults entrypoint settings so we don't have to set them on any docker services
# - "--entryPoints.websecure.http.middlewares=chain-oauth-auth@file"
labels:
- "traefik.http.routers.traefik-rtr.service=api@internal"
The static
config (ie the traefik command line) you can put most of the docker logic negating the need to put anything in the docker labels, except for where they expose more than one port, then you just add the loadbalancer label, and that's generally all you need
labels:
# Gitea Image exposes multiple ports, but I only want this one
- "traefik.http.services.gitea-svc.loadbalancer.server.port=3000"
whoami only exposes 1 port, it needs no labels with the correct traefik static config
# whoami.domain.com
whoami:
image: "traefik/whoami"
container_name: "whoami"
middleware-oauth.yml <-- put this in your /rules folder, its dynamic
http:
middlewares:
middlewares-oauth:
forwardAuth:
address: "http://oauth:4181"
trustForwardHeader: true
authResponseHeaders:
- "X-Forwarded-User"
Oauth example
## OAuth - Forward Authentication
oauth:
image: thomseddon/traefik-forward-auth
container_name: "oauth"
restart: unless-stopped
networks:
- t2_proxy
command:
# Limit Admin page to oauth
- --rule.restrictpage.action=auth
- --rule.restrictpage.rule=HostRegexp(`{adminpages:^(vault|gitlab|gitea)}.${DOMAINNAME}`) && PathPrefix(`/admin`)
# Allow access to the API of sonarr/radarr for NZB360, but still require oauth for the web interface
- --rule.sonarrapi.action=allow
- --rule.sonarrapi.rule=HostRegexp(`{nzbapi:^(sonarr|radarr)}.${DOMAINNAME}`) && PathPrefix(`/api`)
# Allow subdomain access to internal, non-routable IP addresses
- --rule.bypasslocal.action=allow
- --rule.bypasslocal.rule=HostRegexp(`{subdomain:[a-z0-9]+}.{subdomain:(disk|desktop)}.${DOMAINNAME}`)
# Allow public access to vaultwarden,gitlab,gitea
- --rule.bypassdomain.action=allow
- --rule.bypassdomain.rule=HostRegexp(`{subdomain:^(hvault|vault|gitlab|gitea)}.${DOMAINNAME}`)
environment:
# Setup Google OAuth API Credentials for these values
- PROVIDERS_GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- PROVIDERS_GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
# API Credentials Authorised JavaScript origins values
- AUTH_HOST=oauth.${DOMAINNAME}
# API Credentials Authorised redirect URI value is appended to https://${DOMAINNAME}
- URL_PATH=/_oauth
# Whitelist this domain or email addresses
- MATCH_WHITELIST_OR_DOMAIN=true
- DOMAIN=${DOMAINNAME}
- WHITELIST=${MY_EMAIL}
# General OAuth Container settings
- COOKIE_DOMAIN=${DOMAINNAME}
- SECRET=${OAUTH_SECRET}
- INSECURE_COOKIE="true"
- LOG_FORMAT=pretty
- LOG_LEVEL=error
labels:
- "traefik.http.services.oauth-svc.loadbalancer.server.port=4181"