Pi-hole alongside Unbound on Raspberry Pi

To deploy Pi-hole alongside Unbound as a recursive DNS resolver on your Raspberry Pi, you need to install Pi-hole, configure Unbound to listen on a custom port, and link the two together. This guide assumes you have already flashed Raspberry Pi OS Lite and successfully connected to your Pi via SSH.


1. Update the OS & Install Unbound

Ensure all system packages are fully updated. Install the Unbound package via your system package manager.

sudo apt update && sudo apt upgrade -y && sudo apt install unbound dns-root-data -y

2. Install Pi-hole

Run the automated installation script provided by Pi-hole [1].

curl -sSL https://install.pi-hole.net | bash
  • Step-by-step choices: Follow the on-screen installer prompts.
  • IP Address: Acknowledge the static IP warning.
  • Upstream DNS: Temporarily select a temporary public provider like Google or Cloudflare [2] (we will change this to Unbound shortly).
  • Completion: At the end of the installation, note down the Admin Web Interface Password displayed on your terminal screen.

3. Configure Unbound

Create a custom configuration file dedicated to your Pi-hole integration.

sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf

Paste the official configuration optimized by Pi-hole [3] into the file:

server:
    verbosity: 1
    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    # May be set to yes if you have IPv6 capability
    do-ip6: no
    do-udp: yes
    do-tcp: yes
    ratelimit: 1000
    hide-identity: yes
    hide-version: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: no

    # Use this only when you downloaded the list of primary root servers!
    # If for some reason root.hints cannot be fetched defaults to built-in.
    root-hints: "/var/lib/unbound/root.hints"

    # Trust anchor file, used for DNSSEC
    # auto-trust-anchor-file: "/var/lib/unbound/root.key"

    # Buffer size management
    so-rcvbuf: 4m
    edns-buffer-size: 1232
    prefetch: yes
    num-threads: 1

    # Ensure privacy of local networks
    private-address: 192.168.0.0/16
    private-address: 169.254.0.0/16
    private-address: 172.16.0.0/12
    private-address: 10.0.0.0/8

Press CTRL+O, then Enter to save, and CTRL+X to exit the nano editor.

4. Download Root Hints (optional)

Download the list of primary root servers so Unbound can perform true recursive lookups independently. if not already been done in step 1.

sudo wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root

5. Adjust Package Conflicts (Debian/Ubuntu specific)

Recent versions of Debian/Raspberry Pi OS include a package called resolvconf that can disrupt Unbound’s startup binding. Disable this conflicting service element:

sudo systemctl disable --now unbound-resolvconf.service

6. Restart and Verify Unbound

Restart the Unbound service to initialize your custom configuration.

sudo systemctl restart unbound && systemctl status unbound

Test if Unbound successfully resolves queries locally on its assigned port (5335):

dig @127.0.0.1 -p 5335 unblog.ch

If you see a status: NOERROR message along with an actual IP address in the response output, Unbound is working correctly.

7. Link Pi-hole to Unbound

  1. Open your web browser and go to your Pi-hole web panel dashboard: http://YOUR_PI_IP/admin.
  2. Log in using the password generated in Step 2.
  3. Navigate to Settings in the left sidebar menu, and select the DNS tab at the top.
  4. Under the Upstream DNS Servers columns, uncheck every active public provider.
  5. On the right side under Custom 1 (IPv4), type:
    127.0.0.1#5335
  6. Scroll down to the bottom of the page and click Save.

Hint If a Pi-hole has been running for some time, an update can be performed.

sudo pihole -up

Hide the Unbound warning about the missing option.

sudo echo "DAEMON_OPTS=" > /etc/default/unbound

✅ Deployment Complete

Your self-contained local network privacy shield is now ready. To begin filtering your entire environment, log into your home internet router’s admin settings page and change your local network’s DHCP Primary DNS Server IP directly to the static IP address belonging to your Raspberry Pi running Pi-hole.


Link Sources

Backup helper script for Synology NAS

A simple backup helper script for Synology NAS that copies a Hyper Backup file or folder from a fixed source path to an external USB-mounted destination, then sends an email notification about the result.

copy2usb.sh

Backup helper script for Synology NAS

What it does

  • Verifies the source backup path exists before attempting to copy.
  • Verifies the destination USB mount path exists and is reachable.
  • Copies the source to the destination using cp -rf.
  • Checks whether the destination copy exists after a successful cp.
  • Sends an email notification for success, warning, or failure.

Script functions

send_mail()

This helper function builds a simple email message with headers and body text, then pipes it into /bin/ssmtp.

  • From: configured by MAIL_FROM
  • To: configured by MAIL_TO
  • Subject: set according to success or failure state
  • Date: uses the current date in RFC 2822 format

Configuration

Edit the top of copy2usb.sh to match your environment:

  • SRC – source file or directory to copy
  • DST – destination directory mounted from the USB drive
  • SMTP – SMTP server address used by ssmtp (in this script the variable is defined but not directly used by send_mail)
  • MAIL_TO – destination email address for notifications
  • MAIL_FROM – sender email address used in the notification header

Example: configurtion for sSMTP server using the backup script on Synology NAS:

vi /etc/ssmtp/ssmtp.conf

Minimum content for the SMTP gateway without authentication:

SRC="/volume1/data/DS918_1.hbk"
DST="/volumeUSB1/usbshare/"
SMTP="203.0.113.104"
MAIL_TO="hostmaster@example.com"
MAIL_FROM="nas@ds918.local"

Usage

  1. Testing the sSMTP configuration with email sending can be done with this command.
echo -e "From: nas@ds918.local\nTo: hostmaster@example.com\nSubject: Test\n\nTest von DS918" | /bin/ssmtp hostmaster@example.com
  1. Make sure the script is executable:
chmod +x copy2usb.sh
  1. Run the script manually:
./copy2usb.sh
  1. Optionally schedule it with cron or Synology Task Scheduler to run regularly.

A task is created in the DSM Task Scheduler, Go to Control Panel > Task Scheduler.

Expected behavior

  • If the source path does not exist, the script exits with code 1 and sends a failure email.
  • If the destination USB mount is not reachable, it exits with code 2 and sends a failure email.
  • If the copy command returns success but the copied destination is not verifiable, it sends a warning email.
  • If the copy succeeds and the destination file or folder exists, it sends a success email.

Requirements

  • bash
  • cp
  • ssmtp configured and available at /bin/ssmtp

Notes

  • The script currently uses cp -rf, which overwrites existing files and copies recursively.
  • The SMTP variable is defined for configuration consistency, but send_mail() relies on the /bin/ssmtp command and does not directly use the variable in this version.