Post

How to create a self hosted ngrok

How to include the child model's fields in the dashboard and be able to search through them.

DigitalOcean Referral Badge

The Problem

I needed to use Facebook’s webhooks because I was creating a Messenger chatbot. In order for them to work in development I needed to “host” my local server so it can receive requests from Facebook. I tried using the free version of ngrok, but got an error (something related to security). So I was left with the option of paying for ngrok, or creating my own thing. So I spent a few days researching and I managed to puzzle together a free alternative of ngrok that worked for me.

Step 1: Create a DigitalOcean droplet

It is basically free, because you can use this referral link, which gives you 200$ of free credits. The machine we are going to use costs 4$ per month. We will also need a domain name.

Step 2: SSH into droplet

Get the IP of your machine and connect to it using ssh.

1
ssh root@your_droplet_ip

Step 3: Get a SSL certificate using certbot

We will obtain a free SSL certificate using Let’s encrypt. You don’t necessary need a certificate, but it is free and easy, so why not.

Input your domain, so it is easier to copy the commands directly


yourdomain will be used for all commands.

Install certbot

https://certbot.eff.org/instructions?ws=nginx&os=snap

1
2
3
sudo apt-get remove certbot &&
sudo snap install --classic certbot &&
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Once certbot is installed we can provision the certificate like this:

1
certbot -d tunnel.yourdomain -d *.tunnel.yourdomain --manual --preferred-challenges dns certonly

It will ask you for an email and to accept the terms of service. After this you will see:

1
2
Account registered.
Requesting a certificate for tunnel.yourdomain and *.tunnel.yourdomain

Finally, it will ask us to create TXT records.

1
2
3
4
5
Please deploy a DNS TXT record under the name:
_acme-challenge.tunnel.yourdomain.

with the following value:
tkSrK1GJZuZjTMnU09oHhVtJ0Q5iX8iVvEJJzo1ngKc

Step 4: Setup TXT records

Go on and create the two TXT records in your DNS settings. While you are there you can create two A records with *.tunnel and tunnel as the “hosts”, and the ip of your droplet as the “value” (I am using Namecheap). We will need this later.

The TXT records should be with host: _acme-challenge.tunnel and the value should be the one given in your command line.

Namecheap A records screenshot Namecheap TXT records screenshot

1
2
3
4
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.tunnel.yourdomain.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.
1
2
3
4
5
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/tunnel.combatist.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/tunnel.combatist.com/privkey.pem
This certificate expires on 2025-11-18.
These files will be updated when the certificate renews.

Step 5: Configure nginx

https://ubuntu.com/tutorials/install-and-configure-nginx#2-installing-nginx

1
2
sudo apt update -y &&
sudo apt install nginx -y

Go on and create this file, which we will need for our configuration:

1
sudo nano /etc/nginx/sites-available/tunnel.yourdomain

Paste this in the newly created file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
server {
    server_name tunnel.yourdomain;

    access_log /var/log/nginx/$host;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/tunnel.yourdomain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/tunnel.yourdomain/privkey.pem;

    location / {
        proxy_pass http://localhost:3000/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_redirect off;
    }

    error_page 502 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}
# Automatically redirect http to https
server {
    if ($host = tunnel.yourdomain) {
        return 301 https://$host$request_uri;
    }

    listen 80;
    server_name tunnel.yourdomain;
    return 404;
}

Create a link from /etc/nginx/sites-available/tunnel.yourdomain to /etc/nginx/sites-enabled/, to enable the configuration:

1
sudo ln -s /etc/nginx/sites-available/tunnel.yourdomain /etc/nginx/sites-enabled/

Now go and remove the default site, and restart nginx:

1
2
rm /etc/nginx/sites-enabled/default &&
sudo systemctl reload nginx

Step 6: Run your program

1
python3 -m http.server 8888

Step 7: Create a SSH reverse tunnel

Now you can exit the droplet and go to the command line of your own machine.

Start a SSH reverse tunnel:

1
ssh -R 3000:localhost:8888 root@your_droplet_ip

Now when you go to tunnel.yourdomain you will see the same thing you see on localhost:8888.




Sources:

This post is licensed under CC BY-NC 4.0 by the author.