- Consolidated documentation from Ralph Loop iterations - Archived 20+ outdated/superseded files to .archive/ - Kept essential docs: OIDC integration, mobile setup, quick start - Added operational scripts for health monitoring and backup - Research artifacts preserved in .tasks/artifacts/ Current state: - 3 VPS sites (fry, proton, photon) ONLINE in Pangolin - brn-home site pending for local services (Jellyfin, etc.) - Mobile access configuration pending Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
349 lines
9.8 KiB
Markdown
349 lines
9.8 KiB
Markdown
# Traefik Configuration Analysis
|
|
|
|
**Analysis Date:** 2025-01-20
|
|
**Source:** /srv/docker/traefik/
|
|
**Purpose:** Document Traefik configuration for Authentik and Pangolin integration
|
|
|
|
---
|
|
|
|
## Docker Network Configuration
|
|
|
|
### Primary Network
|
|
- **Network Name:** `traefik`
|
|
- **Type:** External bridge network
|
|
- **Subnet:** 172.19.0.0/16
|
|
- **Gateway:** 172.19.0.1
|
|
- **Network ID:** fffc2e33eb02203ed2ebd30725098d0ef8c7d5b0890fdf9a6d4aba5eb0784cc8
|
|
|
|
### Connected Containers
|
|
Currently attached services on the traefik network:
|
|
- traefik (172.19.0.3)
|
|
- transmission (172.19.0.2)
|
|
- openwebui (172.19.0.4)
|
|
- static-site-baumert-cc (172.19.0.5)
|
|
- static-sites (172.19.0.6)
|
|
- jellyfin (172.19.0.7)
|
|
|
|
**CRITICAL:** All services that need Traefik routing must be connected to the `traefik` external network.
|
|
|
|
---
|
|
|
|
## Certificate Resolver Configuration
|
|
|
|
### ACME Settings
|
|
- **Resolver Name:** `letsencrypt`
|
|
- **Challenge Type:** DNS-01 (Exoscale)
|
|
- **Provider:** exoscale
|
|
- **DNS Resolvers:** 1.1.1.1:53, 8.8.8.8:53
|
|
- **Delay Before Check:** 30s
|
|
- **ACME Email:** admin@obr.digital
|
|
- **Storage Path:** /letsencrypt/acme.json
|
|
|
|
### Environment Variables Required
|
|
```bash
|
|
EXOSCALE_API_KEY=EXO7929dee61aff39dce8dd104a
|
|
EXOSCALE_API_SECRET=vgfgnK3fmB-76v-YrZSQuu6Q_gBY6OMsOP_QuWWcr1A
|
|
```
|
|
|
|
**Note:** DNS-01 challenge allows wildcard certificates and works without requiring ports 80/443 to be publicly accessible during certificate issuance.
|
|
|
|
---
|
|
|
|
## Traefik Label Patterns
|
|
|
|
### Standard Service Pattern (Docker Labels)
|
|
|
|
Example from transmission service:
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.transmission.rule=Host(`transmission.local.obr.digital`)"
|
|
- "traefik.http.routers.transmission.entrypoints=websecure"
|
|
- "traefik.http.routers.transmission.tls=true"
|
|
- "traefik.http.routers.transmission.tls.certresolver=letsencrypt"
|
|
- "traefik.http.routers.transmission.service=transmission"
|
|
- "traefik.http.services.transmission.loadbalancer.server.port=9091"
|
|
```
|
|
|
|
Example from openwebui service:
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.openwebui.rule=Host(`openwebui.local.obr.digital`)"
|
|
- "traefik.http.routers.openwebui.entrypoints=websecure"
|
|
- "traefik.http.routers.openwebui.tls=true"
|
|
- "traefik.http.routers.openwebui.tls.certresolver=letsencrypt"
|
|
- "traefik.http.services.openwebui.loadbalancer.server.port=8080"
|
|
- "traefik.docker.network=traefik"
|
|
```
|
|
|
|
### Label Pattern Template
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.<service-name>.rule=Host(`<domain>`)"
|
|
- "traefik.http.routers.<service-name>.entrypoints=websecure"
|
|
- "traefik.http.routers.<service-name>.tls=true"
|
|
- "traefik.http.routers.<service-name>.tls.certresolver=letsencrypt"
|
|
- "traefik.http.services.<service-name>.loadbalancer.server.port=<port>"
|
|
- "traefik.docker.network=traefik" # Required when service uses multiple networks
|
|
```
|
|
|
|
### Middleware Pattern (Basic Auth)
|
|
From Traefik dashboard configuration:
|
|
```yaml
|
|
labels:
|
|
- "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$Di.EvXJZ$$z3Tc1Oss4W3nx/enE0gk71"
|
|
- "traefik.http.routers.dashboard.middlewares=dashboard-auth"
|
|
```
|
|
|
|
**Note:** Dollar signs must be doubled (`$$`) in docker-compose files to escape them properly.
|
|
|
|
---
|
|
|
|
## Entry Points
|
|
|
|
### Configured Entry Points
|
|
1. **web** (Port 80)
|
|
- Automatic redirect to HTTPS
|
|
- Permanent redirect (301)
|
|
- Scheme: https
|
|
|
|
2. **websecure** (Port 443)
|
|
- TLS enabled by default
|
|
- Primary entry point for all services
|
|
|
|
3. **metrics** (Port 8082)
|
|
- Prometheus metrics endpoint
|
|
- Internal only (not exposed in ports)
|
|
|
|
### Entry Point Configuration
|
|
```yaml
|
|
command:
|
|
- "--entrypoints.web.address=:80"
|
|
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
|
|
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
|
|
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
|
|
- "--entrypoints.websecure.address=:443"
|
|
- "--entrypoints.websecure.http.tls=true"
|
|
```
|
|
|
|
---
|
|
|
|
## Dynamic Configuration Structure
|
|
|
|
### File Location
|
|
- **Path:** /srv/docker/traefik/traefik_dynamic.yaml
|
|
- **Mount:** Read-only volume in Traefik container
|
|
- **Provider:** File provider enabled in Traefik config
|
|
|
|
### Dynamic Configuration Pattern
|
|
The dynamic configuration file defines routers and services in YAML format:
|
|
|
|
```yaml
|
|
http:
|
|
routers:
|
|
<router-name>:
|
|
rule: "Host(`<domain>`)"
|
|
service: <service-name>
|
|
priority: 100
|
|
entryPoints:
|
|
- websecure
|
|
tls:
|
|
certResolver: letsencrypt
|
|
|
|
services:
|
|
<service-name>:
|
|
loadBalancer:
|
|
servers:
|
|
- url: "http://<container-name>:<port>"
|
|
```
|
|
|
|
### Current Dynamic Routes
|
|
The dynamic configuration currently handles:
|
|
- Static sites (1.obr.sh, fw.obr.sh, brn.obnh.io)
|
|
- Pi-hole admin (dns.obnh.io, dns.obnh.network) - routes to host.docker.internal:8080
|
|
- Transmission (tor.obnh.org, tor.obnh.network)
|
|
- OpenWebUI (ll.obr.sh)
|
|
- HTTPS fallback router (priority: 1)
|
|
|
|
### Service Backend Patterns
|
|
1. **Docker containers:** `http://<container-name>:<port>`
|
|
2. **Host services:** `http://host.docker.internal:<port>`
|
|
|
|
---
|
|
|
|
## Traefik Provider Configuration
|
|
|
|
### Docker Provider
|
|
```yaml
|
|
command:
|
|
- "--providers.docker=true"
|
|
- "--providers.docker.exposedbydefault=false"
|
|
- "--providers.docker.network=traefik"
|
|
```
|
|
|
|
**Key Points:**
|
|
- Services must explicitly set `traefik.enable=true`
|
|
- Default network for label-based routing is `traefik`
|
|
- Docker socket mounted read-only for security
|
|
|
|
### File Provider
|
|
```yaml
|
|
command:
|
|
- "--providers.file.filename=/traefik_dynamic.yaml"
|
|
```
|
|
|
|
---
|
|
|
|
## API and Dashboard
|
|
|
|
### Dashboard Access
|
|
- **URL:** https://traefik.local.obr.digital
|
|
- **Authentication:** Basic Auth (admin:obr2024)
|
|
- **Router:** dashboard
|
|
- **Service:** api@internal
|
|
- **TLS:** Let's Encrypt certificate
|
|
|
|
### API Configuration
|
|
```yaml
|
|
command:
|
|
- "--api.dashboard=true"
|
|
- "--api.insecure=false"
|
|
```
|
|
|
|
---
|
|
|
|
## Recommendations for Authentik Integration
|
|
|
|
### 1. Network Configuration
|
|
Authentik services must be added to the `traefik` external network:
|
|
```yaml
|
|
networks:
|
|
- traefik
|
|
- authentik-internal # For PostgreSQL/Redis internal communication
|
|
```
|
|
|
|
### 2. Required Labels for Authentik Server
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.authentik.rule=Host(`auth.obr.digital`)"
|
|
- "traefik.http.routers.authentik.entrypoints=websecure"
|
|
- "traefik.http.routers.authentik.tls=true"
|
|
- "traefik.http.routers.authentik.tls.certresolver=letsencrypt"
|
|
- "traefik.http.services.authentik.loadbalancer.server.port=9000"
|
|
- "traefik.docker.network=traefik"
|
|
```
|
|
|
|
### 3. Forward Auth Middleware Pattern
|
|
For protecting services with Authentik SSO:
|
|
```yaml
|
|
labels:
|
|
- "traefik.http.middlewares.authentik.forwardauth.address=http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
|
|
- "traefik.http.middlewares.authentik.forwardauth.trustForwardHeader=true"
|
|
- "traefik.http.middlewares.authentik.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid"
|
|
- "traefik.http.routers.<service>.middlewares=authentik"
|
|
```
|
|
|
|
### 4. Network Declaration in docker-compose.yml
|
|
```yaml
|
|
networks:
|
|
traefik:
|
|
external: true
|
|
authentik-internal:
|
|
driver: bridge
|
|
```
|
|
|
|
---
|
|
|
|
## Recommendations for Pangolin Integration
|
|
|
|
### 1. Service Labels
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.pangolin.rule=Host(`pangolin.obr.digital`)"
|
|
- "traefik.http.routers.pangolin.entrypoints=websecure"
|
|
- "traefik.http.routers.pangolin.tls=true"
|
|
- "traefik.http.routers.pangolin.tls.certresolver=letsencrypt"
|
|
- "traefik.http.services.pangolin.loadbalancer.server.port=8000"
|
|
- "traefik.http.routers.pangolin.middlewares=authentik"
|
|
- "traefik.docker.network=traefik"
|
|
```
|
|
|
|
### 2. Network Configuration
|
|
```yaml
|
|
networks:
|
|
- traefik
|
|
- pangolin-internal # For PostgreSQL internal communication
|
|
```
|
|
|
|
---
|
|
|
|
## Security Considerations
|
|
|
|
### 1. Docker Socket Access
|
|
- Traefik has read-only access to Docker socket
|
|
- No containers can modify Docker state through Traefik
|
|
|
|
### 2. Exposed by Default
|
|
- `exposedbydefault=false` requires explicit opt-in via labels
|
|
- Prevents accidental service exposure
|
|
|
|
### 3. TLS Configuration
|
|
- All services force HTTPS via websecure entry point
|
|
- HTTP automatically redirects to HTTPS (permanent 301)
|
|
- Let's Encrypt certificates auto-renewed
|
|
|
|
### 4. Metrics
|
|
- Prometheus metrics on port 8082
|
|
- Not exposed externally in port mappings
|
|
- Can be accessed internally by monitoring containers
|
|
|
|
---
|
|
|
|
## Files Reference
|
|
|
|
### Configuration Files
|
|
1. `/srv/docker/traefik/docker-compose.yml` - Main Traefik service definition
|
|
2. `/srv/docker/traefik/traefik_dynamic.yaml` - Dynamic file-based configuration
|
|
3. `/srv/docker/traefik/.env` - Exoscale API credentials
|
|
4. `/srv/docker/traefik/letsencrypt/acme.json` - Certificate storage (auto-generated)
|
|
|
|
### Example Service Configurations
|
|
1. `/srv/docker/transmission/docker-compose.yml` - Full label-based routing
|
|
2. `/srv/docker/openwebui/docker-compose.yml` - Multi-network service with Traefik
|
|
3. `/srv/docker/static-site/docker-compose.yml` - Minimal service (uses dynamic config)
|
|
|
|
---
|
|
|
|
## Summary for Integration Tasks
|
|
|
|
### For TASK-003 (Authentik Deployment)
|
|
- Use external network: `traefik`
|
|
- Certificate resolver: `letsencrypt`
|
|
- Entry point: `websecure`
|
|
- Suggested domain: `auth.obr.digital`
|
|
- Required port: 9000 (Authentik server)
|
|
- Add `traefik.docker.network=traefik` label (multi-network scenario)
|
|
|
|
### For TASK-008 (Pangolin Deployment)
|
|
- Use external network: `traefik`
|
|
- Certificate resolver: `letsencrypt`
|
|
- Entry point: `websecure`
|
|
- Suggested domain: `pangolin.obr.digital`
|
|
- Required port: 8000 (typical Django/FastAPI port)
|
|
- Apply Authentik forward auth middleware
|
|
- Add `traefik.docker.network=traefik` label (multi-network scenario)
|
|
|
|
### Network Connectivity
|
|
Both services must declare:
|
|
```yaml
|
|
networks:
|
|
traefik:
|
|
external: true
|
|
```
|
|
|
|
This ensures they can communicate with Traefik and be discovered by its Docker provider.
|