Expose a local HTTP server to the internet with one command. No accounts, no dashboard.
openhole 3000https://blue-fox.ophl.link → http://localhost:3000
Current version: v0.2.1 · Full documentation · openhole.dev/docs
| Feature | Description |
|---|---|
| One-command tunnels | Public HTTPS URL for any local port |
| WebSocket passthrough | Next.js HMR, Vite, Socket.IO (v0.2.0+) |
| Multi-tunnel | openhole 3000 8080 — multiple ports, one process |
| Named subdomains | --subdomain myapp with reclaim tokens |
| Config file | ~/.config/openhole/config.yaml |
| Registration tokens | --token for self-hosted servers |
| Request logs | openhole logs -f --json |
| Cross-platform | macOS, Linux, Windows (amd64 + arm64) |
| Self-hosting | Docker Compose + Caddy + wildcard TLS |
# Install (macOS / Linux)
curl -fsSL https://openhole.dev/install.sh | sh
# Windows (PowerShell)
irm https://openhole.dev/install.ps1 | iex
# Expose port 3000
openhole 3000See Getting started for a full walkthrough.
| Guide | Description |
|---|---|
| docs/README.md | Documentation index |
| Getting started | Install and first tunnel |
| Installation | All install methods |
| CLI usage | Ports, config, tokens, multi-tunnel |
| Commands | status, logs, update, flags |
| WebSocket passthrough | HMR and real-time apps |
| Configuration | Flags, env, config.yaml, server vars |
| Self-hosting | Docker, DNS, registration tokens |
| Security | Threat model and limits |
| Package managers | Homebrew, Scoop, apt |
Website: openhole.dev/docs
openhole 3000 # random subdomain
openhole 3000 --subdomain myapp # stable URL
openhole 3000 8080 # multiple ports
openhole 3000 --token secret # protected server
openhole status # active tunnels
openhole logs -f # follow request log
openhole update # self-updateConfig file (~/.config/openhole/config.yaml):
server: wss://tunnel.myteam.dev/tunnel
host: localhost
subdomain: myapp
token: your-secretInternet → Caddy (TLS) → openhole-server ←WebSocket→ openhole CLI → localhost:PORT
- CLI registers a subdomain over WebSocket.
- HTTPS traffic hits
https://<subdomain>.<domain>. - Server forwards HTTP requests and WebSocket upgrades to your CLI.
- CLI proxies to your local app.
cd deployments && cp env.example .env
# Set CLOUDFLARE_API_TOKEN, domains, etc.
docker compose up -d --buildexport OPENHOLE_SERVER_URL=wss://tunnel.yourdomain.com/tunnel
openhole 3000 --token your-secret # if REGISTRATION_TOKENS is setFull guide: docs/self-hosting.md
go test -race -count=1 ./...
./scripts/build.sh
./scripts/release.sh v0.2.1Website:
cd website && npm install && npm run devSee CONTRIBUTING.md and SECURITY.md.
MIT — see LICENSE.