graph LR
Client -->|HTTPS| CF[Cloudflare Tunnel]
CF -->|:8080| TF[Traefik]
TF -->|"Host(apps.walt3r.dev)"| PD[permitd :8081]
TF -->|"Host(*.walt3r.dev) via labels"| PODS[App Pods]
Traefik has two providers:
- Docker (Podman) — reads labels from running pods (
exposedByDefault: false) - File — watches
~/traefik/dynamic/for YAML configs
The CI workflow creates pods with Traefik labels that auto-register a router + service:
sequenceDiagram
participant GH as GitHub Actions
participant PM as Podman
participant TF as Traefik
GH->>PM: Create pod "karenbolon-transcendence-main"<br/>with traefik labels
PM-->>TF: Pod appears on "apps" network
TF->>TF: Reads labels → registers<br/>router: Host(karenbolon-transcendence-main.walt3r.dev)<br/>service: karenbolon-transcendence-main (port 3000)
Instead of modifying the CI workflow, we add a file-based router in Traefik that references the docker-provider service using the @docker suffix.
http:
routers:
pong:
rule: "Host(`pong.walt3r.dev`)"
service: karenbolon-transcendence-main@docker
entryPoints:
- webgraph TD
subgraph Cloudflare
DNS[pong.walt3r.dev CNAME]
TUNNEL[Cloudflare Tunnel]
end
subgraph "Traefik :8080"
subgraph "File provider (~/traefik/dynamic/)"
R_PERMITD["Router: permitd<br/>Host(apps.walt3r.dev)"]
R_PONG["Router: pong<br/>Host(pong.walt3r.dev)"]
S_PERMITD["Service: permitd<br/>→ host:8081"]
end
subgraph "Docker provider (podman labels)"
R_AUTO["Router: karenbolon-transcendence-main<br/>Host(karenbolon-transcendence-main.walt3r.dev)"]
S_AUTO["Service: karenbolon-transcendence-main<br/>→ pod:3000"]
end
end
DNS --> TUNNEL --> R_PONG
R_PONG -->|"@docker cross-provider ref"| S_AUTO
R_AUTO --> S_AUTO
R_PERMITD --> S_PERMITD
S_AUTO --> POD[Transcendence Pod]
S_PERMITD --> PD[permitd]
Traefik merges config from all providers. A file-based router can reference a docker-provider service by appending @docker:
service: karenbolon-transcendence-main@docker
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^
service name from pod labels provider qualifier
This means the file config acts as a pure alias — no changes to the CI workflow, and Traefik picks it up immediately (watch: true).
- Cloudflare DNS — Add a CNAME record:
pongpointing to the tunnel target (same as other*.walt3r.devsubdomains) - Traefik — Create
~/traefik/dynamic/pong.ymlon the server with the config above - Done. No restart needed, no workflow changes.
Why Thank you Walter!!