Add internal Traefik ingress for Pangolin and Authelia
Some checks failed
secret-guardrails / artifact-secret-scan (push) Has been cancelled
secret-guardrails / gitleaks (push) Has been cancelled

This commit is contained in:
Fizzlepoof
2026-05-23 10:59:20 +00:00
parent 889783e621
commit 5c6b3cab4d
14 changed files with 499 additions and 6 deletions

30
ingress/README.md Normal file
View File

@@ -0,0 +1,30 @@
# Ingress / Traefik
This stack adds an internal Traefik layer on PD.
Why this exists:
- keep Pangolin as the public tunnel/edge from the VPS
- centralize app routing behind one internal reverse proxy
- put Authelia in front of selected apps with domain-based policy
- fix browser cert pain for apps like Technitium by terminating the public HTTPS edge before the self-signed backend
- avoid giving Traefik Docker socket access; routes are explicit file-provider config
Design choices:
- Traefik is internal-only on the `pangolin` Docker network
- no host port publishing
- no ACME on PD
- no Docker provider / no docker.sock mount
- Pangolin resources should target `traefik:80` on site 4 when an app is cut over to this layer
- Authelia remains the identity decision point for domain/group access
Current routed hostnames in dynamic config:
- `auth.paccoco.com` -> Authelia
- `gitea.paccoco.com` -> Gitea (Authelia-protected)
- `grafana.paccoco.com` -> Grafana (Authelia-protected)
- `dns.paccoco.com` -> Technitium (Authelia-protected)
- `traefik.paccoco.com` -> Traefik dashboard (Authelia-protected)
Cutover note:
- Deploying this stack does not automatically rewrite Pangolin resources.
- The secure end state is: Pangolin tunnel -> Traefik -> app.
- If an existing Pangolin resource still points directly at an app, that app will keep behaving the old way until its target is changed.

View File

@@ -0,0 +1,32 @@
name: ingress
networks:
pangolin:
external: true
services:
traefik:
image: traefik:v3.1
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /tmp
- /run
networks:
- pangolin
volumes:
- /mnt/docker-ssd/docker/compose/ingress/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- /mnt/docker-ssd/docker/compose/ingress/traefik/dynamic:/etc/traefik/dynamic:ro
healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s

View File

@@ -0,0 +1,89 @@
http:
routers:
auth:
rule: Host(`auth.paccoco.com`)
entryPoints: [web]
service: authelia
middlewares:
- security-headers
gitea:
rule: Host(`gitea.paccoco.com`)
entryPoints: [web]
service: gitea
middlewares:
- security-headers
- authelia-forwardauth
grafana:
rule: Host(`grafana.paccoco.com`)
entryPoints: [web]
service: grafana
middlewares:
- security-headers
- authelia-forwardauth
technitium:
rule: Host(`dns.paccoco.com`)
entryPoints: [web]
service: technitium
middlewares:
- security-headers
- authelia-forwardauth
traefik-dashboard:
rule: Host(`traefik.paccoco.com`)
entryPoints: [web]
service: api@internal
middlewares:
- security-headers
- authelia-forwardauth
services:
authelia:
loadBalancer:
servers:
- url: http://authelia:9091
gitea:
loadBalancer:
servers:
- url: http://gitea:3000
grafana:
loadBalancer:
servers:
- url: http://grafana:3000
technitium:
loadBalancer:
passHostHeader: true
serversTransport: technitium-selfsigned
servers:
- url: https://technitium-dns-pilot:443
middlewares:
authelia-forwardauth:
forwardAuth:
address: http://authelia:9091/api/authz/forward-auth
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups
- Remote-Name
- Remote-Email
security-headers:
headers:
frameDeny: true
browserXssFilter: true
contentTypeNosniff: true
referrerPolicy: same-origin
customRequestHeaders:
X-Forwarded-Proto: https
customResponseHeaders:
X-Robots-Tag: noindex, nofollow, noarchive, nosnippet
serversTransports:
technitium-selfsigned:
insecureSkipVerify: true

View File

@@ -0,0 +1,22 @@
global:
checkNewVersion: false
sendAnonymousUsage: false
api:
dashboard: true
ping: {}
entryPoints:
web:
address: ":80"
providers:
file:
directory: /etc/traefik/dynamic
watch: true
log:
level: INFO
accessLog: {}