self-tunnel
v0.4.0
Published
A lightweight local HTTP tunnel over WebSocket
Maintainers
Readme
self-tunnel
self-tunnel is a lightweight Node.js module that allows your application to establish a secure, outbound WebSocket tunnel to a remote service. This provides HTTPS access to your local web server (Express, Fastify, etc.) from anywhere in the world without port forwarding or a static IP address. You can register any domain (including free subdomains from providers like No-IP or ClouDNS) or use your own custom domain and configure it in one place.
Features
-📡 Remote HTTPS access to a Node.js server behind a NAT or firewall.
-🔐 Secure tunneling over WebSockets (WSS).
-🌍 No port forwarding or public IP address required.
-⚙️ Easy integration with any Node.js application running on a local port.
-🔧 Flexible configuration via an options object or environment variables (process.env).
-🔄 Automatic reconnection and keep-alive checks.
-🕊️ Minimal dependencies (only ws).
How It Works
Your Node.js application, using self-tunnel, opens a persistent WebSocket connection to the tunnel service endpoint (device-tunnel.top).
The tunnel service accepts incoming HTTPS requests for your domain and forwards them over the WebSocket to your application.
self-tunnel receives the request, establishes a local TCP connection to your web server (e.g., on localhost:8080), sends it the request, and returns the response back through the tunnel.
Quick Start
1. Pick/Register a Domain
You can use any domain or subdomain.
If you need a free subdomain, try services like No-IP or ClouDNS.
Add your domain to the https://device-tunnel.top/ service.
2. Installation
Add the module to your project using npm or yarn:
npm install self-tunnel # or yarn add self-tunnel3. Configure and Run
This is all you need to start a tunnel for your existing Node.js server.
Example with Express.js:
import express from 'express';
import selfTunnel from 'self-tunnel';
// 1. Your application
const app = express();
const PORT = 3000;
app.get('/', (req, res) => {
res.send('Hello from my local server via the tunnel!');
});
app.listen(PORT, () => {
console.log(`Local server running at http://localhost:${PORT}`);
// 2. Start the tunnel
const tunnel = selfTunnel({
domain: process.env.TUNNEL_DOMAIN || 'mynodeapp.mydomain.com', // Your domain
secret: process.env.TUNNEL_SECRET, // Your secret key
localPort: PORT, // Your local server's port
debug: true // Enable debug logs
});
// Your server is now accessible at https://mynodeapp.mydomain.com
});You can set domain and secret directly in the code or use the environment variables TUNNEL_DOMAIN and TUNNEL_SECRET for better security and flexibility.
Accessing Multiple Devices Under One Domain
If you have multiple Node.js applications running behind the same tunnel domain, you can configure path-based routing using the device option.
Application A uses: selfTunnel({ domain: "myapps.example.com", device: "service-A", ... })
Application B uses the same domain but a different device name: selfTunnel({ domain: "myapps.example.com", device: "service-B", ... })
Clients can now access them at different URLs:
https://myapps.example.com/service-A/
https://myapps.example.com/service-B/The tunnel service will route requests based on the device name prefix. The device marked as "primary" in the service will be accessible from the root domain path.
Requirements
Node.js v16.x or higher.
A running local web server (based on Express, Fastify, http.createServer, etc.).
A registered domain (or subdomain) pointing to a compatible tunnel service
Configuration Reference
Initializes and starts the tunnel.
selfTunnel(options, [app])
app: (Optional) An Express/Connect app instance. If provided, the module will automatically add middleware to preserve the x-original-id header for better performance.
options<Object>
Returned tunnel Object
- tunnel.close(): Gracefully closes the WebSocket connection and all local sockets, and disables auto-reconnect.
- tunnel.pause(): Temporarily suspends request proxying by sending a suspend command to the server.
- tunnel.resume(): Resumes request handling after a pause.
License
MIT
Contributing / Feedback
If you find a bug, have a feature request, or want to contribute, please file an issue or submit a PR on the GitHub repo.
