expose

module
v0.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT

README

expose

expose is a self-hosted HTTP tunnel. Run your own server, then expose local HTTP ports from any machine - no third-party services 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
  • Static site publishing via expose static for quick docs, SPAs, and local folders
  • Multi-route configs via expose.yml - expose multiple services under one subdomain with path-based routing
  • 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 zero downtime
  • 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 to prevent abuse
  • Persistent login - authenticate once with expose login, credentials are saved locally
  • Automatic reconnection with exponential backoff and keepalive pings

How It Works

flowchart TB
    App["💻 Local app<br/>127.0.0.1:PORT"]

    subgraph client["expose client"]
        Fwd["Forward"] --> Conn["Connect"] --> Reg["Register"]
    end

    subgraph server["expose server"]
        Hub{{"Session hub"}}
        Route["Route by hostname"]
        TLS["TLS · WAF"]
        DB[("SQLite")]

        Hub --> Route --> TLS
        Route -. resolve .-> DB
    end

    Browser["🌐 Browser"]

    App -- "HTTP" --> Fwd
    Hub <-- "WebSocket tunnel" --> Conn
    Conn -- "token" --> Hub
    Reg -- "API key" --> Route
    TLS -- "HTTPS *.domain" --> Browser
  1. The server terminates TLS, runs WAF inspection, and routes requests by hostname to the correct tunnel
  2. The client registers via API key, opens a persistent WebSocket, and proxies requests to your local port
  3. Requests and responses flow over the WebSocket as JSON envelopes with binary streaming for large bodies

For the full request lifecycle and component breakdown, see Architecture Overview.

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
1. Install

Download the latest binary from Releases and place it in your PATH.

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 a static directory as a website
expose static

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.

Documentation

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

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

Directories

Path Synopsis
cmd
expose command
internal
auth
Package auth provides API key generation, hashing, and comparison utilities used by both the server and CLI admin commands.
Package auth provides API key generation, hashing, and comparison utilities used by both the server and CLI admin commands.
cli
Package cli implements the expose command-line interface, dispatching subcommands for server, client, login, and API key administration.
Package cli implements the expose command-line interface, dispatching subcommands for server, client, login, and API key administration.
client
Package client implements the expose tunnel client that registers with the server, maintains a WebSocket session, and proxies traffic to a local port.
Package client implements the expose tunnel client that registers with the server, maintains a WebSocket session, and proxies traffic to a local port.
client/settings
Package settings persists and loads client credentials (server URL and API key) in a JSON file under the user's home directory.
Package settings persists and loads client credentials (server URL and API key) in a JSON file under the user's home directory.
config
Package config defines the configuration structs and flag/env parsing for the expose server and client.
Package config defines the configuration structs and flag/env parsing for the expose server and client.
domain
Package domain defines the core data types shared across the expose server, store, and tunnel protocol layers.
Package domain defines the core data types shared across the expose server, store, and tunnel protocol layers.
log
Package log provides a minimal factory for structured slog loggers.
Package log provides a minimal factory for structured slog loggers.
netutil
Package netutil provides shared HTTP/network normalization helpers.
Package netutil provides shared HTTP/network normalization helpers.
selfupdate
Package selfupdate checks for newer releases on GitHub and replaces the running binary in-place.
Package selfupdate checks for newer releases on GitHub and replaces the running binary in-place.
server
Package server implements the expose HTTPS reverse-proxy server with WebSocket-based tunnel management, ACME TLS, and session lifecycle.
Package server implements the expose HTTPS reverse-proxy server with WebSocket-based tunnel management, ACME TLS, and session lifecycle.
store/sqlite
Package sqlite implements the expose data store backed by a SQLite database.
Package sqlite implements the expose data store backed by a SQLite database.
tunnelproto
Package tunnelproto defines the JSON wire protocol exchanged between the expose server and its tunnel clients over a WebSocket connection.
Package tunnelproto defines the JSON wire protocol exchanged between the expose server and its tunnel clients over a WebSocket connection.
waf
Package waf implements a lightweight Web Application Firewall middleware that inspects incoming HTTP requests and blocks common attack patterns.
Package waf implements a lightweight Web Application Firewall middleware that inspects incoming HTTP requests and blocks common attack patterns.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL