Initial commit: cleaned project structure
- 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>
This commit is contained in:
348
.tasks/artifacts/traefik-analysis.md
Normal file
348
.tasks/artifacts/traefik-analysis.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user