Tunneling to Localhost

4 minute read

When you’re developing Rails apps or pretty much any other framework you can name, you typically work with a server running on localhost. This is all well and good until you need to access it from a different location. This usually comes up in one of two ways.

The simpler case is the need to access your development server from another device, say a phone or a (shudder) Windows desktop. If the device is on the same network, you can work around this by using the IP of your dev box. However, if the device is outside the network and your dev box is behind NAT (which is almost always the case), then it’s not simple.

Likewise, if you are developing for against something that uses a callback, a webhook, or otherwise needs to hit your remote-to-it server to function, localhost and private IP aren’t going to cut it.

What you need in this case is some sort of proxy, a port on a server accessible from the Internet at large that tunnels back to you dev box. Here are three ways to handle it.


If you have SSH access to a server on the public Internet and you have admin privileges, then the simplest approach is to take advantage of that as you already have the tools you need.

One of the core features of the OpenSSH ssh client is port forwarding. When you connect to a remote server, you can tell ssh to open a port on the server and forward any connections that come in to a port on your local machine.

However, this feature is typically disabled by default. Or more specifically, tunnels are only allowed to bind to localhost. If you have admin privileges, you can edit /etc/ssh/sshd_config, add GatewayPorts clientspecified and then restart SSH with sudo service ssh restart and use this method. If not, skip to the next two options.

If GatewayPorts is enabled, it’s as simple as:

ssh -f -N -R 1234:localhost:3000 server.example.com

This connects port 1243 on server.example.com to port 3000 on your local machine. Any connections that arrive on server.example.com:1234 are automatically forwarded to localhost:3000.

Breaking down the other options:

  • -N don’t run a remote command, we don’t need one.
  • -f Run in the background. This causes ssh to return you to command prompt immediately. I like this as it doesn’t tie up a window. However, it does mean you will need to find and kill the process later.

And a couple of caveats. Because of UNIX port restrictions, non-root users can’t open ports below 1024. That means you can’t put the remote end of your tunnel on port 80 (or 443 for HTTPS) and that your URL will always need in include the port number.

Also, if you want to use HTTPS, the tunnel will simple pass all traffic through, so you’ll need to support it in your app (maybe by running Thin).


Localtunnel is a free service/open source project that creates a tunnel from their server back to port 3000 on your dev box. It functions pretty much exactly like an SSH tunnel, but doesn’t require that you have a server. It does require that you have Node.js installed.

Presuming you do, to install with:

npm install -g localtunnel

To use:

lt --port 3000
your url is: https://oszqyipeml.localtunnel.me

Connecting the “your url” tunnels back to port 3000 on your local computer. A nice bonus of Localtunnel is that the connection automatically (and optionally) supports HTTPS, something I’m seeing required more often by service intergations.

The downside of Localtunnel is that the URL is randomly generate and changes every time you run lt. This is fine for many kinds of testing, but if you are working with a callback or webhook, you may need to reconfigure it each time you start lt. Alternatively…


NGROK is a commercial service with freemium model. For free, you get the same features as Localtunnel, namely a tunnel with a random URL and optional HTTPS support. Download it and run:

ngrok http 3000
Forwarding                    http://2213de79.ngrok.io -> localhost:3000
Forwarding                    https://2213de79.ngrok.io -> localhost:3000

Also included is a nice web interface which lets you inspect the traffic traveling over the tunnel. You can view the request, the response, and headers going in either direction. You can even replay requests to test fixes without needing to generate a new request.

And, for mere money (starting at $7, cheaper if you pay annually) you can get a reserved URL so that you don’t have to reconfigure. There are other features as well, reserved IPs, wildcard domains, etc. See the label for details.

In summary. SSH is the build-your-own-lightsaber approach and requires a server you manage, Localtunnel is an easy, free option, and NGROK gives you the option of buying additional features if you need them. Whichever you choose, localhost won’t have to be local anymore.