Advertisers Hate This One Weird Trick

Pi-hole without A Raspberry Pi

Yes, you can absolutely run a Pi-hole without a Raspberry Pi.
Yes, you can absolutely install Pi-hole on to your laptop and take it with you.

Pi-hole to go! Yummy!

If you like the network-wide protection your home pi-hole provides against adverts, domains that are known phishing sites, or domains that are known to serve malware, then you are going to love finding out that you can have a local laptop install of pi-hole and take it with you wherever you go.

Just you, and your laptop. Nothing else.

A local laptop install of pi-hole can, in addition to other precautions, boost your protection if you are out and about in cafes, hotels and airports.

I’m going to cover installing a Docker powered Pi-hole on Windows and Linux systems.

At the very end of this article I will mention how a Pi-hole can protect you from the latest Google’s manifest V3 threat to your personal privacy.

Thanks to the Pi-hole Dev Team

Before we get to the nuts and bolts of getting your laptop protected with Pi-hole, lets take a moment to say thanks to the Pi-hole team.

Without the great work that the Pi-hole dev team carry out we wouldn’t have the opportunity to block advert, malware and other scam websites. They are a team with limited resources and the package they create is perfect for running natively on raspberry pi.

In this tutorial we will be running Pi-hole on docker. I suspect there is no extra bandwidth to maintain docker branches of pi-hole which is why I’ll show you an easy workaround for a common problem faced by people running pi-hole in a docker container.

Please consider donating to the Pi-hole project,

  • For the awesome service they provide.
  • To help keep them running.
  • Possibly expand their bandwidth to cover other types of pi-hole installs.
  • Keep it free for people that really really can’t afford to donate.

Windows Laptops

Prerequisites

Prerequisite 1) Docker Desktop

Head over to docker.com and install Docker Desktop.
https://www.docker.com/products/docker-desktop/

Prerequisite 2) Autostart Windows

Ideally after installation you should enable autostart for Docker Desktop.

This ensures that you can still access webpages. Pi-hole will resolve all of your website/DNS requests, if the Pi-hole docker container is off then you won’t be able to visit webpages.

You also need to make a change in Docker Desktop settings, make sure that you check the ‘Start Docker Desktop when you log in‘ box.

Pull Official Pi-hole Docker Image

We are going to use the official Pi-Hole Docker image, use their docker-compose.yml with a minor modification. Head over to https://hub.docker.com/r/pihole/pihole to find out more about the official Pi-hole Docker Image.

The rest of this article fills in the gaps so that you can have Pi-hole up and running on your PC.

Open up a command prompt and run the pull command.

C:\Users\goodboy>docker pull pihole/pihole
Using default tag: latest
latest: Pulling from pihole/pihole
31b3f1ad4ce1: Pull complete
2cf454ba7aa0: Pull complete
4f4fb700ef54: Pull complete
d5d1e33c70cc: Pull complete
82b13da8209d: Pull complete
48e71cb85034: Pull complete
Digest: sha256:aa6140856dfc67f3ae36c352e30903f944e4e220699ffeeaf6b85235b2d84c95
Status: Downloaded newer image for pihole/pihole:latest
docker.io/pihole/pihole:latest

C:\Users\goodboy>

Docker Compose File

We want to run Pi-hole only locally on your laptop and not as a wider network service.
The docker-compose.yml file below is taken from the example docker-compose.yml file on the official Pi-hole docker page but with all DHCP references removed.

You should change the time zone, and add your own ‘WEBPASSWORD‘ password. You will use this password later to access the Pi-hole admin page.

Also, as noted above, the docker version is quite close to perfect but needs a helping hand. You could request that you want the ‘lastest‘ tag/version of the docker container but the workaround in the next paragraph is guaranteed to work with the tag ‘2023.01.10‘ as stated in the line 6. You can of course replace that with latest if you wish to try.

The addition of the environment variable ‘WEB_UID: 999‘ on line 14 is a workaround for not being able to add new advert lists, modify black and white lists, or do any operation that requires writing to the pihole database.

version: "3"

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:2023.01.10
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
    environment:
      TZ: 'America/Chicago'
      WEBPASSWORD: 'choose a password'
      WEB_UID: 999
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'    
    restart: unless-stopped

Create a new folder/directory (also referred to a ‘docker context’), anywhere on your user account and create the file with name ‘docker-compose.yml’ and add the above content.

Open up a command prompt and run the command ‘docker-compose up –detach‘ .

C:\Users\goodboy\pihole>docker-compose up --detach
[+] Running 2/2
 - Network pihole_default  Created                                                                                 0.9s
 - Container pihole        Started                                                                                 2.0s

C:\Users\goodboy\pihole>

If you check your Docker Desktop you should see a Pi-hole container running.

Check For Admin Page

Before we finalise your Pi-hole network settings lets check that your Pi-hole is actually running.

Open a web browser and visit the following local webpage ‘http://localhost/admin/, you should bookmark this for convenience.

Login with the password you chose in the docker-context.yml file above.

You should be met with the Pi-hole admin page.

Modify Windows Network Settings

The final step is to let windows know it should use your Pi-hole to run DNS requests.

This isn’t a permanent change and you can always change this back, but, because it’s semi-permanent you need to make sure that docker starts up when windows starts up so that your web browsers have a target to make DNS requests.

Open up control panel, and select ‘Network and Sharing Center‘.

Then select ‘Change adapter settings‘.

You should do the following steps for each adapter you use to connect to the internet.
I’m going to do this to my Wi-Fi adapter as that is the only way I connect to the internet.

Right click on your adapter and select ‘Properties

Select ‘Internet Protocol Version 4(TCP/IPv4)‘ and click ‘Properties

Since we are running Pi-hole locally on our laptop, we need to point our ‘Preferred DNS server‘ to our local loopback IP address. Select the ‘Use the following DNS server addresses:‘ radio button, and add the address ‘127.0.0.1‘ to ‘Preferred DNS server:

Click okay. If you go back to your pihole admin page ‘http://localhost/admin/‘ and log in, you should
see that the Pi-hole is immediately taking DNS requests and protecting you.

If your internet ever drops out, if your docker fails, return your adapter settings to the values before or even set the ‘Obtain DNS server address automatically‘ radio button.
Caution: You will no longer be protected by Pi-hole in this case.

VPN compatibility

A portable Pi-hole in your bag is one great advantage.

The other advantage of running docker directly from your local laptop is that suddenly you have Pi-hole protection when connecting to your VPN provider. ProtonVPN, NordVPN, whichever other VPN provider you user, via their VPN apps or OpenVPN, your web browser will make a DNS request to your local Pi-hole before tunneling through your VPN.

Pi-hole working with VPN? Cool eh? Well…. enjoy your Pi-hole.

Linux Laptops

I’m working on Debian based systems, so Ubuntu and Linux Mint and will cover installing a laptop portable Pi-hole for these systems.

Prerequisites

Prerequisite 1) Docker

There are two options for you here. You could go ahead and install Docker just to be used from the command line (which I prefer), or with Docker Desktop.

Option 1) Docker Install Without Docker Desktop

Open up a terminal and update your system.

ubuntu@goodboy:~$ sudo apt update
Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Ign:2 http://packages.linuxmint.com vanessa InRelease                                                                                                                                                                                        
Get:3 http://packages.microsoft.com/repos/code stable InRelease [10,4 kB]                                                                                                                                                                    
Hit:4 https://brave-browser-apt-release.s3.brave.com stable InRelease                                                                                        
Hit:5 https://repo.protonvpn.com/debian stable InRelease                                                                                                     
Get:6 http://packages.linuxmint.com vanessa Release [24,1 kB]                                        
Hit:7 http://archive.ubuntu.com/ubuntu jammy InRelease                                  
Get:8 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [114 kB]
...
...
...
Fetched 2.670 kB in 5s (505 kB/s)             
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
50 packages can be upgraded. Run 'apt list --upgradable' to see them.
ubuntu@goodboy:~$ 

You are ready to install Docker. Run the following command and don’t forget the astrix ‘*’, the astrix catches all necessary docker packages.

 sudo apt install docker*

Your output should look something like the following. I have removed a lot of output to keep it neat.

ubuntu@goodboy:~$ sudo apt install docker*
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'docker-compose' for glob 'docker*'
Note, selecting 'docker.io-doc' for glob 'docker*'
Note, selecting 'docker2aci' for glob 'docker*'
Note, selecting 'docker-doc' for glob 'docker*'
Note, selecting 'docker-ce' for glob 'docker*'
Note, selecting 'docker.io' for glob 'docker*'
Note, selecting 'docker' for glob 'docker*'
Note, selecting 'docker-clean' for glob 'docker*'
Note, selecting 'docker-registry' for glob 'docker*'
Note, selecting 'docker-doc' instead of 'docker.io-doc'
The following additional packages will be installed:
...
...
...
Need to get 74,3 MB of archives.
After this operation, 311 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Let’s check if docker is installed.

ubuntu@goodboy:~$ docker --version
Docker version 20.10.12, build 20.10.12-0ubuntu4
ubuntu@goodboy:~$ 

And now add the docker group,

ubuntu@goodboy:~$ groupadd docker

also add your current user to the docker group, and check that you are added to the group,

ubuntu@goodboy:~$ sudo usermod -aG docker $USER
ubuntu@goodboy:~$ id -Gn ubuntu
ubuntu adm cdrom sudo dip plugdev lpadmin sambashare docker

You need to log out and log back in, maybe even restart so that your docker membership is applied.
Okay, we are ready to continue.

Option 2) Docker Install With Docker Desktop

You do also have the option to instead install Docker Desktop on your linux machine.
Follow the instructions at the following ling to do this.

https://docs.docker.com/desktop/install/linux-install/

You will find instruction at that link for Ubuntu, and you may think that the instructions apply to
derivative distros like Linux Mint…. well… mostly, except for one small detail that will make you
pull your hair out.

So, by popular demand here are instructions specific to installing Docker, and Docker Compose on to Linux Mint systems.

Prerequisite 2) Autostart Linux

As noted at https://docs.docker.com/engine/install/linux-postinstall/#configure-docker-to-start-on-boot
on Debian and Ubuntu based systems, the Docker service is configured to start on boot by default.
To setup autostart for non Debian systems please read the above link.

Pull Official Pi-hole Docker Image

As in the Windows case, run the following command to pull the official Pi-hole image.

ubuntu@goodboy:~$ docker pull pihole/pihole
Using default tag: latest
latest: Pulling from pihole/pihole
31b3f1ad4ce1: Pull complete 
2cf454ba7aa0: Pull complete 
4f4fb700ef54: Pull complete 
d5d1e33c70cc: Pull complete 
82b13da8209d: Pull complete 
48e71cb85034: Pull complete 
Digest: sha256:aa6140856dfc67f3ae36c352e30903f944e4e220699ffeeaf6b85235b2d84c95
Status: Downloaded newer image for pihole/pihole:latest
docker.io/pihole/pihole:latest
ubuntu@goodboy:~$ 

Docker Compose File

Create And Run Docker Compose File

We’re going to use the same docker-compose.yml file as we did before. Here it is again.

Notice I have replaced latest here with 2023.01.10 as this is the latest docker tag I tested this worked with. The workaround mentioned earlier using ‘WEB_UID’ is also present.

version: "3"

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:2023.01.10
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
    environment:
      TZ: 'America/Chicago'
      WEBPASSWORD: 'choose a password'
      WEB_UID: 999
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'    
    restart: unless-stopped

Save this file in a directory/folder, again usually referenced to as a docker context.
Then run the command ‘docker-compose up –detach’.

Error: Cannot start service pihole: driver failed programming external connectivity on endpoint pihole

Oh oh…… don’t panic, this error was expected. Port 53 is used for Domain Name Resolution and the error states that it is already in use. Pi-hole wants port 53 to itself.

ubuntu@goodboy:~/pihole$ docker-compose up --detach
Creating network "pihole_default" with the default driver
Creating pihole ... 
Creating pihole ... error

ERROR: for pihole  Cannot start service pihole: driver failed programming external connectivity on endpoint pihole (daf6fe4a4b196b99572098bece676988056341f86dd260cd4a3bc0ad4647a153): Error starting userland proxy: listen tcp4 0.0.0.0:53: bind: address already in use

ERROR: for pihole  Cannot start service pihole: driver failed programming external connectivity on endpoint pihole (daf6fe4a4b196b99572098bece676988056341f86dd260cd4a3bc0ad4647a153): Error starting userland proxy: listen tcp4 0.0.0.0:53: bind: address already in use
ERROR: Encountered errors while bringing up the project.

now… you may have thought it was going to run smoothly. From the above output it is clear it did not. You will most likely face the same issue on your linux machine so were going to run through troubleshooting this. Lets run netstat and see what is hogging port 53.

ubuntu@goodboy:~/pihole$ sudo netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      576/systemd-resolve 
udp        0      0 127.0.0.53:53           0.0.0.0:*                           576/systemd-resolve 

Well, well, well… if it isn’t systemd-resolve. Your linux system already resolves DNS on that port 53, we have a conflict that needs to be managed.

Manage The Port 53 Conflict

If you look at the documentation for systemd-resolve you will see confirmation that it is a ‘Network Name Resolution manager’, which is exactly what Pi-hole is. No wonder there is a conflict.

The Pi-hole Docker documentation covers this, as can be read here.

WARNING: Managing this conflict will remove DNS resolution until your Pi-Hole is up and running!! Make a local copy of these instructions before continuing.

Step 1) Disable The Stub Resolver On Your System

You can edit the ‘/etc/systemd/resolved.conf’ directly or run the following command.

sudo sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf

I would open up ‘/etc/systemd/resolved.conf’ and double check anyway.

Step 2) Change The resolv.conf Sym Link

Run the following command.

sudo sh -c 'rm /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'

Step 3) Restart systemd-resolved

Run the following command.

systemctl restart systemd-resolved

Continue Installing Pi-hole

At this point your machine won’t be able to resolve DNS requests, and so will have no real internet access until we finish installing Pi-hole.

Step1) Re-run Docker Compose Up

ubuntu@goodboy:~/pihole$ docker-compose up --detach
Starting pihole ... done
ubuntu@goodboy:~/pihole$ 

That worked quite well.

Step 2) Modify Linux Network Settings

This may vary for your machine. I got to this place by left clicking on my network icon and clicking network settings.

Set your DNS to your local machine.

Access Pi-hole Admin Page

Head straight over to the pihole website at localhost.

VPN

If you are running a VPN, if you set your DNS to your loopback IP ‘127.0.0.1’ the Pi-hole will reply to your DNS requests.

WARNING: !!!DNS LEAK!!!

One purpose of using a VPN is to protect your DNS traffic, and VPNs do this well. If you use Pi-Hole you will have noticed that pi-hole asks you to chose upstream DNS servers and depending on your personal threat model you may not want cloudflare or google to profile you via DNS requests. A solution to this is to run your own recursive DNS server locally on your laptop. I will cover this at a later date.

Check for DNS leaks at,

https://dnscheck.tools/ and https://www.dnsleaktest.com/

if you see any DNS servers other than your VPN then you have a leak.

Google Manifest V3 & Ad Blockers

Considering Google’s entire business model is to track you, create profiles, and push adverts to you it is clear why they have made it near impossible for you to prevent them from doing this in any chrome based browser, that included ‘Microsoft Edge’. Of course, they try to sell this to you as something ‘for your own protection’ LOL.

Previously in the old Chrome Manifest V2 the API webRequest was available to Chrome extension developers. webRequest is the backbone of all Ad Blocker / Tracker Blocker Chrome extension technology and without it in browser Ad Blockers will be affected, which will severely limit what Ad Blockers can do and harms your privacy – some extensions will just not work at all.

Pi-hole implements network level blocking, which your browser has no control over.

What can you do? Three options.

  • Install a Pi-hole in your home network with a Raspberry Pi or another cheap computer.
  • Install a Docker powered Pi-hole on your personal laptop or computer.
  • Switch to a browser that will continue to support the webRequest API. Download Firefox.

Why not all three? I do, and it works really well. My preference is Brave Browser which, although does use Manifest V3, does have inbuilt tracker and advert blocking.

If you want further protection for your phone, consider using https://grapheneos.org/ and buy a second cheap phone for any Google authentication you need.

I know… as a small website that runs adverts to support itself, I am shooting myself in the foot giving you this advice – but I hope with the freedom of choice, you will control which adverts and which websites you choose to support and add to your whitelist. 😉

Other:

communications error to 127.0 01 53: connection refused

If you are running code that needs to make many queries you might get this error, then spend 2 hours tearing your hair out.
Please check your DNS settings in pihole first, it is doing its job correctly. You can temporarily lift a rate limit by setting both fields to 0.

One thought on “Pi-hole: A Portable Docker Laptop Solution”

Leave a Reply