167 lines
6.8 KiB
YAML
167 lines
6.8 KiB
YAML
########################
|
|
# Networks & Volumes
|
|
########################
|
|
networks:
|
|
traefik_proxy:
|
|
name: traefik_proxy
|
|
internal:
|
|
name: internal
|
|
|
|
volumes:
|
|
traefik_letsencrypt:
|
|
traefik_logs:
|
|
portainer_data:
|
|
uptime_kuma_data:
|
|
|
|
########################
|
|
# Services
|
|
########################
|
|
services:
|
|
|
|
## ─────────────────────────────────────────────
|
|
## Traefik — edge router + ACME (HTTP-01)
|
|
## ─────────────────────────────────────────────
|
|
traefik:
|
|
image: traefik:v3.1
|
|
container_name: traefik
|
|
restart: unless-stopped
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
networks: [traefik_proxy]
|
|
environment:
|
|
TZ: "${TZ}"
|
|
command:
|
|
# Providers
|
|
- --providers.docker=true
|
|
- --providers.docker.exposedbydefault=false
|
|
|
|
# Entrypoints
|
|
- --entrypoints.web.address=:80
|
|
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
|
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
|
- --entrypoints.websecure.address=:443
|
|
- --entrypoints.web.forwardedheaders.insecure=true
|
|
- --entrypoints.websecure.forwardedheaders.insecure=true
|
|
|
|
# Dashboard/API (internal)
|
|
- --api.dashboard=true
|
|
|
|
# ACME via HTTP-01 (no registrar API needed)
|
|
- --certificatesresolvers.le.acme.email=${ACME_EMAIL}
|
|
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
|
|
- --certificatesresolvers.le.acme.httpchallenge=true
|
|
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
|
|
# (Alt) Use TLS-ALPN-01 if port 80 is blocked:
|
|
# - --certificatesresolvers.le.acme.tlschallenge=true
|
|
|
|
# Global timeouts for slow backends
|
|
- --serversTransport.forwardingTimeouts.dialTimeout=30s
|
|
- --serversTransport.forwardingTimeouts.responseHeaderTimeout=60s
|
|
- --serversTransport.forwardingTimeouts.idleConnTimeout=180s
|
|
|
|
# Logs
|
|
- --accesslog.filepath=/var/log/traefik/access.log
|
|
- --accesslog.bufferingsize=100
|
|
- --log.level=INFO
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
- traefik_letsencrypt:/letsencrypt
|
|
- traefik_logs:/var/log/traefik
|
|
labels:
|
|
- traefik.enable=true
|
|
|
|
# Reusable security headers
|
|
- traefik.http.middlewares.security-headers.headers.stsSeconds=31536000
|
|
- traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true
|
|
- traefik.http.middlewares.security-headers.headers.stsPreload=true
|
|
- traefik.http.middlewares.security-headers.headers.browserXssFilter=true
|
|
- traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true
|
|
- traefik.http.middlewares.security-headers.headers.referrerPolicy=no-referrer-when-downgrade
|
|
- traefik.http.middlewares.security-headers.headers.frameDeny=true
|
|
|
|
# Traefik dashboard (protected)
|
|
- traefik.http.routers.traefik.rule=Host(`traefik.gate.${DOMAIN}`)
|
|
- traefik.http.routers.traefik.entrypoints=websecure
|
|
- traefik.http.routers.traefik.tls.certresolver=le
|
|
- traefik.http.routers.traefik.service=api@internal
|
|
- traefik.http.routers.traefik.middlewares=security-headers
|
|
|
|
## ─────────────────────────────────────────────
|
|
## Portainer — Docker control plane
|
|
## ─────────────────────────────────────────────
|
|
portainer:
|
|
image: portainer/portainer-ce:latest
|
|
container_name: portainer
|
|
restart: unless-stopped
|
|
networks: [traefik_proxy]
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- portainer_data:/data
|
|
depends_on:
|
|
authelia:
|
|
condition: service_healthy
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.http.routers.portainer.rule=Host(`portainer.gate.${DOMAIN}`)
|
|
- traefik.http.routers.portainer.entrypoints=websecure
|
|
- traefik.http.routers.portainer.tls.certresolver=le
|
|
- traefik.http.routers.portainer.middlewares=authelia,security-headers
|
|
- traefik.http.services.portainer.loadbalancer.server.port=9000
|
|
|
|
## ─────────────────────────────────────────────
|
|
## Authelia — authentication and authorization
|
|
## ─────────────────────────────────────────────
|
|
authelia:
|
|
image: authelia/authelia:latest
|
|
container_name: authelia
|
|
restart: unless-stopped
|
|
networks: [traefik_proxy, internal]
|
|
volumes:
|
|
- ./authelia:/config
|
|
environment:
|
|
TZ: "${TZ}"
|
|
AUTHELIA_JWT_SECRET: "${AUTHELIA_JWT_SECRET}"
|
|
AUTHELIA_SESSION_SECRET: "${AUTHELIA_SESSION_SECRET}"
|
|
AUTHELIA_STORAGE_ENCRYPTION_KEY: "${AUTHELIA_STORAGE_ENCRYPTION_KEY}"
|
|
DOMAIN: "${DOMAIN}"
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9091/api/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.http.routers.authelia.rule=Host(`auth.gate.${DOMAIN}`)
|
|
- traefik.http.routers.authelia.entrypoints=websecure
|
|
- traefik.http.routers.authelia.tls.certresolver=le
|
|
- traefik.http.routers.authelia.middlewares=security-headers
|
|
- traefik.http.services.authelia.loadbalancer.server.port=9091
|
|
|
|
# ForwardAuth middleware for protecting other services
|
|
- traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/authz/forward-auth
|
|
- traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true
|
|
- traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Email,Remote-Name
|
|
|
|
## ─────────────────────────────────────────────
|
|
## Uptime Kuma — status page / checks
|
|
## ─────────────────────────────────────────────
|
|
uptime-kuma:
|
|
image: louislam/uptime-kuma:1
|
|
container_name: uptime-kuma
|
|
restart: unless-stopped
|
|
volumes:
|
|
- uptime_kuma_data:/app/data
|
|
networks: [traefik_proxy]
|
|
depends_on:
|
|
authelia:
|
|
condition: service_healthy
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.http.routers.kuma.rule=Host(`uptime.gate.${DOMAIN}`)
|
|
- traefik.http.routers.kuma.entrypoints=websecure
|
|
- traefik.http.routers.kuma.tls.certresolver=le
|
|
- traefik.http.routers.kuma.middlewares=authelia,security-headers
|
|
- traefik.http.services.kuma.loadbalancer.server.port=3001
|