Open source ยท Self-hosted ยท MIT license

Your localhost, on the internet.

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.

$npm install -g @porthole/cli

Or: brew install porthole ยท requires macOS

zsh โ€” porthole

$ 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

โ–Œโ–ˆ

A tunnel in three steps

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

HTTPS requestโ†’

porthole server

porthole.devbench.co.in

WebSocketโ†โ†’

porthole CLI

your machine

HTTPโ†’

localhost:3000

your app

01

Install

Install the porthole CLI via npm or Homebrew. Requires Node 18+ (or use the standalone binary โ€” no Node needed).

npm i -g @porthole/cli
02

Connect

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
03

Share

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

Everything you need

โšก

Zero configuration

One command. No config files, no sign-up, no credit card. porthole <port> and you are live.

๐Ÿ”„

Auto-reconnect

Network blip? The CLI detects dead connections via WebSocket ping/pong and reconnects with exponential backoff.

๐Ÿ”’

Optional auth

Set AUTH_TOKEN on your server. Clients pass --token to connect. Everything else is rejected at the handshake.

๐Ÿท

Custom subdomains

Request a memorable name: porthole 3000 --subdomain staging. Great for sharing with teammates or clients.

๐Ÿบ

Homebrew support

Mac users install in one line. No Node.js required โ€” pkg bundles the runtime into a single self-contained binary.

๐Ÿ›ก

Production hardened

50 MB body cap, heartbeat keep-alive, immediate request drain on disconnect, graceful SIGTERM shutdown.

Up and running in 30 seconds

via npm

Install globally

npm install -g @porthole/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
๐Ÿบvia Homebrew (macOS)

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.

Two packages, one tunnel

porthole ships as a monorepo. The CLI is what you run locally; the server is what you deploy.

@porthole/cli

The CLI tool

v1.0.0

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.

โœ“ WebSocket tunnel client
โœ“ Auto-reconnect + backoff
โœ“ Request/response logging
โœ“ Auth token support
โœ“ --open flag
โœ“ Homebrew binary
npm install -g @porthole/cli

@porthole/server

The tunnel server

v1.0.0

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.

โœ“ HTTP + WebSocket server
โœ“ Wildcard subdomain routing
โœ“ Heartbeat keep-alive
โœ“ Body size limits
โœ“ Auth token gating
โœ“ Graceful shutdown
npm install @porthole/server

All options

FlagDescription
<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)
--openOpen the public URL in your browser after connecting
--print-requestsPrint each forwarded request and response inline
-V, --versionPrint CLI version

Run your own server

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.

Deploy the tunnel server

1

Clone the repo

git clone https://github.com/SaiBhargavRallapalli/porthole
2

Deploy packages/server to Railway or Render

On Railway: railway up. On Render: connect the repo and set Root Directory to packages/server.

3

Configure wildcard DNS

# 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

4

Connect your CLI to your own server

porthole 3000 \
  --server https://porthole.devbench.co.in

Environment variables

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.