Files
homelab-configs/traefik/dynamic_conf_node02.yml
tommy 7fac4fc9c7 traefik: sync dynamic_conf.yml and add drift-check cron
node02 was missing two blocks from node01 (canonical):
- strip-trailing-dot-speedtest middleware (regex redirect for speedtest.goattw.net. URLs)
- speedtest-trailing-dot router (catches trailing-dot Host header variant)

crowdsecLapiHost intentionally differs: node01 uses Docker service name
(crowdsec:8080, container on same host); node02 points to node01 IP
(192.168.99.186:8081, node02 has no local CrowdSec instance).

Added traefik-drift-check.sh — runs daily at 06:00 on ansible-control,
diffs both configs (excluding known crowdsecLapiHost difference),
posts to ntfy homelab-alerts on unexpected divergence.

Traefik hot-reloaded on node02 via SIGHUP — no restart required.
2026-05-05 20:17:17 -05:00

712 lines
20 KiB
YAML

http:
serversTransports:
default-transport:
forwardingTimeouts:
dialTimeout: 30s
responseHeaderTimeout: 30s
idleConnTimeout: 90s
insecure-transport:
insecureSkipVerify: true
middlewares:
secure-headers:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
- POST
accessControlMaxAge: 100
addVaryHeader: true
frameDeny: true
customRequestHeaders:
X-Forwarded-Proto: "https"
X-Forwarded-Port: "443"
X-Forwarded-Ssl: "on"
sslProxyHeaders:
X-Forwarded-Proto: "https"
browserXssFilter: true
contentTypeNosniff: true
referrerPolicy: "same-origin"
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
ha-headers:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
X-Forwarded-Port: "443"
X-Forwarded-Ssl: "on"
sslProxyHeaders:
X-Forwarded-Proto: "https"
browserXssFilter: true
contentTypeNosniff: true
referrerPolicy: "same-origin"
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
customResponseHeaders:
X-Frame-Options: "SAMEORIGIN"
authelia-auth:
forwardAuth:
address: "http://authelia:9091/api/authz/forward-auth?rd=https://auth.goattw.net/"
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups
- Remote-Name
- Remote-Email
strip-trailing-dot-speedtest:
redirectRegex:
regex: '^https://speedtest\.goattw\.net\.(/.*)?$'
replacement: "https://speedtest.goattw.net${1}"
permanent: false
# ============================================================
# CROWDSEC-BOUNCER - Block malicious IPs via CrowdSec decisions
# ============================================================
# Purpose: Queries CrowdSec local API before passing requests through.
# Blocks IPs flagged by local detection or community blocklists.
# Notes: API key generated via: docker exec crowdsec cscli bouncers add traefik-bouncer
# CrowdSec runs on docker-node01 at port 8081.
# ============================================================
crowdsec-bouncer:
plugin:
crowdsec-bouncer:
enabled: true
crowdsecLapiKey: VMCnws/j+9pmsT4YT+t3HzrvX8OhBCwoquwo4NqWJPs
crowdsecLapiHost: 192.168.99.186:8081
crowdsecMode: live
routers:
nextcloud:
rule: "Host(`cloud.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: nextcloud-service
middlewares: ["secure-headers@file"]
homeassistant:
rule: "Host(`ha.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: homeassistant-service
middlewares: ["ha-headers@file"]
plex:
rule: "Host(`plex.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: plex-service
middlewares: ["secure-headers@file", "crowdsec-bouncer@file"]
homepage:
rule: "Host(`home.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: homepage-service
middlewares: ["secure-headers@file", "crowdsec-bouncer@file"]
sonarr:
rule: "Host(`sonarr.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: sonarr-service
middlewares: ["secure-headers@file", "authelia-auth@file", "crowdsec-bouncer@file"]
radarr:
rule: "Host(`radarr.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: radarr-service
middlewares: ["secure-headers@file", "authelia-auth@file", "crowdsec-bouncer@file"]
prowlarr:
rule: "Host(`prowlarr.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: prowlarr-service
middlewares: ["secure-headers@file", "authelia-auth@file", "crowdsec-bouncer@file"]
overseerr:
rule: "Host(`request.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: overseerr-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
tautulli:
rule: "Host(`stats.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: tautulli-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
transmission:
rule: "Host(`transmission.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: transmission-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
sabnzbd:
rule: "Host(`sabnzbd.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: sabnzbd-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
uptime-kuma:
rule: "Host(`uptime.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: uptime-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
beszel:
rule: "Host(`beszel.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: beszel-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
dozzle:
rule: "Host(`dozzle.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: dozzle-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
paperless:
rule: "Host(`paperless.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: paperless-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
grafana:
rule: "Host(`grafana.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: grafana-service
middlewares: ["secure-headers@file", "authelia-auth@file", "crowdsec-bouncer@file"]
prometheus:
rule: "Host(`prometheus.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: prometheus-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
loki:
rule: "Host(`loki.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: loki-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
tdarr:
rule: "Host(`tdarr.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: tdarr-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
gitea:
rule: "Host(`gitea.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: gitea-service
middlewares: ["secure-headers@file"]
portainer:
rule: "Host(`portainer.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: portainer-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
immich:
rule: "Host(`immich.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: immich-service
middlewares: ["secure-headers@file"]
dockge:
rule: "Host(`dockge.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: dockge-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
open-webui:
rule: "Host(`ai.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: open-webui-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
bazarr:
rule: "Host(`bazarr.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: bazarr-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
lidarr:
rule: "Host(`lidarr.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: lidarr-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
smokeping:
rule: "Host(`smokeping.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: smokeping-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
it-tools:
rule: "Host(`it-tools.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: it-tools-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
plex-utills:
rule: "Host(`plex-utills.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: plex-utills-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
navidrome:
rule: "Host(`music.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: navidrome-service
middlewares: ["secure-headers@file"]
semaphore:
rule: "Host(`semaphore.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: semaphore-service
middlewares: ["authelia-auth@file"]
netbox:
rule: "Host(`netbox.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: netbox-service
middlewares: ["authelia-auth@file"]
wazuh:
rule: "Host(`wazuh.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: wazuh-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
dagu:
rule: "Host(`dagu.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: dagu-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
n8n:
rule: "Host(`n8n.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: n8n-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
node-red:
rule: "Host(`nodered.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: node-red-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
woodpecker:
rule: "Host(`ci.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: woodpecker-service
middlewares: ["secure-headers@file"]
filebrowser:
rule: "Host(`files.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: filebrowser-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
healthchecks:
rule: "Host(`healthchecks.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: healthchecks-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
tandoor:
rule: "Host(`tandoor.goattw.net`)"
entryPoints: ["websecure"]
tls: { certResolver: letsencrypt }
service: tandoor-service
middlewares: ["secure-headers@file", "authelia-auth@file"]
ntfy:
rule: "Host(`ntfy.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: ntfy-service
tls:
certResolver: letsencrypt
speedtest-trailing-dot:
rule: "Host(`speedtest.goattw.net.`)"
entryPoints:
- websecure
priority: 200
middlewares:
- strip-trailing-dot-speedtest@file
service: speedtest-service
tls:
certResolver: letsencrypt
speedtest:
rule: "Host(`speedtest.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: speedtest-service
tls:
certResolver: letsencrypt
linkding:
rule: "Host(`linkding.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: linkding-service
tls:
certResolver: letsencrypt
vikunja:
rule: "Host(`vikunja.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: vikunja-service
tls:
certResolver: letsencrypt
watchyourlan:
rule: "Host(`watchyourlan.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: watchyourlan-service
tls:
certResolver: letsencrypt
glances:
rule: "Host(`glances.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: glances-service
tls:
certResolver: letsencrypt
netdata:
rule: "Host(`netdata.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: netdata-service
tls:
certResolver: letsencrypt
mealie:
rule: "Host(`mealie.goattw.net`)"
entryPoints:
- websecure
middlewares:
- authelia-auth@file
service: mealie-service
tls:
certResolver: letsencrypt
services:
nextcloud-service:
loadBalancer:
servers: [{ url: "http://192.168.99.31:11000" }]
serversTransport: default-transport
homeassistant-service:
loadBalancer:
servers: [{ url: "http://192.168.99.100:8123" }]
passHostHeader: true
serversTransport: default-transport
plex-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:32400" }]
serversTransport: default-transport
homepage-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:3000" }]
serversTransport: default-transport
sonarr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8989" }]
serversTransport: default-transport
radarr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:7878" }]
serversTransport: default-transport
prowlarr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:9696" }]
serversTransport: default-transport
overseerr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:5055" }]
serversTransport: default-transport
tautulli-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8181" }]
serversTransport: default-transport
transmission-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:9091" }]
serversTransport: default-transport
sabnzbd-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8081" }]
serversTransport: default-transport
uptime-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:3001" }]
serversTransport: default-transport
beszel-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8090" }]
serversTransport: default-transport
dozzle-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8082" }]
serversTransport: default-transport
paperless-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8010" }]
serversTransport: default-transport
grafana-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:3005" }]
serversTransport: default-transport
prometheus-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:9090" }]
serversTransport: default-transport
loki-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:3100" }]
serversTransport: default-transport
tdarr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8265" }]
serversTransport: default-transport
gitea-service:
loadBalancer:
servers: [{ url: "http://192.168.99.186:3002" }]
serversTransport: default-transport
portainer-service:
loadBalancer:
servers:
- url: "https://192.168.99.186:9443"
serversTransport: insecure-transport
immich-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:2283" }]
serversTransport: default-transport
dockge-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:5001" }]
serversTransport: default-transport
open-webui-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8080" }]
serversTransport: default-transport
bazarr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:6767" }]
serversTransport: default-transport
lidarr-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8686" }]
serversTransport: default-transport
smokeping-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8086" }]
serversTransport: default-transport
it-tools-service:
loadBalancer:
servers: [{ url: "http://192.168.99.186:8085" }]
serversTransport: default-transport
plex-utills-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:5000" }]
serversTransport: default-transport
navidrome-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:4533" }]
serversTransport: default-transport
semaphore-service:
loadBalancer:
servers: [{ url: "http://192.168.99.186:3001" }]
serversTransport: default-transport
netbox-service:
loadBalancer:
servers: [{ url: "http://192.168.99.186:8084" }]
serversTransport: default-transport
wazuh-service:
loadBalancer:
servers: [{ url: "https://192.168.99.199" }]
serversTransport: insecure-transport
healthchecks-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8091" }]
serversTransport: default-transport
dagu-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8092" }]
serversTransport: default-transport
filebrowser-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8093" }]
serversTransport: default-transport
woodpecker-service:
loadBalancer:
servers: [{ url: "http://192.168.99.186:8086" }]
serversTransport: default-transport
node-red-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:1880" }]
serversTransport: default-transport
tandoor-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:8094" }]
serversTransport: default-transport
n8n-service:
loadBalancer:
servers: [{ url: "http://192.168.99.183:5678" }]
serversTransport: default-transport
ntfy-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:8095"
serversTransport: default-transport
speedtest-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:8096"
serversTransport: default-transport
linkding-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:8097"
serversTransport: default-transport
vikunja-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:8098"
serversTransport: default-transport
watchyourlan-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:8840"
serversTransport: default-transport
glances-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:61208"
serversTransport: default-transport
netdata-service:
loadBalancer:
servers:
- url: "http://192.168.99.198:19999"
serversTransport: default-transport
mealie-service:
loadBalancer:
servers:
- url: "http://192.168.99.183:9925"
serversTransport: default-transport