Traefik & Network Routing¶
Traefik is the single, unified reverse proxy and load balancer for all CharlieHub services. It handles both HTTP(S) and TCP routing from a centralized control plane via the Domain Manager API.
Overview¶
| Property | Value |
|---|---|
| Location | hub2 (OVH Dedicated Server) |
| Container | charliehub-traefik |
| Instances | 1 (unified ACME-only) |
| Ports | 80, 443 (HTTPS), 8883 (MQTT TCP), 8091 (dashboard) |
| URL | https://traefik.charliehub.net |
| Config | /opt/charliehub/traefik/config/ |
| Architecture | Single-writer (drift-proof) |
Architecture¶
Traffic Flow Overview¶
INTERNET
│
▼
┌───────────────────────┐
│ DNS: *.charliehub.net │
│ → 51.68.235.106 │
└───────────┬───────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────────┐
│ hub2 (OVH Dedicated) │
│ 51.68.235.106 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Traefik (Unified ACME) │ │
│ │ Single instance → All routing (HTTP + TCP) │ │
│ │ Port 80, 443, 8883 │ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────────────────┐ │ │
│ │ │ TLS Termination │ │ TCP Services │ │ │
│ │ │ + HTTP Routing │ │ (MQTT on :8883) │ │ │
│ │ │ │ │ (via tcp entrypoint) │ │ │
│ │ └────────┬────────────┘ └─────────────┬───────────────────┘ │ │
│ └────────────┼────────────────────────────────┼──────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────┐ ┌─────────────────────────────────┐ │
│ │ Docs, Grafana, │ │ parking-mosquitto │ │
│ │ Prometheus, UniFi, etc │ │ (MQTT broker) │ │
│ │ (HTTP services) │ │ │ │
│ └──────────────────────────┘ └─────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────────────┘
How Traefik + Domain Manager Work Together¶
Traefik handles all inbound HTTPS traffic from the internet. All routing (HTTP + TCP) is managed from a single PostgreSQL source via Domain Manager:
PostgreSQL domains table
↓
Domain Manager API (/api/domains/*)
↓
traefik_generator.py (v2.3+)
↓
/traefik/config/generated/routes.yml (atomic writes)
↓
Traefik routers (HTTP + TCP)
Example: UniFi API accessing UCG controllers
- User requests
https://unifi.charliehub.net/api/clients?controller=uk - Traefik terminates TLS, checks Authelia, routes to UniFi API container
- UniFi API needs to reach UK UCG at
10.44.1.29 - Traffic routes via WireGuard interface wg-uk to 10.44.x.x subnet
- Response flows back through the same path
Routing Management¶
Key Principle: Single Source of Truth¶
All routes are defined in PostgreSQL and managed via the Domain Manager API. Never edit /traefik/config/generated/routes.yml directly — it is generated from the database.
How to Add a Route¶
Use the Domain Manager API:
curl -X POST http://localhost:8001/api/domains \
-H "X-API-Key: charliehub" \
-H "Content-Type: application/json" \
-d '{
"domain": "myservice.charliehub.net",
"protocol": "http",
"service_type": "api",
"backend_host": "myservice",
"backend_port": 8080,
"environment": "production",
"auth_required": true,
"status": "active"
}'
The API validates the configuration, stores it in PostgreSQL, and automatically triggers route generation.
Generated Routes¶
Routes are generated to /traefik/config/generated/routes.yml:
http:
routers:
myservice-charliehub-net:
rule: Host(`myservice.charliehub.net`)
service: myservice-charliehub-net
entryPoints: [websecure]
tls:
certResolver: letsencrypt
middlewares:
- authelia@file
services:
myservice-charliehub-net:
loadBalancer:
servers:
- url: http://myservice:8080
TCP Routing¶
TCP routes (like MQTT) are managed the same way:
curl -X POST http://localhost:8001/api/domains \
-H "X-API-Key: charliehub" \
-d '{
"domain": "mqtt.verdegris.eu",
"protocol": "tcp",
"service_type": "tcp-proxy",
"tcp_entrypoint": "mqtt",
"backend_host": "parking-mosquitto",
"backend_port": 1883,
"status": "active"
}'
See CharlieHub TCP Routing for detailed TCP routing procedures.
Traefik Configuration¶
Static Configuration (Immutable)¶
# /opt/charliehub/traefik/config/traefik.yml
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
mqtt:
address: ":8883"
certificatesResolvers:
letsencrypt:
acme:
email: admin@charliehub.net
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
providers:
file:
directory: /config
watch: true
Key Points:
- Docker provider is disabled (routes managed via file provider only)
- File provider watches /config recursively (includes /config/generated/)
- ACME is the only certificate resolver (Let's Encrypt)
- TCP entrypoint mqtt defined here; used by Domain Manager routes
Dynamic Configuration (Generated)¶
Routes are generated to /traefik/config/generated/routes.yml and include:
- HTTP routers with Authelia middleware
- TCP routers with SNI-based routing
- Service definitions with load balancer backends
- Security headers and CORS middleware
Authentication Management¶
Overview¶
Traefik enforces Authelia authentication by default for all managed services. Authentication is controlled via the Domain Manager API using the auth_required field.
| auth_required | Behavior | Middleware | Use Case |
|---|---|---|---|
true (default) |
Requires Authelia login | authelia@file + security headers |
Internal/sensitive services |
false |
No authentication | Security headers only | Public services, public APIs |
Updating Authentication¶
# Disable authentication
curl -X PUT http://localhost:8001/api/domains/123 \
-H "X-API-Key: charliehub" \
-d '{"auth_required": false}'
# Re-enable authentication
curl -X PUT http://localhost:8001/api/domains/123 \
-H "X-API-Key: charliehub" \
-d '{"auth_required": true}'
Routes regenerate automatically.
Accessing Services from Homelab¶
The Problem¶
When a homelab VM/CT accesses docs.charliehub.net:
- DNS resolves to
51.68.235.106(hub2's public IP) - Traffic goes out via the UCG's WAN connection
- Arrives at hub2 from the site's public WAN IP (e.g.,
78.116.21.175) - Authelia sees the WAN IP, not the VM's internal IP
This breaks IP-based authentication bypass.
The Solution: Route via WireGuard¶
Configure local DNS on your UCG to route CharlieHub services via WireGuard:
| Domain | Points To | Notes |
|---|---|---|
*.charliehub.net |
10.44.x.x |
hub2's WireGuard IP (via wg-uk) |
On UniFi UCG: Settings → Networks → (select network) → DHCP → DNS Server → Add custom DNS entries
With this setup:
1. VM resolves docs.charliehub.net → 10.44.x.x
2. Traffic routes via WireGuard tunnel to hub2
3. Arrives at hub2 from 10.x.x.x (VM's actual IP)
4. Authelia bypass rules work correctly
Common Operations¶
View Active HTTP Routers¶
curl -s http://localhost:8091/api/http/routers | jq '.[].name'
View Active TCP Routers¶
curl -s http://localhost:8091/api/tcp/routers | jq '.[].name'
Check Certificate Status¶
curl -s http://localhost:8091/api/http/routers | jq '.[] | {name, tls}'
View Generated Routes¶
# Preview what was generated
cat /opt/charliehub/traefik/config/generated/routes.yml | head -50
View Logs¶
docker logs charliehub-traefik --tail 100 -f
Troubleshooting¶
404 Not Found¶
- Check router is registered:
curl http://localhost:8091/api/http/routers - Verify domain exists in database:
docker exec -i charliehub-postgres psql -U charliehub -d charliehub_domains -c "SELECT domain, status FROM domains WHERE domain='myservice.charliehub.net'" - Check status is
active(disabled routes don't generate)
502 Bad Gateway¶
- Backend container not running or unhealthy
- Wrong port in
backend_port - Network connectivity issue:
docker exec -i charliehub-postgres psql ... -c "SELECT backend_host, backend_port FROM domains ..."
Certificate Errors¶
# Check ACME status
docker exec -i charliehub-postgres psql -U charliehub -d charliehub_domains \
-c "SELECT domain, status FROM domains WHERE status='active' ORDER BY domain"
# Check Traefik logs for ACME errors
docker logs charliehub-traefik 2>&1 | grep -i acme
Routes Not Generating¶
# Manually trigger generation
docker exec charliehub_domain_manager_v3 python3 /app/services/traefik_generator.py
# Check for errors in output
Authelia Redirect Loop¶
- Service missing from Authelia bypass rules
- Cookie domain mismatch
- Check Authelia logs:
docker logs charliehub_authelia
Related¶
- Standards & Governance - Control plane rules
- Authelia SSO - Authentication configuration
- Domain Manager API - Domain management
- CharlieHub TCP Routing - TCP service routing
- WireGuard VPN - VPN connectivity
- Emergency Procedures - Recovery procedures
Last updated: 2026-02-12 | Architecture: Unified ACME, drift-proof