Exposing a locally running web service to the internet is a daily task for developers — whether you’re sharing a staging demo with a client, testing webhook integrations, or debugging a mobile app against your local API. Ngrok popularized this workflow, but its free tier limits, pricing changes, and centralized architecture have pushed many teams toward self-hosted alternatives.
This guide compares three open-source tools that solve the same problem from different angles: Bore (minimalist Rust binary), Expose (full-featured PHP/Laravel platform), and LocalTunnel (lightweight Node.js solution). Each can be deployed on your own server with zero usage restrictions.
Why Self-Host Your Tunnel Server?
Running your own tunnel infrastructure offers several advantages over SaaS solutions:
- No connection limits — unrestricted concurrent tunnels and bandwidth
- Custom domains — use your own domain instead of random subdomains
- Full control — no rate limiting, no disconnections, no feature gating
- Privacy — traffic flows through your server, not a third party
- Cost predictability — one VPS replaces recurring subscriptions
- Compliance — data stays within your infrastructure for regulated environments
Quick Comparison Table
| Feature | Bore | Expose | LocalTunnel |
|---|---|---|---|
| Language | Rust | PHP (Laravel) | Node.js |
| Stars (GitHub) | 11,076 | 4,546 | 10,300+ |
| Last Updated | Feb 2026 | Mar 2026 | 2024 |
| License | MIT | AGPL-3.0 | MIT |
| Self-Host Server | ✅ | ✅ | ✅ |
| Auth/Auth Tokens | ✅ Secret-based | ✅ User accounts | ❌ |
| Admin Dashboard | ❌ | ✅ Full UI | ❌ |
| Custom Domains | ✅ | ✅ | ✅ |
| HTTP + TCP | TCP only | HTTP only | HTTP only |
| WebSocket Support | ✅ | ✅ | ✅ |
| Docker Image | Official (scratch) | Official | Community |
| Binary Size | ~6 MB | N/A (PHP) | N/A (npm) |
| Min RAM | ~10 MB | ~256 MB | ~80 MB |
Bore: Minimalist Rust Tunnel
Bore is the lightest option in this comparison — a single Rust binary (~6 MB when compiled) that opens a reverse TCP tunnel between your machine and a remote server. It was designed with simplicity as the core principle: one command to expose any local port.
Architecture
Bore operates as a client-server model:
- You run
bore serveron a public VPS (listens on port 7835 by default) - You run
bore client --port 3000 --remote bore.example.comlocally - The server assigns a public port (e.g., 9000) that forwards to your local port 3000
| |
Installation
Server side (VPS):
| |
Client side (local machine):
| |
Docker Compose Deployment
Bore’s minimal footprint makes it ideal for containers. The official image uses a scratch base:
| |
Add a reverse proxy (Nginx or Caddy) in front if you want HTTPS termination and custom domain routing.
Bore Pros and Cons
Pros:
- Extremely lightweight — ~10 MB RAM usage, ~6 MB binary
- Zero dependencies — single static binary, no runtime needed
- Fast startup — sub-second connection establishment
- Secret-based authentication prevents unauthorized tunnels
- Supports any TCP protocol (HTTP, SSH, databases, game servers)
Cons:
- No built-in HTTP inspection or replay
- No admin dashboard or web UI
- No request logging out of the box
- TCP-only — no HTTP-specific features like header rewriting
Expose: Full-Featured PHP Tunnel Platform
Expose takes the opposite approach from Bore — it’s a comprehensive tunneling platform built on Laravel, with a polished web dashboard, user management, team sharing, and request inspection. If Bore is a scalpel, Expose is a Swiss Army knife.
Key Features
- Admin dashboard — monitor all active tunnels, inspect requests in real time
- User accounts — multi-user support with per-user subdomain allocation
- Request logging — full HTTP request/response inspection and replay
- Custom subdomains — reserve and assign specific subdomains to users
- Password protection — add basic auth to any shared tunnel
- Team sharing — share tunnels with team members through the dashboard
- API — REST API for programmatic tunnel management
Installation
Server setup via Composer:
| |
Client usage:
| |
Docker Compose Deployment
| |
The Expose server stores user accounts, tunnel configurations, and request logs in a MySQL database, making it more resource-intensive than Bore but far more capable for team environments.
Expose Pros and Cons
Pros:
- Full admin dashboard with real-time request monitoring
- Multi-user support with authentication
- Request inspection, logging, and replay
- Custom subdomains and password-protected tunnels
- Active development with regular releases
Cons:
- Heavier resource footprint (PHP + MySQL, ~256 MB minimum)
- Requires Composer and PHP runtime on the server
- AGPL-3.0 license (copyleft — modifications must be shared)
- HTTP-only — cannot tunnel arbitrary TCP protocols
LocalTunnel: Lightweight Node.js Solution
LocalTunnel is the simplest option to get running — a Node.js package that requires just npm install -g localtunnel and a single command. The public localtunnel.me service exists, but you can also host your own server for full control.
Self-Hosted Server Setup
The server component ships as part of the localtunnel npm package:
| |
For a proper production deployment, you’ll want to run the server component separately:
| |
Client Usage
| |
Docker Compose Deployment
| |
LocalTunnel Pros and Cons
Pros:
- Easiest to install — single
npm installcommand - Very low barrier to entry for Node.js developers
- Supports WebSocket connections
- Lightweight on resources (~80 MB RAM)
- MIT license — no copyleft restrictions
Cons:
- Less actively maintained (last major release 2024)
- No admin dashboard or user management
- No authentication mechanism built in
- HTTP-only — no TCP tunneling
- Limited configuration options compared to Expose
Deployment Comparison: Resource Requirements
| Metric | Bore Server | Expose Server | LocalTunnel Server |
|---|---|---|---|
| Min RAM | 10 MB | 256 MB | 80 MB |
| Disk | 6 MB | 200 MB+ | 50 MB |
| CPU | Negligible | Low | Low |
| Dependencies | None | PHP + MySQL | Node.js |
| Container Size | ~6 MB | ~400 MB | ~180 MB |
| VPS Tier | $3/mo | $6/mo | $4/mo |
For a solo developer running occasional demos, Bore on a $3/month VPS is hard to beat. For a team of 10+ developers who need audit trails and request inspection, Expose justifies its higher footprint.
Which Should You Choose?
Choose Bore if:
- You want the absolute simplest, lightest solution
- You need TCP tunneling (SSH, databases, custom protocols)
- You’re comfortable with CLI-only tools
- You’re deploying to resource-constrained environments (Raspberry Pi, cheap VPS)
Choose Expose if:
- You need an admin dashboard for monitoring
- You have a team sharing tunnels regularly
- You want request inspection and replay capabilities
- You need user accounts and authentication
Choose LocalTunnel if:
- You want the fastest setup with minimal configuration
- You’re already in the Node.js ecosystem
- You need something quick for a one-off demo
- You prefer the simplicity of npm-based tooling
Complete Bore Server Setup with Nginx Reverse Proxy
For a production-ready Bore deployment with HTTPS, combine it with Nginx. If you need a GUI-driven approach to reverse proxy management, check out our Nginx Proxy Manager vs SWAG vs Caddy Docker Proxy guide for a visual configuration alternative. For a broader look at self-hosted tunneling tools including TCP and DNS-based options, see our frp vs Chisel vs rathole comparison and webhook relay and tunnel guide.
| |
Sample Nginx configuration for the Bore control port:
| |
FAQ
Is Bore faster than Ngrok?
Bore typically has lower latency because there’s no intermediary relay — your traffic goes directly from the server to your machine over a single TCP connection. However, Ngrok’s global edge network may provide better latency for users far from your server’s location. For most development use cases, the difference is imperceptible.
Can I use a custom domain with these tools?
Yes, all three tools support custom domains when self-hosted. With Bore, you assign specific ports that map to your DNS records. Expose has built-in custom domain management through its admin dashboard. LocalTunnel supports custom subdomains via the --subdomain flag combined with a wildcard DNS record pointing to your server.
Which tool supports HTTPS out of the box?
None of these tools handle TLS termination natively — they operate at the TCP or HTTP layer. For HTTPS, you should place a reverse proxy (Caddy, Nginx, or Traefik) in front of the tunnel server. Caddy is the simplest option as it handles automatic Let’s Encrypt certificate provisioning.
Is self-hosting a tunnel server secure?
The tunnel connection itself is encrypted (Bore uses TCP, Expose and LocalTunnel support HTTPS when behind a reverse proxy). However, you are responsible for: securing the VPS, managing firewall rules, keeping the software updated, and configuring authentication (Bore’s --secret flag, Expose’s user system). Without authentication, anyone could create tunnels through your server.
Can these tools replace Ngrok for webhook testing?
Yes, all three are well-suited for webhook testing. Expose has an advantage here because its request inspection dashboard lets you view, filter, and replay webhook payloads without additional tools. With Bore, you’d pair it with a local request logger. For simple webhook endpoints, any of the three works fine.
What happens if the tunnel server goes down?
When the server process stops, all active tunnels disconnect immediately. Clients will need to reconnect once the server is back online. For production use, consider setting up process supervision (systemd, supervisord, or Docker’s restart: unless-stopped) and monitoring (uptime checks via Uptime Kuma or Gatus) to ensure quick recovery.