Remote testing with ngrok

Testing websites and web applications across platforms, browsers and operating systems is a nightmare. Browsers’ developer tools have made it much more convenient over the years with respect to mobile but still, you can’t simulate IE in Firefox or weird “improvements” some OS + browser combinations make (I’m looking at you, Safari on an iPhone). There’s no getting around of running the browser on an actual device.

However, getting the website/app running somewhere accessible can be a bit of a problem. How big, depends on the complexity of setup and the deployment process. Even when you get there and find an issue, debugging and fixing it becomes a nightmare because of a long feedback loop between typing code and seeing the result and trying something else. This is where smart tools like ngrok come in.

ngrok is basically a dynamic DNS - you run an ngrok binary telling it to tunnel a specific port over the service’s server which gets published under a random third level domain under [random domain] You can then for example open Internet Explorer on a Windows machine, type in the URL and check the issue. Then, when you make a local change you can see it immediately on the other device as well.

To get ngrok working with a Rails application requires a few steps. I run Puma on the default port 3000 in local development so the basic command is:

ngrok http 3000

This should work for a simple app which doesn’t do any redirects using absolute URLs. In the case of Enectiva, some gems we use redirect using an absolute URL which means that requests get redirected to localhost:3000. This doesn’t match up with the remote access via an ngrok tunnel because the remote browser then tries to access port 3000 on its host machine. There might be nothing running on that port or something completely different. The result is the same.

To solve this issue, the simplest way is to change the default_url_options[:host] configuration to match the tunnel URL. The easiest way to do this is editing DEFAULT_HOST variable in .env file (or config/environments/development.rb directly). There are two downsides: (1) your local access won’t work as expected, you’ll be redirected through the tunnel (not a problem except for the unnecessary round trip) and (2) the URL is randomly assigned every time you start the ngrok tool so you have to copy it fresh. ngrok offers a paid version with a reserved subdomains and many more features.

If you’re in Europe like us, you will probably feel the lag. By default, ngrok routes the tunnels through servers in the US. However, it offers a flag to select other regions, so we run:

ngrok http -region eu 3000

One thing I haven’t managed to get working is the development Webpacker process. It runs as a process separate from Rails themselves, providing a WebSocket with updates of the assets on another port and hot reloading the page. While it’s possible to run multiple tunnels at the same time, there’s no relationship between the assigned URLs. I assume it’s possible to configure Rails to use another URL for the Webpacker process but I haven’t dug into it. The setup defaults to serving the assets and having to press F5 when you make a change which is not a huge cost. Compared to the alternatives, debugging issues in IE or on an iPhone is much less daunting with ngrok.

We're looking for developers to help us save energy

If you're interested in what we do and you would like to help us save energy, drop us a line at

comments powered by Disqus