All Articles

Expose your local server to the internet with ngrok

Photo by Aaron Burden on Unsplash unsplash-logoAaron Burden

I first bumped to ngrok in 2017. Recently more than one colleague asked me about SSH tunnels to expose local servers/ports to the internet, and things started to get a bit complex — that is where ngrok comes to aid. It gets easier test external callbacks, use SEO tools and more having a way to access your server from any place.

How it works?

The ideia behind it is very simple. It creates a tunnel between ngrok server and your local machine. So it does not matter if you have firewalls or a complex enterprise network.

How ngrok works

From ngrok site

All you need to do is to download the CLI client, authenticate with your token and expose the desired port and protocol:

./ngrok auth <your token here>
./ngrok http 80

Now you’ll see a output like that:

Session Status                online                                                                    
Account                       Vinicius Schettino (Plan: Free)                                           
Version                       2.3.35                                                                    
Region                        United States (us)                                                        
Web Interface                 http://127.0.0.1:4040                                                     
Forwarding                    http://83ea683f.ngrok.io -> http://localhost:80                         
Forwarding                    https://83ea683f.ngrok.io -> http://localhost:80                        
                                                                                                        
Connections                   ttl     opn     rt1     rt5     p50     p90                               
                              17      2       0.24    0.05    2.48    6.52                              
                                                                                                        
HTTP Requests                                                                                           
-------------                                                                                           
                                                                                                        
GET  /photo.jpg                         200 OK                                                          
GET  /socket.io/                        200 OK                                                          
POST /socket.io/                        200 OK                                                          
GET  /socket.io/                        200 OK                            
                                                                               

Now your packages are smoothly sailing between internet and your nice local server.

Ngrok in action

I think a more real example would better illustrate the usefulness of ngrok. Let’s take this website, powered by Gatsby. I sometimes like to see how a new post would look like in social medias. One tool I like to use is Twitter Card Validator, just to check how the image is cropped, how the description excerpt is, etc. Since it is a online tool, I have two choices:

  1. Publish it as a draft, expose the URL;
  2. Use ngrok to expose my local version to the validator.

Although the first one is not all bad, it gives me some trouble. Especially because if there’s something wrong, I need to rework and push it again, going through more minutes of build and deploy on Gitlab CI/CD. Ngrok is just one command away! So I run that simple line:

./ngrok http 8000

This time I got this address: http://e9b5bea6.ngrok.io. So I access the card validator and test it:

Ngrok / Twitter Card Validator

Voilà! It looks ok, ready for deploy. You even have this nice web interface to inspect all requests you received. Good for debug!

Ngrok inspect interface

You can also use it with other protocols, like TCP (good for SSH tunneling) and websockets. You can configure some HTTP headers (like host) and ask for some simple authentication. Using the ngrok.yml config file you can “store” multiple host configurations and use them all at once, as well. More info can be found at online docs.

What about no-ip services? And SSH tunnels?

I used to expose ports online using a no-ip service. It means you can reserve a domain (like vschettino.no-ip.com), and the vendor would watch for changes on your IP address (gave by you ISP). On this method you still need to have some control over your network to allow a port forwarding from your external IP to your local machine. Sometimes it is easy to do that, like from your home. In bigger companies it sometimes can be a headache.

SSH tunnels are easy, secure and fast. A suitable choice when you have already a server exposed to the internet, with access from both your machine and the desired target. So you can pass trough this bridge server and get access to the desired port. The drawback here is obvious: you need to have this link between the origin and destination. This scenario is not always the same I use to consider ngrok.

Wait, is it paid?

It does have paid plans, although there’s this “free forever version”. The main benefits I see for paying are custom domains and more performance. You can have more connections per minute and open tunnels. To be honest it does feel a bit slow on the free plan, but it does the trick for my uses.

Actually, you do not even have to authenticate for start using ngrok. It only gives you a bit more of features and resources.

Conclusion?

If you have similiar use cases, you should consider ngrok. I use it sporadically to test external API callbacks (like those from Gitlab hooks and OAuth2 providers) and it works well too. Its easy of use/configuration also allows you to attach it to automated workflows and CI/CD pipelines.

Do I miss some neat feature you use? There are more nice scenarios where you can also count on ngrok to help? Please let me now :)