Self-Hosted Ngrok in 200 Lines of Node.js
Problem: Need to tunnel multiple local services. Ngrok free tier = 1 tunnel.
Solution: Built my own. Took 4 hours.
What It Does
liptunnel http 3000,8080,5000 --multi
Creates 3 public URLs on your domain. One command.
The Architecture
User → yourdomain.com → VPS → WebSocket → Your PC → localhost
Core concept:
// Server: Forward HTTP via WebSocket
app.use((req, res) => {
const subdomain = req.headers.host.split('.')[0];
tunnels[subdomain].ws.send(JSON.stringify(req));
// Wait for response, send back
});
// Client: Receive, proxy, respond
ws.on('message', (data) => {
http.request('localhost:3000', data.request, (response) => {
ws.send(response);
});
});
That's the entire concept. The rest is error handling.
Why Self-Host?
✅ Privacy - Your traffic stays yours
✅ Cost - $0 beyond your VPS
✅ Branding - Your domain
✅ Control - Customize everything
Performance
- Memory: 25MB/tunnel
- Latency: ~5ms overhead
- Throughput: 100+ req/sec
- Setup: 5 minutes
Use Cases
Microservices: Tunnel entire stack locally
Webhooks: Test Stripe/GitHub without deploying
Demos: Client-branded URLs
Compliance: Healthcare/finance (no third parties)
Get Started
Full code + docs:
👉 github.com/ibrahimpelumi6142/liptunnel
git clone https://github.com/ibrahimpelumi6142/liptunnel
npm install
node server/server.js # On VPS
liptunnel http 3000 # Local
Tech Stack
- Node.js (runtime)
- WebSocket (tunnel)
- Express (dashboard)
No frameworks. ~200 lines total.
What's Next
Coming soon:
- HTTPS (Let's Encrypt)
- Fixed subdomains
- Auth tokens
- Request inspector
Try It
Questions? Drop them below 👇
Tags: #nodejs #opensource #webdev #selfhosted

Top comments (0)