The very blog post you are reading right now is being served from my RaspberryPI 4 on my work desk. If you have a spare laptop running 24/7 or a RaspberryPI, you might be tempted to serve applications on them. I’ll be iterating over the various ways you can expose a web app.
Cloudflare Zero Trust
For me personally, the term “Zero Trust” didn’t make much sense in the beginning but it basically means what it says; I trust no one and I want my app on my local laptop/server. You will install a cloudflared binary, use the provided APIs to set up an “everlasting” tunnel to Cloudflare servers and traffic comes back from the tunnel. You get their CDN and your app won’t be DOS/DDOSed by external actors.
Install the bad boy
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
Login
cloudflared tunnel login
Create the tunnel
cloudflared tunnel create blog-tunnel
Route traffic
cloudflared tunnel route dns blog-tunnel blog.yourdomain.com
Create a config file at ~/.cloudflared/config.yml
tunnel: <TUNNEL-UUID>
credentials-file: /home/yourusername/.cloudflared/<TUNNEL-UUID>.json
ingress:
- hostname: blog.yourdomain.com
service: http://localhost:80 # The local port your app runs on
- service: http_status:404
Run the tunnel
cloudflared tunnel run blog-tunnel
Pretty straightforward stuff. I’ve used this same exact approach for serving this blog site.
ddclient
Based on their own github repo: ddclient is a Perl client used to update dynamic DNS entries for accounts on many dynamic DNS services. It uses curl for internet access.
I used this method to access my custom AdGuard Home DNS server everywhere on my phone. Cloudflare’s free plan didn’t support irregular ports like 853 which I needed for Dns over TLS.
Most of the time, your internet provider assigns a public IP to your house and all you need to do is go to your router’s admin page, open up a couple of ports and select which local IP will be serving which incoming port and that’s it.
Two caveats though:
- You need to reserve the local IP of the device serving your app so it won’t change on reconnects.
- You need to react when your internet provider changes your house’s IP
The first one is simple. You just need to hang around in your router’s admin panel and you will find your way around.
For the second issue, ddclient will be your saviour. It supports many dns providers’ APIs, especially my favorite, Cloudflare!
Install the app
sudo apt update
sudo apt install ddclient
Go to your cloudflare dashboard, create a token for your domain with these accesses: Zone:Zone:Read and Zone:DNS:Edit, copy it. You’ll need to paste it into your config file.
Write the config file at /etc/ddclient.conf
daemon=300
syslog=yes
ssl=yes
use=web, web=https://api.ipify.org
protocol=cloudflare
server=api.cloudflare.com/client/v4
zone=yourdomain.com
ttl=60
login=token
password='<your-cloudflare-api-token>'
blog.yourdomain.com
Confine the config
sudo chmod 600 /etc/ddclient.conf
sudo chown root:root /etc/ddclient.conf
Give it a try
sudo ddclient -daemon=0 -debug -verbose -noquiet
Aaaand finalize
sudo systemctl enable --now ddclient
sudo systemctl status ddclient
Tailscale
I didn’t like it. After exposing your service to the internet, it gives you a domain but you will be left alone with it since the best you can do now is adding a CNAME record to mask the .ts.net domain tailscale provides behind your own domain but good luck with getting your proper TLS certificate for that!
So I’m not going through the steps, but if your use case is not affected by the domain, go for it.
Conclusion
Here were 3 (2 to be honest) to expose your apps. There are numerous ways out there (e.g. ngrok) you can try them out yourself.
The second approach using ddclient was the most novel to me and was the main reason I wanted to write this blog post. Hope you enjoyed it!