How to Install Pi-hole on Ubuntu 24.04

How to Install Pi-hole on Ubuntu 24.04 (Network-Wide Ad Blocking Without a Pi)

Most Pi-hole guides assume you are running a Raspberry Pi. That is where the name comes from, and it is a perfectly good deployment target. But plenty of people have an Ubuntu server already running in their homelab, or a spare mini PC, or a VPS they want to use. You do not need a Raspberry Pi to run Pi-hole, and honestly, an Ubuntu 24.04 LTS server gives you a more powerful and flexible platform for it.

From the homelab: If you want to understand DNS properly, run Pi-hole on bare metal. You will learn about upstream resolvers, local DNS records, conditional forwarding, and DHCP — all the fundamentals that get abstracted away in cloud environments.

This guide covers the native installation method using Pi-hole’s official installer on Ubuntu 24.04. Not Docker, not a snap, not some third-party package. The curl-pipe-bash installer that the Pi-hole project maintains. If you would rather run it in Docker, I have a separate guide for that: Pi-hole in Docker. Both approaches work. The native install is simpler if Pi-hole is the only thing running on the machine. Docker is better if you are running multiple services and want clean isolation.

Why Ubuntu specifically? Because it is the most common Linux server distribution by a wide margin. Ubuntu 24.04 LTS has support until 2029, it is what most hosting providers offer as a default image, and if you are learning Linux for your career, Ubuntu is where you will spend most of your time. The principles here apply to Debian too, but the systemd-resolved issue we need to fix first is specifically an Ubuntu thing.

Career Value: DNS filtering is a core function in enterprise security stacks. Products like Cisco Umbrella, Zscaler, and Infoblox all operate on the same principle as Pi-hole: intercept DNS queries and block the ones that match known-bad categories. Understanding how DNS sinkholes work, how to troubleshoot resolution failures, and how to manage blocklists translates directly to Network Security and Infrastructure Engineer roles. Running it on Ubuntu adds Linux administration skills to the mix.

Prerequisites

You will need:

  • Ubuntu 24.04 LTS server with a static IP address (or DHCP reservation on your router)
  • SSH access to the server (or direct console access)
  • sudo privileges on the account you are using
  • Access to your router’s admin panel for DNS configuration changes later

Static IP is non-negotiable. Pi-hole will become the DNS server for your entire network. If its IP address changes because DHCP gave it a different lease, every device on your network will lose internet access. Set a static IP on the server itself or create a DHCP reservation on your router before you start. Do this now, not later.

Fix the systemd-resolved Port 53 Conflict

This is the step that catches everyone. Ubuntu 24.04 runs a local DNS stub resolver called systemd-resolved by default. It listens on port 53, which is the standard DNS port. Pi-hole also needs port 53. Two services cannot bind to the same port, and the Pi-hole installer will either fail or produce a broken installation if you skip this step.

I have seen people waste hours debugging this. It is documented in the Pi-hole FAQ, it is mentioned in every Pi-hole subreddit thread about Ubuntu, and people still miss it. Do not be one of them.

Step 1: Confirm the conflict exists

sudo ss -lntp | grep ':53 '

If you see systemd-resolve in the output, port 53 is occupied and you need to free it.

Step 2: Disable the DNS stub listener

sudo nano /etc/systemd/resolved.conf

Find the [Resolve] section and set these values:

[Resolve]
DNSStubListener=no
DNS=1.1.1.1
FallbackDNS=8.8.8.8

Step 3: Fix the resolv.conf symlink

This is the step people forget. Even after disabling the stub listener, Ubuntu still points /etc/resolv.conf at the old stub address (127.0.0.53). You need to update the symlink:

sudo rm /etc/resolv.conf
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

Step 4: Restart the service and verify

sudo systemctl restart systemd-resolved
sudo ss -lntp | grep ':53 '

The second command should return nothing. Port 53 is now free for Pi-hole.

Why not just disable systemd-resolved entirely? You could run sudo systemctl disable systemd-resolved, and some guides suggest exactly that. The problem is that your server then has no DNS resolution at all until Pi-hole is running. If Pi-hole fails to start, you cannot even apt install anything to fix it because apt needs DNS. The approach above disables only the stub listener while keeping the service running as a fallback. It is the safer path.

Install Pi-hole

With port 53 clear, the installation itself is straightforward. Pi-hole provides a single-command installer:

curl -sSL https://install.pi-hole.net | bash

Yes, piping curl to bash makes security people uncomfortable. If you want to review the script first:

curl -sSL https://install.pi-hole.net -o pihole-install.sh
less pihole-install.sh
sudo bash pihole-install.sh

The installer walks you through several choices. Here is what to select:

  • Upstream DNS provider: Cloudflare (1.1.1.1) or Google (8.8.8.8) are fine starting points. You can change this later. If you care about DNS privacy, Cloudflare is the better choice as they have committed to not selling query data. Google has not made the same commitment.
  • Blocklists: Accept the default Steven Black list. You will add more later.
  • Admin web interface: Yes. You want this.
  • Web server (lighttpd): Yes, unless you already have a web server running on port 80. If you are running Nginx or Apache, say no here and configure a reverse proxy manually.
  • Query logging: Yes. The logs are what make Pi-hole educational, not just functional.
  • Privacy mode: Show everything, at least initially. You can lock this down later once you understand what your network is doing.

At the end of the installation, the script displays your admin password. Write this down or change it immediately:

pihole -a -p

This prompts you to set a new web interface password.

Configure Upstream DNS

Pi-hole is not a recursive DNS resolver by default. It forwards queries to an upstream provider. The installer asked you to pick one, but you can change or add more via the web interface at Settings > DNS.

My recommendations:

  • Primary: Cloudflare (1.1.1.1) — fast, privacy-focused, WARP-compatible
  • Secondary: Quad9 (9.9.9.9) — blocks known malicious domains at the resolver level, good second layer

Avoid using your ISP’s DNS servers. They are typically slower, they log everything, and some ISPs inject ads or redirect failed lookups to search pages. The entire point of running Pi-hole is to control your DNS. Sending queries to your ISP undermines that.

Want full control? You can pair Pi-hole with Unbound, a recursive DNS resolver that queries root nameservers directly instead of forwarding to any third party. This eliminates the upstream provider entirely. It is a more advanced setup and adds some latency to initial lookups, but it means your DNS queries go nowhere except the authoritative nameservers for each domain. I will cover Unbound in a separate guide.

Point Your Network at Pi-hole

Pi-hole is running, but right now only the server itself is using it. You need every device on your network to send DNS queries to Pi-hole. There are three ways to do this, in order of preference.

Option 1: Change DNS in your router’s DHCP settings (best)

Log into your router’s admin panel and find the DHCP settings. Set the DNS server that gets handed to devices via DHCP to your Pi-hole server’s IP address. This way, every device that connects to your network automatically uses Pi-hole without any per-device configuration.

The advantage of DHCP-level DNS assignment is that Pi-hole sees each device’s individual queries. If you change the router’s own DNS settings instead (Option 2), all queries appear to come from the router’s IP, and you lose per-device visibility in the logs.

Option 2: Change the router’s DNS servers

If your router does not expose DHCP DNS settings separately (many consumer routers hide this), change the router’s own DNS servers to your Pi-hole IP. This works but means Pi-hole sees all queries coming from the router rather than from individual devices.

Option 3: Per-device manual configuration

If you have a locked-down ISP router that will not let you change DNS settings at all (looking at you, BT Home Hub and Sky Q), you can manually set DNS on each device. This is tedious but it works.

The secondary DNS trap. If you set a public DNS server (like 1.1.1.1) as your secondary DNS alongside Pi-hole as primary, some devices will use the secondary instead, bypassing Pi-hole entirely. Android is particularly guilty of this. If you want consistent filtering, set both primary and secondary DNS to your Pi-hole IP. The trade-off is that if Pi-hole goes down, DNS stops working. In practice, Pi-hole on Ubuntu LTS is very stable, but it is a decision you should make deliberately.

After changing your DNS settings, renew DHCP leases on your devices. The quickest way is to disconnect and reconnect to Wi-Fi, or restart the device. Within a few minutes, queries should start appearing in the Pi-hole dashboard.

The Gravity Database and Blocklist Management

Pi-hole’s blocklist database is called Gravity. When you add a blocklist URL, Pi-hole downloads the list and imports the domains into the Gravity database. This is a local SQLite database, not a text file, which is why Pi-hole can handle millions of blocked domains without performance degradation.

To add blocklists, go to Adlists in the web interface. Here are the lists I run:

  • Steven Black Unified Hosts: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts — the default, well-maintained, covers the basics
  • OISD Full: https://big.oisd.nl/ — aggressive but well-curated, catches a lot of telemetry
  • Hagezi Pro: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.txt — excellent balance of coverage and false positive avoidance

After adding lists, update Gravity to pull them in:

pihole -g

Or use the web interface: Tools > Update Gravity. Gravity updates automatically on a weekly cron schedule, but always run it manually after adding new lists.

More blocklists does not mean better blocking. Aggressive lists break things. Banking sites, CAPTCHAs, app login flows, and streaming services can all stop working if you over-block. Start with the defaults plus one additional list. Live with it for a week. If nothing breaks, add another. If your partner’s banking app stops working at 9pm on a Sunday, you will regret going straight to the nuclear option.

Group Management for Family Members

Pi-hole 5 and later supports group management, which is genuinely useful if you share a network with other people. The concept is simple: you can assign devices to groups, and each group can have different blocklists and whitelist rules.

Why this matters: your filtering needs are probably different from your children’s. You might want aggressive blocking on the kids’ devices but more relaxed rules on your own machine where you need access to ad-supported tools for work.

To set this up:

  1. Go to Group Management > Groups and create groups (e.g., “Adults”, “Kids”, “IoT Devices”)
  2. Go to Group Management > Clients and assign devices to groups by their IP or MAC address
  3. Go to Group Management > Adlists and assign blocklists to specific groups
  4. Go to Group Management > Domains and assign whitelist entries to specific groups

A practical example: I have an “IoT” group with the most aggressive blocklists applied. Smart TVs, smart speakers, and home automation devices do not need access to advertising or analytics networks. They get blocked hard. My personal machines are in a group with more permissive rules because I occasionally need to access sites that aggressive lists would break.

Whitelisting False Positives

Things will break. It is not a question of if. Someone in your household will try to do something and it will not work, and the cause will be Pi-hole blocking a domain that the service depends on.

The diagnostic process:

  1. Open the Pi-hole query log (Query Log in the web interface)
  2. Filter by the device having problems
  3. Look for blocked entries (shown in red) that correspond to the service that is broken
  4. Click the blocked domain and add it to the whitelist

Common domains you will likely need to whitelist:

  • s.youtube.com — YouTube history and watch later
  • clients4.google.com — Android connectivity checks
  • captive.apple.com — Apple Wi-Fi portal detection
  • outlook.office365.com — Microsoft 365 email
  • Your bank’s CDN and authentication domains (these vary)

The community maintains a whitelist of common false positives at https://github.com/anudeepND/whitelist. Review it, but do not blindly import the whole thing. Some entries will re-enable tracking you specifically wanted blocked.

Keeping Pi-hole Updated

Native Pi-hole installations update through the built-in updater:

pihole -up

This updates Pi-hole core, the web interface, and FTL (the DNS engine). Run it periodically. Pi-hole does not auto-update, and running old versions means missing security patches and new features.

For the underlying Ubuntu system:

sudo apt update && sudo apt upgrade -y

If a kernel update requires a reboot, Pi-hole will come back automatically since it installs as a systemd service. Your network will lose DNS for the thirty seconds or so that the server is rebooting, which most devices handle gracefully by retrying.

Check the release notes before major version upgrades. Pi-hole version transitions (like v5 to v6) can involve database migrations and configuration changes. The Pi-hole team is good about documenting these, but running pihole -up blindly on a major version bump is asking for trouble. Spend two minutes reading the release notes. It could save you two hours of troubleshooting.

Verifying Pi-hole Is Working

After setup, run these checks:

# Test DNS resolution through Pi-hole
dig @localhost google.com

# Test that blocking is working
dig @localhost ads.google.com
# Should return 0.0.0.0 or NXDOMAIN

# Check Pi-hole status
pihole status

# View recent stats
pihole -c

Then open the web interface at http://YOUR-SERVER-IP/admin and watch the query log for a few minutes. You should see queries from your devices appearing and a percentage of them being blocked.

If the dashboard shows zero queries, your devices are not using Pi-hole as their DNS server. Go back to the router configuration section and double-check your settings.

Watch out: After installation, make sure you change your router’s DHCP settings to hand out the Pi-hole’s IP as the DNS server. Without this step, only devices you have manually configured will use Pi-hole.

Key Takeaways

  • Fix systemd-resolved first. The port 53 conflict is the number one cause of Pi-hole installation failures on Ubuntu. Disable the stub listener and update the resolv.conf symlink before running the installer.
  • Start with minimal blocklists. The defaults plus one additional list is enough. Add more after a week of living with it. Over-blocking creates more problems than it solves.
  • Use group management. Different devices and users have different needs. IoT devices get aggressive blocking. Personal machines get more permissive rules.
  • Set both DNS entries to Pi-hole. A public secondary DNS lets devices bypass your filtering. Decide whether total coverage or fallback resilience matters more to you.
  • Keep a paper note of recovery steps. When DNS is down, you cannot search for how to fix DNS. Write your server’s IP and the basic commands somewhere physical.

Related Guides

Related Guides

If you found this useful, these guides continue the journey:

The RTM Essential Stack - Gear I Actually Use

Enjoyed this guide?

New articles on Linux, homelab, cloud, and automation every 2 days. No spam, unsubscribe anytime.

Scroll to Top