Skip to content

πŸš€ BYOI HTTP tunnel - automatic HTTPS, built-in WAF, real-time dashboard, single binary

License

Notifications You must be signed in to change notification settings

koltyakov/expose

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

73 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

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
  • 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 HTTP Basic Auth (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
Loading
  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:

expose login
expose http 3000

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

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, 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

About

πŸš€ BYOI HTTP tunnel - automatic HTTPS, built-in WAF, real-time dashboard, single binary

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published