DEV Community

Cover image for How to Expose Localhost to the Public Using Nginx and SSH Tunnels
Ganesh Kumar
Ganesh Kumar

Posted on

How to Expose Localhost to the Public Using Nginx and SSH Tunnels

Hello, I'm Ganesh. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.

As a developer, you’ve likely faced this hurdle: You are building a complex application on your local machine, and you need to show it to a client or test a webhook of your application.

You could deploy it to a staging server, but that's slow.
You could use Ngrok, but the free tier has limits and dynamic URLs.

Today, I’ll show you how to build your own "Unlimited" Reverse Proxy using Nginx, Autossh, and a small VPS.

The Architecture

The goal is to route traffic from a professional URL (like test1.yourdomain.com) directly to a port on your local machine (like localhost:3000).

We use three layers of technology to make this happen:

  1. Nginx: Acts as the entry point and handles SSL (HTTPS).
  2. SSH Reverse Tunnel: Creates a secure "pipe" from your VPS back to your laptop.
  3. Autossh: Ensures that if your internet flickers, the "pipe" automatically reconnects.

Step 1: The Remote Server (Nginx)

On your server, you need an Nginx configuration that listens for HTTPS traffic and passes it to a local port.

server {
    listen 443 ssl http2;
    server_name test1.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/your-domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain/privkey.pem;

    location / {
        # Proxy traffic to the SSH-forwarded port
        proxy_pass http://127.0.0.1:6540;

        # Keep the original user's info
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: The Local Bridge

On your local machine, you need to open the tunnel.

Using a Makefile or a shell script makes this repeatable. The core command uses the -R flag, which stands for Remote Forward.

# -R [Remote Port]:[Local Destination]:[Local Port]
autossh -M 20000 -R 6540:localhost:3000 root@your-server -N
Enter fullscreen mode Exit fullscreen mode

Why this is "Unlimited"

Unlike third-party services, this setup gives you:

  • Total Control: No timeout limits or bandwidth caps (other than your own ISP's speed).
  • Professionalism: You use your own domain and your own SSL certificates.
  • Security: Your local machine is not truly "exposed." Only the specific port you choose (8081) is bridged through the encrypted SSH tunnel.

Troubleshooting Common Gotchas

  1. 502 Bad Gateway: This usually means Nginx is working, but your SSH tunnel isn't running or is on the wrong port.
  2. Port Already in Use: If you restart your tunnel quickly, the server might still think the old one is active. Use a cleanup script to kill -9 <PID> any process currently sitting on your remote port before starting a new one.
  3. Firewalls: Ensure your VPS allows traffic on ports 80 and 443!

Conclusion

By combining the stability of Nginx with the flexibility of SSH tunneling, you've created a production-grade development environment.

You now have a permanent bridge between your local setup and the rest of the world.

git-lrc

Any feedback or contributors are welcome! It’s online, source-available, and ready for anyone to use.
⭐ Star it on GitHub: https://github.com/HexmosTech/git-lrc

Top comments (0)