Documentation

Everything you need to expose localhost to the internet — install, authenticate, and tunnel in under a minute.

Introduction

poriq is an open-source tunneling tool that gives any local service a public HTTPS URL. Point it at a port and you get a shareable https://yourapp.poriq.run address with automatic TLS — no firewall changes, no deploy. It speaks HTTP, TCP, and UDP, and it is MIT-licensed and self-hostable.

A tunnel runs over a single persistent WebSocket between the CLI and the server, so connections survive flaky networks and reconnect on their own. Large uploads stream rather than buffer, and inner WebSockets (like a dev server's HMR socket) are proxied transparently.

Installation

Install from a GitHub Release or a package-manager wrapper. Release archives are checksummed and contain the same Go-built CLI binary.

brew install poriq/tap/poriq
npm install -g poriq
pipx install poriq-cli

poriq version
poriq doctor

Authentication

Sign in once with your GitHub account. This opens a browser device flow and stores an API token locally (~/.config/poriq/config.json).

poriq login
# → opens GitHub, enter the shown code
# → "logged in as <you>"

Check status or sign out at any time:

poriq status
poriq logout

Quick Start

Expose a local server running on port 3000:

poriq http 3000

  Tunnel established!
  Public URL:  https://bold-wren-204.poriq.run
  Forwarding:  https://bold-wren-204.poriq.run → http://localhost:3000
  Inspector:   http://localhost:2126

Share the public URL. Every request is forwarded to your local server and shown live in the terminal and the inspector.

HTTP Tunnels

poriq http is the workhorse. Pass one or more ports — multiple ports open multiple tunnels at once.

poriq http 3000                 # single tunnel
poriq http 3000 8080            # two tunnels
poriq http https://localhost:8443   # HTTPS local target (cert ignored)

Options

<port[:subdomain]>Local port to expose. Optionally pin a subdomain, e.g. 3000:myapp.
--newRequest a fresh random subdomain instead of reusing a saved one.
--inspect <port>Web inspector UI port (default 2126, 0 to disable).
--log <file>Append every request to a JSONL file for later replay.
--auth <user:pass>Protect the tunnel with HTTP Basic auth.
--allow-ip <list>Allow only these IPs/CIDRs (comma-separated).
--rate-limit <rps>Cap requests per second to your local server.
--rate-limit-path <path:rps>Per-path rate limit override (repeatable).
--mock <path:status:body>Return a canned response for a path (repeatable).
--rewrite <from:to>Rewrite a request path prefix before forwarding (repeatable).
--header-add / --header-removeAdd or strip request headers before forwarding.
--response-header-add / -removeAdd or strip headers on the response.
--wol <name=MAC|IPv4>Register a Wake-on-LAN target (repeatable).
--notify-on-errorDesktop notification on 5xx responses.
--timeout <dur>Local response timeout, e.g. 30s, 1m.
--drain-timeout <dur>Grace period for in-flight requests on shutdown (default 5s).
--quietSuppress the per-request log output.

TCP & UDP Tunnels

Forward raw TCP or UDP — SSH, databases, game servers, anything. These are available on paid plans and expose a host:port instead of an HTTPS URL.

poriq tcp 22      # → tunnel.poriq.run:10000 → localhost:22
poriq udp 51820   # WireGuard, DNS, game servers, …

Connect using the host and allocated port poriq prints on start.

Paid TCP and UDP tunnels automatically try to reconnect when the poriq agent or infrastructure restarts. Existing TCP/UDP sessions through the tunnel may still be interrupted during security updates, worker drain, maintenance, or failover, so applications should reconnect their own sessions when needed.

WebSockets & HMR

WebSocket upgrades are proxied bidirectionally over the same tunnel, so realtime apps and dev-server hot reload work out of the box.

One caveat for framework dev servers (Next.js, Vite, …): they reject cross-origin dev requests by default. Add your tunnel host to the dev-origin allowlist, e.g. in next.config.js:

// next.config.js
module.exports = {
  allowedDevOrigins: ["*.poriq.run"],
};

Custom Subdomains

Free tunnels get a random subdomain each session. Paid plans can reserve subdomains and reuse them. Pin one inline:

poriq http 3000:myapp     # → https://myapp.poriq.run

poriq remembers the subdomain per local URL, so the next run reuses it automatically. Pass --new to force a fresh one. Reserve and manage subdomains from the dashboard.

Request Inspector

Every HTTP tunnel ships a local web inspector (default http://localhost:2126) showing each request and response — headers, body, status, and timing.

poriq http 3000 --inspect 2126   # change the port
poriq http 3000 --inspect 0      # disable it

Log requests to a file and replay them later in the same UI:

poriq http 3000 --log requests.jsonl
poriq inspect requests.jsonl     # open the saved log

Config File

Drop a poriq.json in your project to avoid retyping flags. Generate a starter with poriq init.

{
  "port": 3000,
  "subdomain": "myapp",
  "tunnels": [{ "port": 3000 }, { "port": 8080 }],
  "inspect": 2126,
  "log": "requests.jsonl",
  "auth": "user:pass",
  "allow_ips": ["10.0.0.0/8"],
  "rate_limit": 50,
  "rate_limits": { "/api/webhook": 10 },
  "mocks": { "/health": { "status": 200, "body": "ok" } },
  "path_rewrites": { "/api/v1": "/v1" },
  "header_add": ["X-From: poriq"],
  "notify_on_error": true,
  "timeout": "30s"
}

Running poriq http with no arguments picks up this file.

Security & Access Control

Gate a tunnel without touching your app:

poriq http 3000 --auth admin:s3cret           # HTTP Basic auth
poriq http 3000 --allow-ip 1.2.3.4,10.0.0.0/8 # IP allowlist
poriq http 3000 --rate-limit 50               # 50 req/s cap
poriq http 3000 --rate-limit-path /api/webhook:10

These run at the edge of your tunnel, so blocked requests never reach your local server.

Traffic Shaping

Mock endpoints, rewrite paths, and rewrite headers on the fly:

# Canned response (path:status:body)
poriq http 3000 --mock /health:200:ok

# Rewrite a path prefix before forwarding
poriq http 3000 --rewrite /api/v1:/v1

# Add / strip headers
poriq http 3000 --header-add "X-Env: tunnel" \
                --response-header-remove "X-Powered-By"

Wake-on-LAN

Register Wake-on-LAN targets so you can boot machines on your LAN remotely through the tunnel (and the dashboard).

poriq http 3000 --wol "desktop=192.168.1.20"
poriq http 3000 --wol "desktop=AA:BB:CC:DD:EE:FF"

IPv4 lookup uses your local ARP/neighbor cache at startup. poriq only sends magic packets for MACs explicitly registered or resolved on the tunnel client machine.

Plans & Limits

Free

$0
  • 2 HTTP tunnels
  • Random subdomains
  • Short sessions, manual reconnect
  • 50 MB / day
  • 5K requests / day

Pro

$5/mo
  • 5 HTTP + 2 TCP
  • 3 custom subdomains
  • Configurable TTL, default off
  • 2 GB / day
  • 100K requests / day

Team

$15/mo
  • 10 HTTP + 5 TCP
  • 10 custom subdomains
  • Configurable TTL, default off
  • 10 GB / day
  • 1M requests / day

Paid plans can still be limited by server policy. The normal paid default is TTL off, while trial, promo, and PoC deployments can use explicit TTLs such as 1h or 8h. TCP/UDP inherit the same duration policy when a plan sets one.

Auto-reconnect restores the tunnel endpoint after restarts or failover, but it does not preserve already-established TCP or UDP application sessions.

HTTP request bodies stream up to 100 MB. Self-hosted operators can tune plan limits, port exposure, and retention policy for their own infrastructure. See pricing for hosted limits.

Self-Hosting

poriq is MIT-licensed and runs as a single server binary. The safe default is HTTP-only behind a reverse proxy; TCP and UDP are opt-in.

PORIQ_DOMAIN=poriq.example.com \
PORIQ_BIND=127.0.0.1 \
PORIQ_PORT=8080 \
PORIQ_DB=/var/lib/poriq/poriq.db \
poriq-server

poriq-server doctor

Point clients at it with --server wss://poriq.example.com. Full guide on GitHub.

CLI Reference

poriq login              authenticate with GitHub
poriq logout             remove saved credentials
poriq status             show auth status
poriq http <port...>     create HTTP tunnel(s)
poriq tcp  <port>        create a TCP tunnel
poriq udp  <port>        create a UDP tunnel
poriq inspect <file>     view a saved request log
poriq init               create a poriq.json config
poriq version            show version info

Run any command with --help to see its full flag set.

Ready to tunnel? Sign in with GitHub and run poriq http 3000.

Get Started — Free