Expose a Traefik reverse proxy through Pinggy
Traefik is a dynamic reverse proxy that auto-discovers services running in Docker, Kubernetes, or static configuration files and routes incoming HTTP/HTTPS traffic to them based on rules such as Host headers and path prefixes. Running Traefik locally is convenient - you can spin up several containerised services and address each by hostname - but those hostnames only resolve on your own machine.
Pinggy solves the public-reachability half of the problem. By tunnelling Traefik’s entry point, every backend Traefik already routes to becomes reachable from the internet through one URL.
Step 1: Run Traefik locally
A minimal docker-compose.yml that starts Traefik on port 80 and enables the dashboard looks like this:
services:
traefik:
image: traefik:v3.0
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--api.insecure=true"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Start the stack with docker compose up -d and confirm Traefik answers on http://localhost:80.
Step 2: Register backend services
Tag each service container with Traefik labels so it can be discovered. For example, an nginx container served at app.localhost:
app:
image: nginx
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.localhost`)"
- "traefik.http.services.app.loadbalancer.server.port=80"
Step 3: Tunnel Traefik’s web entry point
Open a Pinggy HTTP tunnel pointing at the port Traefik listens on:
ssh -p 443 -R0:localhost:80 free.pinggy.io
Pinggy returns a hostname such as https://abcd1234.a.pinggy.link. Every request to that URL is forwarded to Traefik, which then dispatches based on its routing rules.
Step 4: Match Traefik rules against the Pinggy hostname
Traefik routes on the incoming Host header. When traffic arrives through Pinggy, the header is the Pinggy hostname - not app.localhost. Two practical options:
- Catch-all rule: use
HostRegexp to match any hostname, e.g. traefik.http.routers.app.rule=HostRegexp({any:.+}). Useful when only one backend is exposed. - Path-based routing: route by path prefix instead of host, e.g.
PathPrefix(/app) and PathPrefix(/api), so a single Pinggy URL can fan out to multiple services.
For multi-tenant setups, configure a custom domain so Pinggy delivers traffic on a stable hostname that your Traefik rules can match exactly.