paarth.me

home

about

blog

games

photos

reading

code

projects

zines

links

now

uses

music

colophon

changelog



Pi-hole Zine: Network Ad Blocking with Docker

PI-HOLE ZINE

Network-Wide Ad Blocking on OMV 7

Block ads on EVERY device with one setup


WHAT YOU’RE BUILDING

                    BEFORE

    +--------+     +--------+     +--------+
    | PHONE  |     | LAPTOP |     | TABLET |
    +--------+     +--------+     +--------+
         |              |              |
         v              v              v
    +----------------------------------------+
    |              ROUTER                    |
    |         DNS: 8.8.8.8 (Google)          |
    +----------------------------------------+
                      |
                      v
    +----------------------------------------+
    |            INTERNET                    |
    |    (ads, trackers, malware)            |
    +----------------------------------------+


                    AFTER

    +--------+     +--------+     +--------+
    | PHONE  |     | LAPTOP |     | TABLET |
    +--------+     +--------+     +--------+
         |              |              |
         v              v              v
    +----------------------------------------+
    |              ROUTER                    |
    |        DNS: 192.168.1.200              |
    +-------------------|--------------------+
                        |
                        v
    +----------------------------------------+
    |             PI-HOLE                    |
    |    "Is this an ad? BLOCKED!"           |
    |    "Is this legit? ALLOWED!"           |
    +----------------------------------------+
                        |
                        v
    +----------------------------------------+
    |         CLEAN INTERNET                 |
    |      (no ads, no trackers)             |
    +----------------------------------------+

DNS Query Flow

flowchart LR
    Devices -->|DNS| R[Router] -->|DNS| PH[Pi-hole<br/>macvlan] -->|Filtered| UP[1.1.1.1]
    style PH fill:#f96,stroke:#333

How Queries Are Processed

flowchart LR
    D[Device] -->|Query| P[Pi-hole]
    P -->|Ad?| B[Block 0.0.0.0]
    P -->|OK| U[Upstream] --> D

THE ARCHITECTURE

+--------------------------------------------------+
|                RASPBERRY PI                       |
|                                                   |
|  +--------------------+  +--------------------+   |
|  |   OPENMEDIAVAULT   |  |      DOCKER       |   |
|  |    (NAS System)    |  |   (Containers)    |   |
|  +--------------------+  +--------------------+   |
|                               |                   |
|                    +----------+---------+         |
|                    |                    |         |
|              +-----------+      +-----------+     |
|              | PORTAINER |      |  PI-HOLE  |     |
|              | (Manager) |      | (Ad Block)|     |
|              +-----------+      +-----------+     |
|                                       |           |
|                              192.168.1.200        |
|                              (Own IP via         |
|                               macvlan)           |
+--------------------------------------------------+

SETUP FLOWCHART

[1] INSTALL OMV-EXTRAS
        |
        v
[2] INSTALL DOCKER PLUGIN
    (System > Plugins)
        |
        v
[3] DEPLOY PORTAINER
    (Container Manager)
        |
        v
[4] CREATE DIRECTORIES
    /docker/appdata/pihole-config/
        |
        v
[5] FIX PORT 53 CONFLICT
    (Disable systemd-resolved)
        |
        v
[6] CREATE MACVLAN NETWORK
    (Give Pi-hole its own IP)
        |
        v
[7] DEPLOY PI-HOLE CONTAINER
    (Via Portainer)
        |
        v
[8] CONFIGURE ROUTER DNS
    (Point to Pi-hole)
        |
        v
[9] TEST & ENJOY AD-FREE LIFE!

Setup Flow Diagram

flowchart LR
    A[Docker] --> B[Portainer] --> C[Dirs] --> D[Macvlan] --> E[Pi-hole] --> F[Router]

CONFIGURATION VALUES

+-------------------+---------------------------+
|    PARAMETER      |      YOUR VALUE           |
+-------------------+---------------------------+
| OMV Server IP     | ___.___.___.___           |
| Router/Gateway    | ___.___.___.___           |
| Pi-hole IP        | ___.___.___.___           |
| Network Interface | eth0 / end0 / enp0s3      |
| Timezone          | _________________________ |
| Pi-hole Password  | _________________________ |
+-------------------+---------------------------+

TIMEZONE EXAMPLES:
* Asia/Kolkata     (India)
* America/New_York (US East)
* Europe/London    (UK)
* Asia/Tokyo       (Japan)

PORTAINER INSTALLATION

# Create volume for Portainer data
docker volume create portainer_data

# Deploy Portainer
docker run -d \
  -p 9000:9000 \
  --name=portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:latest

ACCESS PORTAINER

+----------------------------------+
|  Browser: http://OMV_IP:9000     |
|                                  |
|  Create admin account:           |
|  - Username: admin               |
|  - Password: (12+ characters)    |
+----------------------------------+

DIRECTORY STRUCTURE

/srv/dev-disk-by-uuid-xxxxx/
    |
    +-- docker/
         |
         +-- appdata/
              |
              +-- pihole-config/
                   |
                   +-- pihole/      <-- Config & DB
                   |
                   +-- dnsmasq.d/   <-- DNS config

CREATE DIRECTORIES

DISK="/srv/dev-disk-by-uuid-YOUR-UUID"

mkdir -p ${DISK}/docker/appdata/pihole-config/pihole
mkdir -p ${DISK}/docker/appdata/pihole-config/dnsmasq.d

chown -R 999:999 ${DISK}/docker/appdata/pihole-config
chmod -R 755 ${DISK}/docker/appdata/pihole-config

FIX PORT 53 CONFLICT

THE PROBLEM

+------------------+
|  systemd-resolved | <-- Uses port 53
+------------------+
        |
        X  CONFLICT!
        |
+------------------+
|     Pi-hole      | <-- Also needs port 53
+------------------+

THE FIX

# Edit configuration
sudo nano /etc/systemd/resolved.conf

# Change this line:
[Resolve]
DNSStubListener=no

# Restart service
sudo systemctl restart systemd-resolved

# Verify port is free
sudo ss -tulpn | grep :53
# Should be empty!

MACVLAN NETWORK

WHY MACVLAN?

BRIDGE NETWORK (Problems):
+------------------+
|  OMV + Pi-hole   |  Both want port 53!
|  Same IP = FAIL  |  Port conflict!
+------------------+


MACVLAN NETWORK (Solution):
+------------------+     +------------------+
|       OMV        |     |     Pi-hole      |
|  192.168.1.100   |     |  192.168.1.200   |
+------------------+     +------------------+
         |                        |
         +------------------------+
                    |
            +---------------+
            |    ROUTER     |
            |  192.168.1.1  |
            +---------------+

CREATE THE NETWORK

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  --ip-range=192.168.1.200/32 \
  -o parent=eth0 \
  pihole_macvlan
PARAMETER GUIDE:
+------------------+---------------------------+
| --subnet         | Your network (usually     |
|                  | 192.168.1.0/24)           |
+------------------+---------------------------+
| --gateway        | Your router IP            |
+------------------+---------------------------+
| --ip-range       | IP for Pi-hole            |
|                  | /32 = single IP only      |
+------------------+---------------------------+
| -o parent        | Network interface name    |
|                  | (eth0, end0, enp0s3)      |
+------------------+---------------------------+

PI-HOLE CONTAINER SETUP

IN PORTAINER

+------------------------------------------+
|  BASIC SETTINGS                          |
+------------------------------------------+
| Name:   pihole                           |
| Image:  pihole/pihole:latest             |
+------------------------------------------+

+------------------------------------------+
|  NETWORK                                 |
+------------------------------------------+
| Network:     pihole_macvlan              |
| IPv4 Address: 192.168.1.200              |
+------------------------------------------+

+------------------------------------------+
|  VOLUMES                                 |
+------------------------------------------+
| /etc/pihole    -> .../pihole-config/pihole    |
| /etc/dnsmasq.d -> .../pihole-config/dnsmasq.d |
+------------------------------------------+

+------------------------------------------+
|  CAPABILITIES                            |
+------------------------------------------+
| [x] NET_ADMIN   <-- REQUIRED!            |
+------------------------------------------+

+------------------------------------------+
|  RESTART POLICY                          |
+------------------------------------------+
| Unless stopped                           |
+------------------------------------------+

ENVIRONMENT VARIABLES

+-------------------+---------------------------+
|       NAME        |         VALUE             |
+-------------------+---------------------------+
| TZ                | Asia/Kolkata              |
|                   | (your timezone)           |
+-------------------+---------------------------+
| WEBPASSWORD       | YourNewPassword123        |
|                   | (NEW password for         |
|                   |  Pi-hole admin only!)     |
+-------------------+---------------------------+
| SERVERIP          | 192.168.1.200             |
|                   | (Pi-hole's macvlan IP)    |
+-------------------+---------------------------+
| PIHOLE_DNS_       | 1.1.1.1;1.0.0.1           |
|                   | (upstream DNS)            |
+-------------------+---------------------------+
| DNSSEC            | true                      |
+-------------------+---------------------------+
| DNSMASQ_LISTENING | all                       |
+-------------------+---------------------------+

PRIVACY-FOCUSED DNS OPTIONS

+-------------+-------------------+------------------+
|  PROVIDER   |     PRIMARY       |    SECONDARY     |
+-------------+-------------------+------------------+
| Cloudflare  | 1.1.1.1           | 1.0.0.1          |
| Quad9       | 9.9.9.9           | 149.112.112.112  |
| OpenDNS     | 208.67.222.222    | 208.67.220.220   |
+-------------+-------------------+------------------+

* NO GOOGLE DNS (8.8.8.8) = More Privacy!

ROUTER CONFIGURATION

+------------------------------------------+
|         ROUTER DHCP SETTINGS             |
+------------------------------------------+
|                                          |
|  Primary DNS:   192.168.1.200            |
|                 (Pi-hole IP)             |
|                                          |
|  Secondary DNS: [leave blank]            |
|                 or 1.1.1.1               |
|                                          |
+------------------------------------------+

After saving, devices will get new DNS
when they renew DHCP lease.

FORCE UPDATE:
* Windows: ipconfig /flushdns
* Mobile:  Toggle WiFi off/on

TESTING

ACCESS PI-HOLE ADMIN

+----------------------------------+
|  http://192.168.1.200/admin      |
|                                  |
|  Login: (WEBPASSWORD you set)    |
+----------------------------------+

TEST AD BLOCKING

# This should return 0.0.0.0:
dig @192.168.1.200 doubleclick.net

# Visit this site - ads should be blocked:
https://ads-blocker.com/testing/

CHECK DASHBOARD

+------------------------------------------+
|  PI-HOLE DASHBOARD                       |
+------------------------------------------+
|                                          |
|  Total Queries:     [################]   |
|  Queries Blocked:   [########]           |
|  Percent Blocked:   45.2%                |
|                                          |
|  Top Blocked:                            |
|  - ads.facebook.com                      |
|  - googleads.g.doubleclick.net           |
|  - analytics.google.com                  |
|                                          |
+------------------------------------------+

TROUBLESHOOTING

Troubleshooting Flow

flowchart LR
    A[Issue] --> B{Running?}
    B -->|No| C[Check: NET_ADMIN,<br/>Port 53, Perms]
    B -->|Yes| D{Admin OK?}
    D -->|No| E[Use other device]
    D -->|Yes| F{Blocking?}
    F -->|No| G[Check router DNS]
    F -->|Yes| H[✅ Working]
    style H fill:#9f9,stroke:#333

CONTAINER WON’T START

CHECK LOGS:
docker logs pihole

COMMON FIXES:
+------------------------------------------+
| Problem          | Solution              |
+------------------------------------------+
| Missing          | Enable NET_ADMIN in   |
| NET_ADMIN        | Portainer Capabilities|
+------------------------------------------+
| Port 53          | Set DNSStubListener=no|
| conflict         | in resolved.conf      |
+------------------------------------------+
| Permission       | chown -R 999:999      |
| denied           | on config directories |
+------------------------------------------+

CAN’T REACH ADMIN PAGE

MACVLAN ISOLATION:
Host can't reach containers on macvlan
(this is normal!)

SOLUTIONS:
1. Access from another device on network
2. Create bridge interface (advanced)

RESET PASSWORD

docker exec -it pihole pihole -a -p
# Enter new password when prompted

QUICK REFERENCE CARD

+------------------------------------------+
|           PI-HOLE COMMANDS               |
+------------------------------------------+
| View logs        | docker logs pihole    |
| Restart          | docker restart pihole |
| Enter shell      | docker exec -it       |
|                  | pihole bash           |
| Update blocklists| docker exec pihole    |
|                  | pihole -g             |
| Reset password   | docker exec pihole    |
|                  | pihole -a -p          |
| Disable blocking | docker exec pihole    |
|                  | pihole disable        |
| Enable blocking  | docker exec pihole    |
|                  | pihole enable         |
+------------------------------------------+

+------------------------------------------+
|           ACCESS POINTS                  |
+------------------------------------------+
| Pi-hole Admin    | http://PIHOLE_IP/admin|
| Portainer        | http://OMV_IP:9000    |
| OMV Web UI       | http://OMV_IP         |
+------------------------------------------+

MAINTENANCE

UPDATE PI-HOLE

IN PORTAINER:
1. Go to Containers
2. Select "pihole"
3. Click "Recreate"
4. Check "Pull latest image"
5. Deploy

BACKUP

# Backup config
tar -czvf pihole-backup.tar.gz \
  /path/to/pihole-config/

# Built-in backup (includes lists)
docker exec pihole pihole -a -t

ADD BLOCKLISTS

Pi-hole Admin > Group Management > Adlists

RECOMMENDED:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts

Then: Tools > Update Gravity

WHAT YOU’VE ACHIEVED

[x] Pi-hole in Docker on OMV 7
[x] Portainer for easy management
[x] Own IP via macvlan (no conflicts)
[x] Privacy-focused DNS (no Google)
[x] Network-wide ad blocking
[x] All devices protected automatically

Set up your NAS first! See: OMV 7 Home NAS Zine


Made with care by Paarth | 2025 Print this zine & share it!