Free, private pi-hole hosting with Fly.io and Tailscale

Hosting a network-wide pi-hole for ad-blocking is easy. It comes with a one-step installation guide that you can run on most environments. I run two pi-holes at my house, but the problem with my setup is, if my internet drops, both pi-holes stop working too. Ideally, I’d need to have a pi-hole outside my house, preferably where internet doesn’t go down at the same time as my provider.

That’s where a cloud-hosted pi-hole proves helpful.

I learned about Fly.io recently. It’s an app hosting platform that makes it incredibly easy to deploy apps to multiple regions and scales as needed. Their free tier offers a generous 2,340 hours per month of uptime, which translates to about 3 shared-cpu-1x VMs with 256MB RAM full time. My pi-hole consumes about 200MB RAM consistently, so this means I could host upto 3 apps each with pi-hole on it. But I have only one as I have two others at my house.

A screenshot from Fly.io's pricing page that shows their free tier metrics.
Fly.io free tier

Setting up the pi-hole

This Fly blog post already documents how you can run a pi-hole in a few steps, but there is a problem with this setup: the pi-hole will be publicly query-able by anyone on the internet. We don’t want that because a public, open DNS resolver is not a good idea. We’ll need to lock this down using a secure tunnel that’s accessible only to you.

Locking down pi-hole access with Tailscale

If you are following my blog, you’d know by now that I am a Tailscale fan. It’s an easy, useful mesh VPN software that you can add to most devices that you have. For the pi-hole on Fly.io setup, I followed the same guide as Fly documented, but in the Dockerfile configuration, I replaced eth0 with tailscale0 so that my pi-hole listens for queries only on the Tailscale network.

With that image deployed, I SSH’d into the Fly instance and installed Tailscale using the Debian installation guide here: Install Tailscale on Linux. That’s not quite easy though. I had to use legacy iptables and then run ./tailscaled & under usr/sbin folder. From there, I could run sudo tailscale up.

Stopping ./tailscaled stops Tailscale, so as a workaround for now, I just close the tab where ./tailscaled is running. I am pretty sure that’s not how I must be doing it, but it works for now.

I further locked down this Fly instance’s DNS port access to my Tailscale nodes as I don’t want anyone else on my Tailnet (I share it with my friends and family) to make other calls to the Fly node. A handy Tailscale ACL like the one below works:

{ "Action": "accept", "Users": ["group:not-arun-family"], "Ports": ["fly:53"] },

2 responses to “Free, private pi-hole hosting with Fly.io and Tailscale”

  1. Hi there, thanks for the nice write-up.

    I have two notes in case you are still using this setup:
    1. Tailscale has written a short guide on how to run Tailscale(d) on fly.io: https://tailscale.com/kb/1132/flydotio/.
    2. As fly.io offers auto scaling, multiple Pi-hole’s could be spun up as well to allow for some more resilience (the assigned IP addresses are anycast). In this case the settings can be kept up to date using Gravity Sync: https://github.com/vmstan/gravity-sync.

    Thanks again and have a nice day! 🙂

    Like

    1. Thanks for sharing, Anon! I am not familiar with the concept of anycast yet. Does scaling to new regions mean each pihole web admin would be available on its own IP address, and are these addresses listed within Fly’s app dashboard?

      Like

Leave a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: