serve_app¶
Expose a local development server to the internet via a reverse SSH tunnel through your VPS.
Usage¶
Tunnel → Port Table¶
| Tunnel Name | VPS Port | Public URL |
|---|---|---|
tunnel1 |
9201 | https://tunnel1.mpltr.app |
tunnel2 |
9202 | https://tunnel2.mpltr.app |
tunnel3 |
9203 | https://tunnel3.mpltr.app |
The VPS user is tunnels at 100.75.34.115.
Examples¶
# Expose a local Next.js dev server (port 3000) via tunnel1
serve_app 3000 tunnel1
# Expose a Vite dev server (port 5173) via tunnel2
serve_app 5173 tunnel2
Architecture¶
Request Flow¶
sequenceDiagram
participant Browser
participant DNS
box Hetzner VPS (65.21.243.161)
participant nginx
participant Tailscale
end
participant dev as Dev Server (local)
Browser->>DNS: tunnel1.mpltr.app
DNS-->>Browser: 65.21.243.161
Browser->>nginx: HTTPS :443
Note over nginx: SSL termination
nginx->>nginx: proxy to 127.0.0.1:9201
Note over nginx,dev: ssh -R binds VPS :9201 → local :8000
nginx->>Tailscale: Tailnet (100.75.34.115)
Tailscale->>dev: localhost:8000
dev-->>Tailscale: Response
Tailscale-->>nginx: Response
nginx-->>Browser: Response
How It Works¶
- Maps the tunnel name to a high-numbered VPS port (9201–9203).
- Opens a reverse SSH tunnel:
ssh -N -R 127.0.0.1:<vps_port>:localhost:<local_port> tunnels@100.75.34.115. - Traffic hitting the VPS port is forwarded back to your local port via Tailscale.
Infrastructure¶
- Domain: mpltr.app —
tunnel{1,2,3}.mpltr.appA records point to the VPS - Server: VPS: Tunnel & Docs — Hetzner VPS running nginx + Certbot, Tailscale connected
Tailscale must be running locally to connect. The SSH tunnel uses the Tailscale IP (100.75.34.115), not the public IP.
Notes¶
- The tunnel runs in the foreground —
Ctrl+Cto stop. - Only three tunnels are available. Use different tunnel names for concurrent services.