Skip to content
koltyakovPublic

About

πŸš€ Self-hosted HTTP tunnel for exposing local apps and static sites with automatic HTTPS, built-in WAF, and a real-time terminal dashboard

Topics

Resources

Contributing

Security policy

Stars

7 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

235 Commits

Folders and files

Repository files navigation

expose

expose logo

expose is a self-hosted HTTP tunnel. Run your own server, then expose local HTTP ports from any machine - no third-party tunnel service required.

expose client

Features

  • HTTPS-only public traffic with automatic TLS (ACME) or static wildcard certificates
  • Built-in WAF blocks SQL injection, XSS, path traversal, and other attacks before they reach your app, including bounded JSON/form/text body inspection
  • Static site publishing via expose static for quick docs, SPAs, and local folders
  • Server-hosted static sites via expose pub, with persistent URLs, optional expiry, guarded archive uploads, and live stats via expose pub connect
  • Multi-route configs via expose.yml - expose multiple services under one subdomain with path-based routing
  • Server-local services via EXPOSE_BYPASSES - reserve subdomains for local HTTP ports, with WAF enabled by default. See server configuration.
  • Real-time client dashboard with request log, latency percentiles, WAF counters, and connection stats
  • Auto-update - server and client can self-update in the background with automatic restart and client reconnection
  • Password-protected tunnels with a built-in access form and edge session cookie (per-tunnel or per-config)
  • Env-first configuration - minimal CLI flags, .env support, and interactive setup wizards
  • Rate limiting on tunnel registration plus optional public traffic throttling per hostname+client IP
  • Persistent login - authenticate once with expose login, credentials are saved locally
  • Automatic reconnection with exponential backoff and keepalive pings
  • HTTP/3 over QUIC support - clients can use --transport=quic for compatibility or negotiated multi-stream mode
  • Optional WebRTC TURN relay on the public server, with UDP, TCP/TLS and short-lived credentials. See TURN relay.

How It Works

expose architecture

  1. The server terminates TLS, runs WAF inspection, and routes requests by hostname to the correct tunnel
  2. The client registers via API key, then opens a persistent WebSocket or HTTP/3 tunnel to the server
  3. Requests and responses flow over the tunnel as versioned binary frames, with raw body bytes for inline and streamed payloads

Large HTTP uploads and downloads stream in bounded chunks without a total-body size cap. Upstream applications enforce their own upload limits; WAF inspection, frame sizes, queues, and timeouts remain bounded.

For the full request lifecycle and component breakdown, see Architecture Overview. For transport mode details (ws|quic) and QUIC requirements, see Client Configuration and UDP Deployment Topologies.

Quick Start

Prerequisites

  • A server or VPS with a public IP - or a home server with port forwarding configured
  • A domain you control (e.g. example.com)
  • A DNS wildcard A record (*.example.com) pointing to your server's public IP
  • Port mappings from public 443/tcp to internal 10443/tcp for normal HTTPS URLs, public 80/tcp to internal 10080/tcp for ACME HTTP-01, and public 443/udp to internal 10443/udp for QUIC

1. Install

Release binaries are published for macOS, Linux, and Windows on both amd64 and arm64, including Windows on Arm.

macOS and Linux:

curl -fsSL https://raw.githubusercontent.com/koltyakov/expose/main/scripts/install.sh | sh

Windows PowerShell:

irm https://raw.githubusercontent.com/koltyakov/expose/main/scripts/install.ps1 | iex

To uninstall, run the matching script:

curl -fsSL https://raw.githubusercontent.com/koltyakov/expose/main/scripts/uninstall.sh | sh
irm https://raw.githubusercontent.com/koltyakov/expose/main/scripts/uninstall.ps1 | iex

Or install from source with Go 1.26 or newer:

go install github.com/koltyakov/expose/cmd/expose@latest

2. Server - init and run

On your public-facing machine, run the interactive setup (writes a .env for you):

expose server init   # guided setup
expose server        # start the tunnel server

Then create an API key for your client(s):

expose apikey create --name default

3. Client - login and run

On any machine you want to expose:

# Login once to save credentials locally
expose login

# Expose a local HTTP port (e.g. 3000) to the internet
expose http 3000

# Or expose it with a named subdomain
expose http 3000 --domain=myapp

# Or expose a static directory as a website
expose static ./public

# Or upload a static site for persistent server-side hosting
expose pub ./dist --ttl=24h
# Track open pages as active visitors:
expose pub ./dist --ws

# List your tunnels and published sites across machines
expose list

For multiple servers, save a named login and select it per command:

expose login --profile work --server work.example.com --api-key <KEY>
expose http 3000 --profile work
expose list --profile work

Omit --profile to keep using your existing default login. Named logins do not change it. See Client profiles for details.

Open the URL shown in the terminal - that's it.

⚠️ Security notice: if your server is using per-host ACME certificates (dynamic, or auto without a matching wildcard certificate), new public hostnames are often discovered and probed by bots shortly after they are created. Protect new tunnels immediately and use --protect for anything non-public. See TLS Modes and Static Sites.

For the full walkthrough, DNS setup guides, and multi-route configs, see Quick Start.

See Static site publishing for named domains, listing, deletion, and upload limits.

Documentation

See the docs/ folder for all guides - server & client configuration, static sites, TLS modes, DNS setup, deployment, WAF, auto-update, troubleshooting, and more.

Development

Build and install locally:

make install

Generate coverage reports:

make cov

Acknowledgements

  • ngrok - the gold standard for HTTP tunnels and a huge inspiration. expose exists because I needed more freedom and control over infrastructure, but ngrok paved the way.
  • OpenAI and Anthropic - AI-assisted development boosted the entire build lifecycle by 10Γ—.

License

MIT

About

πŸš€ Self-hosted HTTP tunnel for exposing local apps and static sites with automatic HTTPS, built-in WAF, and a real-time terminal dashboard

Topics

Resources

Contributing

Security policy

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages