porthole exposes your local server to the internet through a persistent WebSocket tunnel. No accounts, no paid plans, no third-party infrastructure โ run your own server or use ours.
Or: brew install porthole ยท requires macOS
$ porthole 3000 --subdomain staging
ย
porthole v1.0.0
ย
Your public URL is:
ย
https://staging.porthole.devbench.co.in
ย
Forwarding โ http://localhost:3000
ย
GET/2008ms
POST/api/auth/login200134ms
GET/api/users20022ms
GET/static/bundle.js3043ms
โโ
How it works
porthole keeps a persistent WebSocket open from your machine to the server. HTTP requests for your subdomain travel down that socket and land on your local process.
Browser
anywhere
porthole server
porthole.devbench.co.in
porthole CLI
your machine
localhost:3000
your app
Install the porthole CLI via npm or Homebrew. Requires Node 18+ (or use the standalone binary โ no Node needed).
npm i -g @porthole-tunnel/cli
Run porthole with the port of your local server. The CLI opens a WebSocket to the porthole server and gets assigned a subdomain.
porthole 3000
Copy the public URL. Anyone on the internet can now hit your local server. Requests are tunnelled over the WebSocket in real time.
https://swift-fox-0042 .porthole.devbench.co.in
Features
One command. No config files, no sign-up, no credit card. porthole <port> and you are live.
Network blip? The CLI detects dead connections via WebSocket ping/pong and reconnects with exponential backoff.
Set AUTH_TOKEN on your server. Clients pass --token to connect. Everything else is rejected at the handshake.
Request a memorable name: porthole 3000 --subdomain staging. Great for sharing with teammates or clients.
Mac users install in one line. No Node.js required โ pkg bundles the runtime into a single self-contained binary.
50 MB body cap, heartbeat keep-alive, immediate request drain on disconnect, graceful SIGTERM shutdown.
Quick start
Install globally
npm install -g @porthole-tunnel/cli
Expose port 3000
porthole 3000
Custom subdomain + open browser
porthole 3000 --subdomain my-demo --open
Use a private server
porthole 3000 \ --server https://porthole.devbench.co.in \ --token mysecret
Add tap
brew tap SaiBhargavRallapalli/porthole
Install
brew install porthole
Use
porthole 3000
โ No Node.js required
The Homebrew formula installs a self-contained binary bundled with the Node.js runtime. Works on Apple Silicon and Intel Macs.npm packages
porthole ships as a monorepo. The CLI is what you run locally; the server is what you deploy.
@porthole-tunnel/cli
The tunnel client you run on your machine. Connects to the porthole server over WebSocket, proxies requests to your local port, and streams responses back. Auto-reconnects on network failure.
npm install -g @porthole-tunnel/cli
@porthole-tunnel/server
The always-on server that receives public HTTP traffic and tunnels it to registered CLI clients. Deploy it on Railway, Render, Fly.io, or any VPS. Needs wildcard DNS pointing to it.
npm install @porthole-tunnel/server
CLI reference
| Flag | Description |
|---|---|
| <port> | Local port to expose |
| -s, --subdomain <name> | Request a specific subdomain (e.g. my-demo) |
| --server <url> | porthole server URL |
| --local-host <host> | Local hostname to forward requests to |
| --token <token> | Auth token (required if server has AUTH_TOKEN set) |
| --open | Open the public URL in your browser after connecting |
| --print-requests | Print each forwarded request and response inline |
| -V, --version | Print CLI version |
Self-host
porthole is fully self-hostable. The tunnel server runs on any platform that supports persistent Node.js processes. Vercel is for the landing page only โ the tunnel server needs an always-on host like Railway, Render, or Fly.io.
git clone https://github.com/SaiBhargavRallapalli/porthole
On Railway: railway up. On Render: connect the repo and set Root Directory to packages/server.
# DNS records for porthole.devbench.co.in
porthole.devbench.co.in CNAME cname.vercel-dns.com # landing page
*.porthole.devbench.co.in A YOUR_SERVER_IP # tunnel server
porthole 3000 \ --server https://porthole.devbench.co.in
| Variable |
|---|
PORT HTTP port the server listens on |
DOMAIN Public base domain (subdomains are carved from this) |
AUTH_TOKEN If set, all tunnel registrations must supply this token |
MAX_BODY_BYTES Maximum request / response body size in bytes |
โ ๏ธ Vercel limitation
The tunnel server requires persistent WebSocket connections โ Vercel functions time out after 10โ300s. Deploy the server on Railway, Render, or a VPS. Only this landing page runs on Vercel.