Tailscale Pi-hole Setup
I’ve recently started using the overlay network Tailscale to provide connectivity between my various machines, regardless of where I am. It’s extremely easy to configure and “just works”. Tailscale also includes a feature called MagicDNS that provides name resolution for machines on my tailnet (i.e. so that ping server123
magically just works). MagicDNS also allows you to override local DNS settings and force a custom DNS server for name resolution machines on your tailnet. This post documents the setup of Pi-hole (accessible only to machines on my tailnet) to provide some level of DNS privacy and Ad Blocking for machines on my tailnet.
I have a Digital Ocean VPS that I wanted to use for my Pi-hole instance (since failures in DNS are annoying, I wanted it more reliable than putting this on my home servers). I already had Docker configured on this machine and the setup will leverage that.
The first step was to create a docker-compose.yml
file that would spin up two containers.
- The
tailscale
container handles connecting to tailscale and providing tailnet connectivity to another - The
pihole
container seems self explanatory 😄
|
|
Next, start up the containers.
$ docker compose up
Then we have to connect our tailscale container to our tailnet manually the first time.
$ docker compose exec tailscale tailscale up
To authenticate, visit:
https://login.tailscale.com/a/aaaaaaaaaaaa
Copy the above URL and load that up in a browser to add this new node to your tailnet (authorizing it if necessary).
Make sure the Tailscale ACL allows connectivity from your other nodes. Your ACL should include some stuff kinda like this.
{
"hosts": {
"pihole": "100.104.250.27", // from admin console
},
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["pihole:53", "pihole:80"],
}
],
}
Finally, turn on MagicDNS (if it’s not on already), add your Pi-hole tailnet IP address (100.104.250.27 in my example) to your list of Global Nameservers and toggle Override local DNS
.
You should now be able to connect to your Pi-hole instance over your tailnet http://pihole/admin
and configure it (using the password in your configured password). Make sure to adjust it to permit requests from all origins (safe since this thing is only accessible to your machines on your tailnet).
From machines on your tailnet, you should be able to verify things are working properly with nslookup
.
A non-blocked site should work as normal.
$ nslookup alpha.erraticbits.ca
Server: magicdns.localhost-tailscale-daemon
Address: 100.100.100.100
Non-authoritative answer:
Name: alpha.erraticbits.ca
Addresses: 2604:a880:cad:d0::ec0:2001
165.227.32.145
And you can see the request hit the Query Log on the Pi-hole instance.
A query for a blocked Ad CDN will fail:
$ nslookup cdn.bannersnack.com
Server: magicdns.localhost-tailscale-daemon
Address: 100.100.100.100
Name: cdn.bannersnack.com
Addresses: ::
0.0.0.0
And you can see that failure in Pi-hole’s Query Log.
That’s it.
--accept-dns=false
parameter otherwise you’ll run into issues starting the Pi-hole’s tailscale container on that machine.