docs: add a Pangolin example - #61
Conversation
Pangolin drives a Traefik v3 instance whose dynamic configuration it generates from its own database, so no Pangolin-specific plugin is needed. What is Pangolin-specific is how the middleware gets attached to a resource, which is what this example demonstrates. The stack runs Pangolin, Traefik (with the badger and sablier plugins), Sablier and a mimic workload on one Docker host, using a Pangolin "Local" site so no tunnel is involved. setup.sh bootstraps the admin, org, site and resource through Pangolin's API. Both attachment options are covered: the global `traefik.additional_middlewares` knob used by the example, and a higher-priority router in the file provider that reuses Pangolin's generated service for per-resource control. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pangolin has no per-resource middleware field, so the example previously relied on `traefik.additional_middlewares`, which applies to every resource in the install. Middleware Manager -- a community service listed in Pangolin's own docs -- reads resources from Pangolin's internal API and re-serves Traefik's dynamic configuration with middlewares attached per resource, which is what the example now demonstrates. Traefik's http provider points at Middleware Manager instead of Pangolin, and setup.sh attaches `sablier-mimic@file` to the single resource through its API. Documents all three attachment options with their trade-offs, including one that is easy to get wrong: Middleware Manager always places its additions before the router's existing middlewares, so Sablier runs before `badger` and an unauthenticated request can wake the container. The `priority` field only orders its own assignments and cannot move one after `badger` -- verified against priorities 1 and -100. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Pushed an update: the example now attaches Sablier per-resource via Middleware Manager rather than through the global Middleware Manager is listed in Pangolin's own community guides. It reads resources from Pangolin's internal API and re-serves Traefik's dynamic configuration with middlewares attached per resource, so Traefik's http provider now points at it instead of at Pangolin. Correction to an earlier claimThe original PR said Middleware Manager unconditionally places its own additions before the router's existing middlewares (config_proxy.go — "Merge middlewares (MW-manager additions first, then existing)"), and The The practical consequence is that an unauthenticated request can wake the container. Harmless for this public demo, but it matters on a zero-trust proxy, so the README now documents all three options as an explicit trade-off:
Also noted: Traefik's entire dynamic config now comes from Middleware Manager, so if that container stops, Traefik loses every Pangolin-generated router — not just the Sablier attachment. VerifiedClean-slate run: 🤖 Generated with Claude Code |
Adds a runnable example showing Sablier waking a container from a real Pangolin resource.
Pangolin isn't a reverse proxy of its own — it drives a Traefik v3 instance whose dynamic configuration it generates from its own database. So there's no Pangolin-specific plugin to build: this is the existing Traefik plugin, loaded next to Pangolin's own
badger. What is Pangolin-specific is how the middleware gets attached to a resource, which is what the example is really about.What's in it
examples/pangolin/runs Pangolin 1.21.1, Traefik v3.7 (with thebadgerandsablierplugins), Sablier and amimicworkload on a single Docker host. It uses a Pangolin Local site, so nogerbil/newttunnel is involved.setup.shbootstraps the server admin, org, site and resource through Pangolin's API so the example works without clicking through the dashboard — the UI path is documented too.Also adds a Pangolin section to the main README, under Usage.
Both attachment options are covered
Pangolin builds every router's chain as
[badger, ...traefik.additional_middlewares]and has no per-resource middleware field. So:traefik.additional_middlewaresknob. Clean and fully supported, but it applies to every HTTP resource — fine for one Sablier group, doesn't scale to a second app.@httpreference. This is what anyone with more than one app needs.Verified
Ran the stack from a clean slate. The generated router comes back as:
{ "name": "1-mimic-router@http", "rule": "Host(`mimic.localhost`)", "middlewares": ["badger@http", "sablier-mimic@file"], "service": "1-mimic-service", "priority": 100 }Full lifecycle confirmed: first request → Sablier waiting page → container started and healthy →
Mimic says hello!→ after 1m idle,instance expiredand the container stops.Option B was verified separately: a priority-1000 file-provider router referencing
1-mimic-service@httptakes over and serves the waiting page correctly.Notes for reviewers
.gitignorehas a baretraefikrule (presumably for a downloaded binary), which silently swallowedexamples/pangolin/config/traefik/. I negated it in the example's own.gitignorerather than touching the shared rule — but anchoring it to/traefikinstead would probably be the better fix.gerbilconfig block turns out to be required even with no tunnel, hence the commented block inconfig/config.yml.Companion docs PR in the main repo: sablierapp/sablier#1091 (closes sablierapp/sablier#1040)
🤖 Generated with Claude Code