Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/damianiglesias/pihole-ubuntu-deploy/llms.txt

Use this file to discover all available pages before exploring further.

This method installs Pi-hole v6 natively on the operating system — no containers, no virtualization layer. It is best suited for dedicated hardware such as a Raspberry Pi or a bare-metal Ubuntu server where you want Pi-hole to own the network stack directly. The script is deploy.sh version 4.1, authored by Damian Iglesias, and automates every step from dependency installation through static IP assignment.
systemd-resolved is permanently stopped and disabled by this script. Pi-hole’s FTL daemon takes over port 53 for all DNS resolution. If you later remove Pi-hole you will need to re-enable systemd-resolved manually.

Installation Steps

1

Clone the repository

Download the project and enter the directory:
git clone https://github.com/damianiglesias/pihole-ubuntu-deploy && cd pihole-ubuntu-deploy
2

Run the deployment script

The script must be executed as root. If the effective user ID is not 0 it prints an error and exits immediately.
sudo ./deploy.sh
3

Network preparation (automatic)

Before touching anything else, the script prepares the host network so Pi-hole can bind to port 53:
  1. Stops and disables systemd-resolved
  2. Removes /etc/resolv.conf
  3. Writes new nameservers:
    nameserver 8.8.8.8
    nameserver 1.1.1.1
    
  4. Pings 8.8.8.8 to verify internet connectivity — exits with a fatal error if the ping fails
4

Dependency installation (automatic)

Runs apt-get update then installs all required packages in one shot:
apt-get install curl net-tools ufw sqlite3 wget python3 python3-venv python3-pip git -y
5

Pi-hole core installation

Pulls and runs the official Pi-hole installer:
curl -sSL https://install.pi-hole.net | bash
Follow the blue interactive screens that appear. Accept all defaults unless you have a specific reason to change them. The script verifies the pihole command is available after installation and exits with an error if it is not found.
6

Advanced blocklists (optional)

After the core install you are prompted:
Install Advanced Lists? [y/n]:
If you answer y, the script injects three curated blocklist URLs directly into Pi-hole’s SQLite database at /etc/pihole/gravity.db using sqlite3, then triggers a gravity update:
pihole -g
See the Blocklist URLs section below for the exact addresses added.
7

Web admin password setup

You are prompted to type and confirm a password for the Pi-hole web interface. The loop repeats until both entries match and the password is non-empty:
> Password:
> Confirm:
The password is applied with:
pihole setpassword "<your-password>"
systemctl restart pihole-FTL
8

Optional add-ons

Each add-on is independently prompted with [y/n]. You can install any combination:
PromptComponentNotes
Install Unbound?Recursive DNS resolverListens on 127.0.0.1:5335; see Unbound
Install PADD dashboard?Terminal stats displayOptional SSH auto-start via .bashrc; see PADD Dashboard
Install DNS Manager tool?Python DNS ManagerCloned to /opt/pihole-dns-manager; see DNS Manager
Install Log2Ram?RAM-based log bufferReduces disk wear — recommended for SD cards and VMs; see Log2Ram
Unbound integration is currently experimental and not fully functional. The installer includes the Unbound setup steps but the recursive DNS resolver may not work correctly after installation. Post-install manual configuration is required — see Unbound for details.
9

Firewall configuration (automatic)

UFW rules are applied automatically after the add-ons:
ufw allow 22/tcp
ufw allow 53
ufw allow 80/tcp
ufw enable
10

Static IP assignment

The script lists all non-loopback network interfaces using:
ip -o link show
You select the interface you want to pin (e.g. enp0s8). The script detects the current IP and default gateway, then asks:
Set this IP as STATIC? [y/n]:
If confirmed, it backs up existing Netplan configs and writes a new one. See Generated Netplan Config below.

Blocklist URLs

When you opt in to advanced blocklists, the following three sources are inserted into gravity.db:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts    # StevenBlack Unified
https://v.firebog.net/hosts/AdguardDNS.txt                          # Adguard Mobile
https://v.firebog.net/hosts/Easyprivacy.txt                         # EasyPrivacy Tracking

Generated Netplan Config

The static IP step writes /etc/netplan/99-pihole-static.yaml with the following structure, using the detected interface name, current IP address, and current default gateway:
network:
  version: 2
  renderer: networkd
  ethernets:
    <interface>:
      dhcp4: false
      addresses: [<current_ip>/24]
      routes: [{to: default, via: <gateway>}]
      nameservers: {addresses: [8.8.8.8, 127.0.0.1]}
netplan apply is run immediately after writing the file. The file permissions are set to 600.
Before writing the new config, deploy.sh copies all existing *.yaml files in /etc/netplan/ to /etc/netplan/backup/. If the static IP configuration breaks your connectivity, you can restore the originals from that backup directory.

Final Deployment Report

When all steps complete, the terminal is cleared and a summary banner is printed:
################################################
#             DEPLOYMENT SUCCESSFUL!           #
################################################

 Server IP:      <your-server-ip>
 Web Interface:  http://<your-server-ip>/admin

 PASSWORD:       <your-password>

 UNBOUND INSTRUCTIONS:         # only shown if Unbound was installed
   1. Login to Web Interface -> Settings -> DNS
   2. Uncheck 'Google' & Check 'Custom 1': 127.0.0.1#5335

 PADD: Type padd to view dashboard.   # only shown if PADD was installed

Optional Component Docs

Unbound

Recursive DNS resolver running on port 5335. Eliminates reliance on upstream DNS providers.

PADD Dashboard

Terminal-based Pi-hole stats display. Can auto-launch on SSH login.

Python DNS Manager

CLI tool for syncing local DNS entries to Pi-hole via the API.

Log2Ram

Mounts the log directory in RAM to reduce SD card and SSD wear.

Build docs developers (and LLMs) love