Localhost on the internet

root3d profile image G∆UR∆V Sehrawat; ・4 min read

Your Localhost On The Internet And That Too SSL enabled With No Restrictions.


There are tons of service which provide you the way to expose your localhost on internet. We need it for testing 3rd party APIs or show casing current development server. For example the most popular ones are:

  1. ngrok
  2. localtunnel
  3. pagekite

So why reinvent the wheel? Because you gotta get to the roots and understand the simple complexity. It's no big deal.


So what all do we need?

  1. A Server (I will using $5 DO server)
  2. A Domain
  3. Curiosity and Patience

What are the benefits of this setup? You may ask.

  • Total Custom Domain and as many domains you want.
  • No limits on usages
  • More than other services' paid plans

Let's get started, shall we?

It's just a 4 steps setup

  1. Setup the listening port using nginx on the server associating it with the subdomain.
  2. Add subdomain in DNS(We will be using awesome Digital Ocean DNS)
  3. Add SSL certificate provided by our favorite Let's Encrypt
  4. Forward the traffic using amazing SSH command.

Step 1 - Configuring server with nginx to serve traffic for the subdomain

Please install nginx on the server first.
You need to add one config file for nginx in sites-available folder of /etc/nginx assuming you are using Ubutnu. The nginx config file looks like below.

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;

server {
    server_name 42.igauravsehrawat.com;

    location / {
        proxy_pass http://localhost:4242;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        # Enables WS support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

server {
    server_name www.42.igauravsehrawat.com;

    location / {
        proxy_pass http://localhost:4242;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        # Enables WS support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

Let's take a look at config.

  1. There is server_name directive which tell what domain to serve the request, listen directive for which port to listen on the domain.
  2. The location directive is important here, here we are just proxing request from localhost with port 4242. This port is important since we will be directing our localhost traffic to it. Then there is setting header on the request.
  3. Rest of directive is enabling websocket support on this setup by upgrading the connection. That's all.

Note: You need to change server_name as per your required sub-domain instead of 42.igauravsehrawat.com.

Step 2 - Configuring Subdomain on DNS

Using Digital Ocean DNS Service, we will add a subdomain of our choice, it be 42.igauravsehrawat.com as done in step 1

For adding a subdomain, we will create 3 records(A Record, AAAA record, CNAME record)
A and AAAA records will redirect to our digital ocean server as shown below.
A & AAAA records

CNAME is just an alias of our A/AAAA record. All three will appear as shown below
All three

So that's all here, you should be able to access your sub-domain over internet, showing you 502 Bad Gateway page, which is expected since nothing is being forwarded to port 4242.

. Step 3 - Enabling SSL

Enabling SSL is piece of cake, more easy than that.Follow the certbot installation sets from here

Then run the magic command for nginx
sudo certbot --nginx

You will see something like below

Run it twice, one for sub-domain and one for CNAME(alias).

Now you should see this we you go to your sub-domain www.42.igauravsehrawat.com
This is expected since nothing is running on port 4242 of localhost at the server.

Woof, we are just one step away from the happy dance.

Step 4 - SSH Magic

Just one command to rule them all

ssh -N -R localhost:4242:localhost:3000 root@42.igauravsehrawat.com

-N tells "Do not execute a remote command. This is useful for just forwarding ports."
-R tells "Connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side."

First localhost is of the server and second is of local machine, then the address of your server. If you set up the SSH keys(Recommended) it would be seamless, no password, nothing.

That's it.

Happy Dance as promised.


Wait, wait, we haven't tested yet.


For testing I will just create a react app using create-react-app and do npm start to run it on port 3000(default).
And then run the magic SSH command
ssh -N -R localhost:4242:localhost:3000 root@42.igauravsehrawat.com

See it in action



With power of just one server, it is not that hard to have your own setup. You just have your own customized, SSL enable sub domain with no restrictions.


Editor guide
mikesheppard profile image

Nice one @root3d ! I found this super useful for quick & dirty testing.

One minor thing to halve the config, add the www. & other server names to the same block, server_name on nginx docs.

server {
  server_name local.example.com www.local.example.com lcl.exmpl.com;

PS. add nginx after the 3 backticks Syntax Highlighting for syntax highlighting in your code samples :)

laukstein profile image

Any guide how to setup it on Apache, and SSH requiring ppk key file and connecting to SSH trough IP (dot domain) because of security reasons?

tux0r profile image

I strongly discourage to expose your local machine as a server...

root3d profile image
G∆UR∆V Sehrawat; Author

I agree that debug mode should not be enable on localhost while exposing. And it should have authentication when it is on web.
I just provided an alternative to existing services like localtunnel.me/, ngrok.com/


seraphicrav profile image
Ravaka Razafimanantsoa

Thanks for the explanation ! It is a nice trick to test services asking to expose a public API endpoint.