my own ngrok

ngrok is a great service that redirects public internet traffic to a service running on a private network, such as your laptop at your house. Lately, as I’ve been doing a lot of development with oauth2 sign ins on webforms, I’ve had to use ngrok to test.

The free plan allows about 24 hours of connection and the paid for plans don’t really cost much ($5 a month for what I need). All in all, a great service and good people.

The problem is I only need this for a few days and since I already have all the resources I need there’s no real point for me to sign up and pay for it. And when I do need it, ngrok rate limits me so I can only make so many calls per minute so it takes my tests longer to run. So here is how I built my own:

1. Get an Internet Host

First, you’ll need a VM or something on the internet with ports that you are allowed to expose. This can be an EC2 instance or a digital ocean droplet. Whatever. In my case, its just a standard VM hosted on VMware managed by the good people at Voonami. (which is also where this blog is posted)

2. Configure NGINX

I create an nginx service that looks like this in sites-enabled. Notice that I already own the domain so just setting up DNS to point to this server works well. Also, I used Let’s Encrypt so you can see that the domain is now encrypted! That helps for testing too since many services (like when developing a backend for an iOS application) want the domains to be secure.

server {
        location / {
                proxy_pass http://localhost:7070;
                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 $scheme;
                error_page 502 /500.html;
        location /500.html {
                return 500 "<center>Nothing to see here...</center>";

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


3. Reverse SSH Tunnel!

Now I’m ready to develop! Whenever I do, from my laptop I run the following command:

ssh -R 7070:localhost:3000 -N cosa

This sweet command stays open in my shell while I’m developing. In this case, I’m developing an application that is on port 3000 (standard ReactJS front end application). So whenever I go to secure port 443, the NGINX proxy will forward that to the localhost 7070. But the ssh tunnel is opening the connection from port 7070 on the server to port 3000 on my laptop! So it takes me all the way back to my machine. Instant ngrok! Nice!


  • No rate limiting
  • Using resources I’m already paying for
  • Turn off/on whenever I want with no extra work but the ssh command.
  • Nothing to install