Skip to content

Instantly share code, notes, and snippets.

@waltervargas
Created April 4, 2026 00:45
Show Gist options
  • Select an option

  • Save waltervargas/a7a7726c7c01514ccf6d47f74cf97c3e to your computer and use it in GitHub Desktop.

Select an option

Save waltervargas/a7a7726c7c01514ccf6d47f74cf97c3e to your computer and use it in GitHub Desktop.
Adding pong.walt3r.dev as a CNAME alias via Traefik cross-provider routing

Adding pong.walt3r.dev as a CNAME alias

Current Architecture

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]
Loading

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)
Loading

The CNAME Alias

Instead of modifying the CI workflow, we add a file-based router in Traefik that references the docker-provider service using the @docker suffix.

~/traefik/dynamic/pong.yml

http:
  routers:
    pong:
      rule: "Host(`pong.walt3r.dev`)"
      service: karenbolon-transcendence-main@docker
      entryPoints:
        - web

How it works

graph 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]
Loading

Key detail: cross-provider references

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).

Steps

  1. Cloudflare DNS — Add a CNAME record: pong pointing to the tunnel target (same as other *.walt3r.dev subdomains)
  2. Traefik — Create ~/traefik/dynamic/pong.yml on the server with the config above
  3. Done. No restart needed, no workflow changes.
@allthetimeintheworld

Copy link
Copy Markdown

Why Thank you Walter!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment