Your Localhost On The Internet And That Too SSL enabled With No Restrictions.
Introduction
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:
So why reinvent the wheel? Because you gotta get to the roots and understand the simple complexity. It's no big deal.
Prerequisites
So what all do we need?
- A Server (I will using $5 DO server)
- A Domain
- 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
- Setup the listening port using nginx on the server associating it with the subdomain.
- Add subdomain in DNS(We will be using awesome Digital Ocean DNS)
- Add SSL certificate provided by our favorite Let's Encrypt
- 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.
- There is
server_name
directive which tell what domain to serve the request,listen
directive for which port to listen on the domain. - The
location
directive is important here, here we are just proxing request fromlocalhost
with port4242
. This port is important since we will be directing our localhost traffic to it. Then there is setting header on the request. - 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.
CNAME is just an alias of our A/AAAA record. All three will appear as shown below
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.
Testing
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
Conclusion
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.
Top comments (5)
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/
Thanks
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.PS. add
nginx
after the 3 backticks for syntax highlighting in your code samples :)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?
Thanks for the explanation ! It is a nice trick to test services asking to expose a public API endpoint.