Skip to content
/ pgrok Public

Personal ngrok alternative. Expose local ports to the internet with automatic HTTPS via SSH tunnels + Caddy.

Notifications You must be signed in to change notification settings

R44VC0RP/pgrok

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pgrok

Personal ngrok alternative. Expose local ports to the internet with automatic HTTPS, an interactive TUI dashboard, and HTTP request inspection -- all through your own VPS.

image

Quick Start

Prerequisites

  • A VPS (any provider) with ports 80 and 443 open (nothing else running on them for now)
  • Docker + Docker Compose on the VPS
  • A domain name you control
  • An SSH key on your Mac/Linux (You can run ssh-keygen to generate one if you don't have one)

1. DNS Setup: Point your domain at the VPS

Add a wildcard A record with your DNS provider (Cloudflare, Vercel, Namecheap, etc):

Type Name Value
A * <your-vps-ip>

2. Client Setup: Install on your Mac/Linux (run this first)

curl -fsSL https://raw.githubusercontent.com/R44VC0RP/pgrok/main/install.sh | bash -s client

(if you have a windows machine, and you get this running, please open a PR!)

You'll be prompted for your VPS IP, domain, and email. The installer will:

  • Auto-detects your SSH key
  • Builds and installs the pgrok command
  • Copies a server setup command to your clipboard (with your SSH key embedded)

3. Server -- Set up your VPS

SSH into your VPS and paste the command from step 2. Or run:

curl -fsSL https://raw.githubusercontent.com/R44VC0RP/pgrok/main/install.sh | sudo bash -s server

The script installs Caddy, configures SSH tunneling, adds your SSH key, and starts everything.

4. Use it

pgrok myapp 4000
# => https://myapp.yourdomain.com -> localhost:4000

Usage

# Expose a local dev server
pgrok myapp 4000
# -> https://myapp.yourdomain.com

# Expose an API
pgrok api 3000
# -> https://api.yourdomain.com

# Any subdomain works instantly
pgrok staging 8080
# -> https://staging.yourdomain.com

# Debug mode -- dumps raw tunnel logs on exit
pgrok myapp 4000 --print-logs

Press Ctrl+C to stop. The route is cleaned up automatically.

Rebuild the binary after pulling updates:

./setup.sh client --rebuild

How it works

image
  • Caddy on the VPS handles HTTPS with on-demand TLS -- certs are auto-provisioned per subdomain. Falls back to ZeroSSL if Let's Encrypt is rate-limited.
  • SSH reverse tunnels carry traffic -- no extra tunnel software.
  • A small Python script on the server dynamically configures Caddy routes when tunnels connect/disconnect.
  • The TUI client (built with OpenTUI) provides a live dashboard with request inspection, connection stats, and color-coded HTTP logs.

TUI Dashboard

The dashboard shows in real-time:

  • Session Status -- connecting / provisioning TLS / online / error
  • Forwarding -- your public URL and local port
  • TLS Certificate -- provisioning status (Let's Encrypt)
  • Connection Stats -- total requests, open connections, request rates (1m/5m), response time percentiles (p50/p90)
  • HTTP Request Log -- scrollable, color-coded log of every request through the tunnel

Request log colors:

  • Methods: GET (blue), POST (purple), PUT/PATCH (yellow), DELETE (red)
  • Status: 2xx (green), 3xx (cyan), 4xx (yellow), 5xx (red)
  • Duration: <100ms (green), 100-500ms (yellow), >500ms (red)

How SSL Works

  1. A request arrives for myapp.yourdomain.com
  2. Caddy checks with pgrok-ask: "Should I get a cert for this domain?"
  3. pgrok-ask verifies it's a single-level subdomain of *.yourdomain.com
  4. Caddy uses HTTP-01 challenge to get a cert -- tries Let's Encrypt first, falls back to ZeroSSL if rate-limited
  5. Cert is cached and auto-renewed
  6. The TUI client triggers cert provisioning during tunnel setup, so it's ready before you open the URL

Security

  • SSH key authentication only (no passwords)
  • Dedicated pgrok user with restricted SSH (remote forwarding only)
  • Caddy admin API only on localhost (not exposed externally)
  • SSH tunnels bind to localhost only (GatewayPorts no)
  • pgrok-ask prevents cert abuse -- only allows single-level subdomains

Configuration

Client (~/.pgrok/config)

Generated by the installer. Edit manually if needed:

PGROK_HOST=your-vps-ip
PGROK_DOMAIN=yourdomain.com
PGROK_USER=pgrok
PGROK_SSH_KEY=~/.ssh/id_ed25519

Server (/opt/pgrok/)

File Purpose
Caddyfile On-demand TLS config with LE + ZeroSSL
docker-compose.yml Caddy container
Script (/usr/local/bin/) Purpose
pgrok-tunnel Manages Caddy routes + provisions TLS certs
pgrok-ask Validates cert requests (systemd service)

Troubleshooting

Stuck on "connecting" in the TUI:

  • Run with --print-logs, press Ctrl+C, check /tmp/pgrok-debug.log
  • Verify SSH works: ssh pgrok@your-vps-ip echo ok

Stuck on "provisioning TLS...":

  • Let's Encrypt may be rate-limited (50 certs/week). ZeroSSL fallback handles this.
  • Check Caddy logs: docker compose logs caddy in /opt/pgrok

SSL certificate errors:

  • Verify pgrok-ask is running: systemctl status pgrok-ask
  • Make sure ports 80 and 443 are open
  • Cloudflare proxy (orange cloud) must be OFF for the wildcard record

Development

cd client/tui
bun install
bun run index.ts myapp 4000    # dev mode
bun run build                   # compile binary
bun run tsc --noEmit            # type-check

Limitations

  • Single user (personal tool, not multi-tenant)
  • Mac and Linux only (no Windows)
  • No automatic reconnection (restart pgrok if connection drops)
  • Stale routes possible on abrupt disconnection (self-heal on next connect)
  • HTTP request logging only (WebSocket passthrough works but isn't logged)

CONTRIBUTING

We welcome contributions! Please open an issue or PR.

LICENSE

MIT

About

Personal ngrok alternative. Expose local ports to the internet with automatic HTTPS via SSH tunnels + Caddy.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published