Introduction
ngrok
is a fantastic tool for exposing local servers to the internet with minimal effort. However, it’s not always an ideal choice due to cost, licensing, or privacy concerns. In this article, we’ll recreate ngrok-like functionality using open-source tools: NGINX, Kubernetes, Docker, and OpenSSH. By the end, you'll have a custom, self-hosted tunnel that forwards traffic from the internet to your local machine.
Here’s a high-level overview of the architecture:
Woovi’s Specific Needs for Tunneling
At Woovi, we developed a Shopify payment app that requires fixed URLs during development. Using ngrok presented a challenge because each developer generated a unique URL. Changing these URLs required re-submitting for Shopify’s review, even for development, causing significant delays.
To solve this problem, we created a solution that allows any developer to forward their local server to a consistent, custom domain, such as shopify.ourdomain.com. This eliminated the URL change issue, saving valuable time and improving the development workflow.
Setting Up OpenSSH + NGINX
The first step is to create a Docker image that includes both OpenSSH and NGINX. OpenSSH allows remote SSH connections, while NGINX will handle HTTP traffic forwarding.
Dockerfile
FROM alpine:latest
RUN apk add --no-cache \
openssh \
nginx \
bash && \
mkdir -p /run/nginx && \
mkdir -p /root/.ssh
# Generate SSH host keys
RUN ssh-keygen -A
# Set the root password to '123456'
RUN echo "root:woovi" | chpasswd
RUN mkdir /var/run/sshd && \
ssh-keygen -A && \
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config && \
echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config && \
echo "GatewayPorts yes" >> /etc/ssh/sshd_config && \
echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config && \
echo "PermitOpen any" >> /etc/ssh/sshd_config && \
echo "MaxAuthTries 6" >> /etc/ssh/sshd_config && \
echo "UseDNS no" >> /etc/ssh/sshd_config && \
echo "AllowUsers root" >> /etc/ssh/sshd_config && \
echo "TCPKeepAlive yes" >> /etc/ssh/sshd_config && \
echo "ClientAliveInterval 60" >> /etc/ssh/sshd_config && \
echo "ClientAliveCountMax 3" >> /etc/ssh/sshd_config && \
sed -i '/^AllowTcpForwarding no$/d' /etc/ssh/sshd_config
# Create SSH directory for root user and set permissions
RUN mkdir -p /root/.ssh && chmod 700 /root/.ssh
RUN touch /root/.ssh/authorized_keys
COPY authorized_keys /root/.ssh/authorized_keys
RUN chmod 600 /root/.ssh/authorized_keys
COPY nginx.conf /etc/nginx/nginx.conf
# Expose port 22 for SSH
EXPOSE 22 80
# Start the SSH service
CMD /usr/sbin/sshd && nginx -g "daemon off;"
This Dockerfile sets up an OpenSSH server alongside NGINX and exposes two ports:
- Port 22: For SSH connections.
- Port 80: For NGINX HTTP traffic.
nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
set_real_ip_from 0.0.0.0/0;
server_name woovi-ssh;
location / {
proxy_pass http://localhost:5001;
}
}
}
This configuration forwards all HTTP requests on port 80 to a local service running on port 5001. You’ll use this setup to forward traffic from your local machine to the remote server.
Forwarding Your Localhost to the Remote Server
Once the Docker container is deployed, you can forward your local server to the remote server using an SSH remote port forward. Run the following command:
ssh -R 5001:localhost:5001 root@myowndomain.com
This command forwards requests from the remote server’s 5001 port to your local machine’s 5001 port. For example, accessing http://myowndomain.com/anypath
will route traffic to http://localhost:5001/anypath
on your machine.
Summary
By combining NGINX, OpenSSH, and Docker, you’ve created a self-hosted alternative to ngrok. This solution gives you complete control over your traffic without relying on third-party services, making it ideal for privacy-conscious developers and teams with specific tunneling needs.
Have you tried this setup? Let us know how it worked for you or share any questions in the comments!
Woovi is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.
If you want to work with us, we are hiring!
Top comments (0)