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 shecho "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 caddyinlets server --port=80 --token=123The token 123 is used here to keep things simple, you should use something more secure
curl -sLS https://get.inlets.dev | sudo shIf you are on a mac, install with Homebrew
brew install inletsrails s -p 4000 inlets client --remote=subdomain.example.com \
--upstream=http://127.0.0.1:4000 \
--token=123Both the inlets client and server must have the same token
inlets server --port=8080 --token=123Caddy needs port 80 to handle web traffic
caddy reverse-proxy \
--from subdomain.example.com \
--to localhost:8080inlets client \
--remote=wss://subdomain.example.com \
--upstream=http://127.0.0.1:4000 \
--token=123Caddy 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.targetsystemctl daemon-reload
systemctl enable inlets
systemctl enable caddy
systemctl start inlets
systemctl start caddystatus, start, stop, restart followed by the service name