Expose localhost to the public WWW with a VPS, nginx and SSH tunneling

Mario Hayashi
The Software Reliever
2 min readJan 9, 2017

If you work in a collaborative environment, you will have come across a situation where you needed to show someone your development work running on localhost to your colleagues.

Suppose you have a Webpack server running on localhost:3000. The simplest way to share your work with a colleague is to find out your IP in your network settings (or run ifconfig) and share a URL like 10.1.2.249:3000. OSX users will be able to share a human-readable URL like mario.local:3000 with minimal effort.

Well, sometimes, that’s easier said than done. Looks like some network firewall settings are preventing me from doing so.

So you try something like localtunnel. Looked really cool. Didn’t work sadly.

Enter SSH tunneling. If you have a public server you can access from the WWW, you can have the public server route requests to your localhost with SSH tunneling. Specifically we’re using remote port forwarding:

Remote port forwarding creates an incoming tunnel which can be used to bring a local computer into the public internet.

For more details on SSH tunneling, see this great SO post.

So, how does one go about it? This post describes a minimal way to expose your localhost to the WWW with SSH tunneling and a public server.

VPS setup

You can get a virtual private server (VPS) to act as your public server (don’t get confused by “private” — we’re making the VPS a public server). I created a DigitalOcean Droplet ($5/month) in less than a minute. Add your public SSH key to the Droplet/VPS. Note down your Droplet/VPS public IP.

SSH tunneling

We now want to forward the remote port 9000 (pick any you like) to the local port 3000. The remote port is the port on the VPS that will be forwarded to our local port 3000. Run this on your local workstation:

$ ssh -f -N -T -R 9000:localhost:3000 root@<my-droplet-ip>

SSH into your Droplet and install nginx:

ssh root@<my-droplet-ip>
apt-get install -y nginx

Reverse proxy with nginx

We’re using nginx on the remote server to create a reverse proxy from port 80 to 9000. This is so that you can serve your app with a URL like http://<my-droplet-ip>.

Add a virtual host to your nginx that will reverse proxy inbound requests arriving at port 80 to port 9000. Add to your /etc/nginx/sites-available/tunnel:

server {
listen 80;
location / {
proxy_pass http://127.0.0.1:9000;
}
}

Now we need to symlink the file to sites-enabled and reload the nginx config:

ln -s /etc/nginx/sites-available/tunnel /etc/nginx/sites-enabled/tunnel 
nginx -s reload

Result

Tell your colleague to access http://<my-droplet-ip>. Voila!

Note: Make sure to kill your SSH tunnel after use. It’s generally not safe to continually expose your localhost.

--

--

Mario Hayashi
The Software Reliever

Product engineer, No-Coder, contractor, tech leadership at startups, indie maker.