Access localhost from the internet – External service callbacks made easy with LocalTunnel

Sony Mathew

Sony Mathew

Published on

3 minute read

Improve development experience with external service callbacks from Facebook, Twitter, Twilio etc., using LocalTunnel.

Working with third-party integrations

As a product developer, one of the biggest pain points that you come across might be related to working with callbacks (mostly webhooks) from third party systems in your local development environment. Most of us use some tunnelling software to expose our local server to the internet and then use that URL for the callbacks.

There are some pain points with this setup. Usually, tunnelling software has this annoying side-effect of changing the exposed URL every time you restart. If you have shared it with your colleagues for testing, you would have to send the new URL again. If you are working on the webhook callbacks with third-party integrations, like Facebook, Twitter, Zapier, Twilio, etc., this becomes frustrating. Every time you restart the tunnel, you have to go to the developer console and update the callback URL. This workflow is cumbersome, and often we forget this and spend a good amount of time debugging on other things.

Chatwoot's Context

At Chatwoot, we have multi-channel support and have inbox support for Facebook, Twitter, Twilio, Slack, chatbots, and various email platforms. We constantly struggled with this problem.

One way to mitigate the problem was by getting individual paid accounts for every team member and get a static URL for the tunnel. This approach solved some of the issues as we don't need to update the callback URLs every time we restart the local system. For the entire period of development, the URL stays the same.

Everything seemed good initially. After some time, we started running into problems again with this setup. When multiple engineers work on a single integration, they have to change the callback URL to their tunnel URL whenever they work on it. Nobody called dibs on this, and often we forget to check the callback URL when we start the work. We were on the path to expand our integrations as a part of the omnichannel support and we wanted a better development experience.

We needed the API callback URLs to stay constant, and it should be easy for any developer to get hold of that tunnel URL. As a possible solution, we looked for open source tunnelling softwares that we could host and customize. That is when we came across LocalTunnel and fell in love with it.

What is LocalTunnel?

LocalTunnel exposes your localhost to the world for easy testing and sharing. It is an open-source software. (https://github.com/localtunnel/localtunnel). From the number of stars and forks of this project, you can see that the community loves this product.

How did we set it up?

We decided to set up our own LocalTunnel on a Digital Ocean droplet. We followed this excellent article written by Alex to host LocalTunnel on Digital Ocean. In addition to the setup guide, we had to open a range of ports on the droplet to allow TCP connections.

We pointed one of the subdomains to the droplet that runs LocalTunnel, which looks something like https://tunnel.example.com.

Development Workflow

To start working with LocalTunnel, you have to install the LocalTunnel client on your machine using the following command.

npm install -g localtunnel

You can connect to the LocalTunnel server by specifying the port and a host name.

lt --port 3000 --host http://tunnel.example.com

By default, LocalTunnel would generate a subdomain using random characters. The URL would look like https://[random-characters].tunnel.example.com

In addition to this, LocalTunnel allows you to request a named subdomain on the LocalTunnel server.

lt --port 3000 --host http://tunnel.example.com --subdomain customsubdomain

This feature allowed us to standardize the list of subdomains to the external services as seen below:

Service Subdomain
Facebook fb-dev.tunnel.example.com
Sendgrid sendgrid-dev.tunnel.example.com
Mailgun mailgun-staging.tunnel.example.com
Twitter twitter-staging.tunnel.example.com
Twilio twilio-dev.tunnel.example.com

An important thing to note here is that when we use a subdomain, for example, Facebook development as fb-dev.tunnel.example.com, we set all the callbacks on the Facebook developer account to this subdomain. Similarly, we set the callback URL on the Twitter developer account for Twitter app development to twitter-dev.tunnel.example.com and so on.

For working on Facebook inbox, we would connect to the standard tunnel URL:

lt --host http://tunnel.example.com --subdomain fb-dev --port 3000

With this approach, we solved both problems mentioned above.

  1. Now that you had a standard set of URLs, you don't have to go to the developer console every time to change it.
  2. Any team member can get hold of any of these tunnels using their LocalTunnel Client seamlessly.

This approach has improved our development workflow to a great extend. The developers don't have to worry about the URL they would use in development. If they conform to the standard URL, everything works seamlessly.

Let us know if you have any questions or if this article helped you in improving your development experience. We are all ears. :)