Skip to content

Pangolin tunnel

Use Pangolin (server) and Newt (client) to expose a local or staging service on the public internet. This is the standard way to handle callbacks, demos, and temporary external access.

Internet -> Pangolin -> Newt -> App

The tunnel.sh helper creates the site + public subdomain, runs Newt, and tears everything down on Ctrl-C. No dashboard or admin role needed:

Terminal window
curl -fsSL -o tunnel.sh \
https://gitlab.d-centralize.nl/dc/dcentralize/infra/-/raw/main/source/services/pangolin/tunnel.sh
chmod +x tunnel.sh
export PANGOLIN_API_TOKEN="$(bw get password 'pangolin developers tunnel token')"
./tunnel.sh my-demo 3000
# -> https://my-demo.tunnel.d-centralize.nl forwards to localhost:3000

It needs curl + jq (downloads Newt on first run). The subdomain is public by default; pass --auth to put it behind Pangolin login instead.

Open https://pangolin.tunnel.d-centralize.nl and click Sign in with Keycloak (your normal d-centralize account). In the Community Edition we run, the management UI (sites, resources, settings) is reserved for the Admin role, so most people see a read-only portal — use tunnel.sh above for day-to-day tunnels. If you need the dashboard for oversight, ask in #infra to be granted the org Admin role.

For a persistent subdomain or a CI job, apply a Pangolin blueprint with an integration API token, then start Newt. newt has no separate reserve-only command.

public-resources:
app:
name: app
protocol: http
full-domain: my-fixed-subdomain.tunnel.d-centralize.nl
targets:
- site: my-site
hostname: localhost
method: http
port: 3000

Apply via the API (PUT /org/d-centralize/blueprint, Bearer token) or the Pangolin CLI (pangolin login / pangolin select / pangolin apply blueprint --file blueprint.yaml). Then run Newt with the site’s NEWT_ID / NEWT_SECRET and PANGOLIN_ENDPOINT=https://pangolin.tunnel.d-centralize.nl:

Terminal window
curl -fsSL https://pangolin.net/get-newt.sh | bash
newt # or `newt &` from an entrypoint script

CI orchestrators do exactly this with a per-project PANGOLIN_API_TOKEN; see the tools/pangolin/site_lifecycle.sh helper in pro6pp-world.

Ephemeral, CI, and temporary tunnels follow a company-wide naming convention: name the site (and any blueprint resource you create for it) with a temp- prefix. The pangolin-site-janitor on the tunnel host reaps any offline temp- site after a single 24-hour offline window, so leaked sites from killed/cancelled jobs do not pile up.

public-resources:
temp-my-job-${CI_PIPELINE_ID}: # niceId carries the prefix too
name: temp-my-job-${CI_PIPELINE_ID}
protocol: http
full-domain: my-job-${CI_PIPELINE_ID}.tunnel.d-centralize.nl
targets:
- hostname: localhost
port: 8080

The public subdomain (full-domain) is independent of the site name, so it can stay human-readable. Persistent, long-lived tunnels (services, demos kept around) must not use the temp- prefix — the janitor never touches them.

A public resource (the tunnel.sh default) is reachable without Pangolin login, which is what you want for webhooks and third-party callbacks. Via the API, set sso:false on the resource (POST /resource/{id}); in the dashboard (admins), open the resource’s Authentication tab and disable Use platform SSO.