If you’ve ever faced any limitations with ngrok, then it’s pretty easy to roll a custom solution. ngrok works, but if you find yourself needing multiple https domains for local development, you will have to upgrade to a paid plan, and the cost could add up pretty quickly. For me, this didn’t make financial sense since I had access to free cloud VMs.
In this tutorial, I will show you how to build a ngrok alternative using Inlets as an exit server and Caddy as a reverse proxy for HTTPS traffic. We will then map a subdomain we own to the Droplet’s public IP address for ease of access.
Click here to create an Ubuntu Droplet on digital ocean, feel free to configure as required.
You may set up your VM using any cloud provider of your choice, I choose to use DigitalOcean.
💡 GCP offers a $300 credit for first-time users
In your DNS host, create an A record pointing to your Droplets public IP address.
subdomain: sub.example.com
Type: A
value: your.droplet.ip.address
Your DNS host must support the ACME protocol since Caddy uses Let’s Encrypt for automatically provisioning SSL/TLS certificate.
If your DNS host does not support the ACME protocol, for example, GoDaddy, you can delegate your domain to a free DNS provider that does. Netlify offers free DNS management
SSH or password login into the Ubuntu Droplet we created.
curl -sLS https://get.inlets.dev | sudo sh
echo "deb [trusted=yes] https://apt.fury.io/caddy/ /" \
| sudo tee -a /etc/apt/sources.list.d/caddy-fury.list
sudo apt update
sudo apt install caddy
inlets server --port=80 --token=123
The token 123 is used here to keep things simple, you should use something more secure
curl -sLS https://get.inlets.dev | sudo sh
If you are on a mac, install with Homebrew
brew install inlets
rails s -p 4000
inlets client --remote=subdomain.example.com \
--upstream=http://127.0.0.1:4000 \
--token=123
Both the inlets client and server must have the same token
inlets server --port=8080 --token=123
Caddy needs port 80 to handle web traffic
caddy reverse-proxy \
--from subdomain.example.com \
--to localhost:8080
inlets client \
--remote=wss://subdomain.example.com \
--upstream=http://127.0.0.1:4000 \
--token=123
Caddy took care of obtaining an SSL certificate on our behalf and will renew it when it gets expired, basically it’s certbot+nginx on steriod.
/etc/systemd/system/inlets.service
[Unit]
Description=Inlets Exit Server
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=simple
Restart=always
RestartSec=1
StartLimitInterval=0
ExecStart=/usr/local/bin/inlets server --port=8080 --token=123
[Install]
WantedBy=multi-user.target
/etc/systemd/system/caddy.service
[Unit]
Description=Caddy Server
After=network.target network-online.target
Requires=network-online.target
[Service]
ExecStart=/usr/local/bin/caddy reverse-proxy --from subdomain.com --to localhost:8080
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable inlets
systemctl enable caddy
systemctl start inlets
systemctl start caddy
status
, start
, stop
, restart
followed by the service name