Self-Hosted Ngrok Alternative in 200 Lines of Node.js

Published: (February 1, 2026 at 11:13 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Problem

Need to tunnel multiple local services, but the free tier of Ngrok only provides a single tunnel.

Solution

A self‑hosted tunnel written in ~200 lines of Node.js. It can create multiple public URLs with a single command.

liptunnel http 3000,8080,5000 --multi

This command creates three public URLs on your domain, routing traffic as:

User → yourdomain.com → VPS → WebSocket → Your PC → localhost

Core concept

Server (forward HTTP via WebSocket)

// server.js (Express middleware)
app.use((req, res) => {
  const subdomain = req.headers.host.split('.')[0];
  tunnels[subdomain].ws.send(JSON.stringify(req));
  // Wait for response, then send it back to the client
});

Client (receive, proxy, respond)

// client.js
ws.on('message', (data) => {
  const request = JSON.parse(data);
  const proxy = http.request(
    {
      hostname: 'localhost',
      port: request.port,
      path: request.path,
      method: request.method,
      headers: request.headers,
    },
    (response) => {
      let body = '';
      response.on('data', (chunk) => (body += chunk));
      response.on('end', () => {
        ws.send(
          JSON.stringify({
            statusCode: response.statusCode,
            headers: response.headers,
            body,
          })
        );
      });
    }
  );
  proxy.end(request.body);
});

The rest of the implementation handles error cases, connection management, and cleanup.

Features

  • Privacy – Traffic never leaves your infrastructure.
  • Cost – Only the expense of your VPS (free beyond that).
  • Branding – Use your own domain for tunnel URLs.
  • Control – Full customization of routing and handling.

Performance

  • Memory: ~25 MB per tunnel
  • Latency: ~5 ms overhead
  • Throughput: 100+ requests/second

Use cases

  • Quick setup of microservices locally
  • Testing webhooks (Stripe, GitHub, etc.) without deploying
  • Demonstrations with client‑branded URLs
  • Compliance‑sensitive environments (healthcare, finance) where third‑party services are prohibited

Setup

# Clone the repository
git clone https://github.com/ibrahimpelumi6142/liptunnel
cd liptunnel

# Install dependencies
npm install

# Run the server on your VPS
node server/server.js   # <-- start on the remote machine

# Start a tunnel from your local machine
liptunnel http 3000     # <-- replace 3000 with the port you want to expose

Technology stack

  • Node.js – runtime
  • WebSocket – tunnel transport
  • Express – optional dashboard (no heavy frameworks)

All code resides in a single ~200‑line project.

Roadmap (coming soon)

  • HTTPS support via Let’s Encrypt
  • Fixed subdomains
  • Authentication tokens for tunnel access
  • Request inspector UI

Contributing

If you find the project useful, consider starring it on GitHub:

⭐ GitHub repository

Feel free to open issues or submit pull requests for improvements.

Back to Blog

Related posts

Read more »