Self-Hosted Ngrok Alternative
Self-Hosted Ngrok Alternative
What is ngrok and Why Do We Need It?
ngrok is a reverse proxy that creates a secure tunnel from a public endpoint to a local service. It allows developers to expose a local server behind a NAT or firewall to the internet without deploying to a public hosting environment. This is particularly useful for testing purposes or sharing work-in-progress applications.
There are indeed easier ways to self-host ngrok-like services—various resources provide examples on how to set these up. However, these methods can conflict with existing configurations. In my case, I use Traefik to serve my Docker services, and many of these self-hosted tunneling solutions could interfere with this setup. Therefore, I needed a solution that integrates seamlessly with Traefik without causing conflicts.
Requirements and Setup
To create a self-hosted alternative to ngrok, we'll leverage:
- Traefik: A HTTP reverse proxy and load balancer that makes deploying microservices easy.
- Docker: Containerization platform to package our applications.
- SSH: Secure Shell protocol to create a tunnel to our Virtual Private Server (VPS).
- socat: A command-line based utility that establishes two bidirectional byte streams and transfers data between them.
Our goal is to:
- Integrate the self-hosted service into our existing VPS infrastructure.
- Use Traefik for SSL termination.
- Avoid running additional web servers.
- Start new tunnels only from the client machine.
- Use Docker to start a new socat proxy container.
- Establish an SSH connection to the VPS without executing commands on it.
Using socat as a TCP Proxy
socat (SOcket CAT) is a networking tool that allows for data transfer between two bidirectional data streams. It's like a combination of netcat
and cat
. We use socat within a Docker container to create a TCP proxy that Traefik can route to, and because we need to attach labels to the Docker container for Traefik's dynamic configuration.
Docker Compose Configuration
Below is the docker-compose.yml
file for the socat proxy. Replace placeholders like ${DOMAIN}
with your actual domain and adjust labels as necessary.
Traefik Configuration
Here's the docker-compose.yml
file for Traefik:
Ensure that ${DOMAIN}
and ${USER_PASSWORD}
are defined in your environment or replace them directly.
Setting Up the SSH Tunnel
To forward traffic from your local machine to the VPS, use the following SSH command:
Explanation:
-R "*:7003:localhost:7003"
: Remote port forwarding, binding to all interfaces on the server (*
).your-vps-domain.com
: Replace with your VPS domain or IP address.
SSHD Configuration for GatewayPorts
By default, SSHD binds remote port forwarding to localhost
, which isn't accessible from Docker containers. To allow binding to all interfaces, adjust the SSHD configuration on your VPS:
-
Open the SSHD configuration file, typically located at
/etc/ssh/sshd_config
. -
Set the
GatewayPorts
option toclientspecified
:
Restart the SSHD service:
This configuration allows the SSH client to specify the bind address, enabling Docker containers to access the forwarded port.
Resources
- https://ngrok.com/
- https://github.com/anderspitman/awesome-tunneling if you don't need integration with traefik use one of the solution from this article, it could be easier.