2026-07-16 11:04:38 +02:00
2026-07-16 11:04:38 +02:00
2026-07-16 11:04:38 +02:00
2026-07-16 11:04:38 +02:00

Pihole Scripts

A collection of helper scripts for Pi-hole v6 that use the new Pi-hole API (/api/...) to automate common DHCP/DNS maintenance tasks. Both scripts authenticate against a local Pi-hole instance and require read (and, for the sync script, write) access to the Pi-hole configuration.

Requirements

  • Pi-hole v6 (uses the FTL REST API, not the legacy PHP admin API)
  • Python 3
  • requests (pip install requests)
  • A Pi-hole API password stored in a plain-text file (see "Password file" below)
  • The Pi-hole TLS CA certificate available locally if your instance uses HTTPS with a self-signed/internal CA (scripts default to /etc/pihole/tls_ca.crt for certificate verification)

Password file

Both scripts read the Pi-hole API password from a file instead of accepting it as a command-line argument or hardcoding it, to avoid leaking the password in shell history or process listings.

echo "your-api-password" > /etc/pihole/api_password
chmod 600 /etc/pihole/api_password

The default path is /etc/pihole/api_password and can be overridden per script with -p/--password-file.

Scripts

dhcp-leases.py

Lists currently active non-static (dynamic) DHCP leases, i.e. leases handed out by Pi-hole's DHCP server that do not correspond to a configured static host mapping.

The script authenticates, reads the configured static DHCP host mappings to determine which MAC addresses are static, then fetches the current lease table and filters out any lease whose MAC address matches a static mapping.

Output formats:

  • Default: CSV (ip,mac,hostname,expires), machine-readable, raw unix timestamp for lease expiry.
  • -j / --json: same data as a JSON array.
  • -t / --table: aligned, human-readable table with lease expiry converted to local time.

Options:

  • -p, --password-file PATH - path to the API password file (default: /etc/pihole/api_password)
  • -t, --table - human-readable table output
  • -j, --json - JSON output

-t and -j are mutually exclusive; without either, output is CSV.

dhcp-dns-sync.py

Synchronizes Pi-hole's static DHCP host mappings (MAC/IP/hostname entries configured under DHCP) into Pi-hole's local DNS host records, so that statically-assigned DHCP clients automatically get a matching DNS entry.

Beyond a simple one-way copy, the script handles three additional cases:

  • IP address changes: if a hostname already exists in DNS but with a different IP than its current DHCP mapping, the old DNS entry is deleted and replaced with the updated one, rather than leaving both a stale and a new entry.
  • Removed DHCP entries: if a static DHCP host mapping is deleted, its corresponding DNS entry is removed as well, keeping DNS from accumulating stale records.
  • Keep-list: DNS entries that should always be preserved regardless of DHCP state (e.g. manually-managed hosts not tied to a static DHCP lease) can be listed in a keep file, referenced by their full ip hostname entry. Entries in the keep file are never removed, even if not present in DHCP.

Keep file format (default path /etc/pihole/dns_hosts_keep), one full DNS entry per line, # for comments:

# entries to always keep in DNS regardless of DHCP state
192.168.1.10 nas.local
192.168.1.11 printer.local

All resulting DNS changes (additions, IP changes, removals) and unchanged/kept entries are computed first, sorted by IP address, and then applied and reported in that order.

Output formats:

  • Default: CSV (ip,hostname,status,old_ip), one row per DHCP/DNS entry considered. status is one of unchanged, new, ip changed, removed, or kept. old_ip is populated only for ip changed rows.
  • -j / --json: same data as a JSON array.
  • -t / --table: aligned, human-readable table with the same columns.

By default, output includes every entry considered (verbose behavior). Use -s/--terse to restrict output to rows that represent an actual change (new, ip changed, removed), omitting unchanged and kept rows.

Detailed processing information (raw API responses, per-entry comparison decisions, HTTP call results for PUT/DELETE/restart operations) is written to stderr and only shown with -d/--debug, keeping stdout clean and parseable in default operation.

Options:

  • -p, --password-file PATH - path to the API password file (default: /etc/pihole/api_password)
  • -k, --keep-file PATH - path to the keep-list file (default: /etc/pihole/dns_hosts_keep)
  • -n, --dry-run - compute and display changes without making any modifying API calls (no PUT/DELETE/DNS restart)
  • -s, --terse - only output changed rows, omitting unchanged/kept rows
  • -d, --debug - print detailed processing steps and raw API call results to stderr
  • -t, --table - human-readable table output
  • -j, --json - JSON output

-t and -j are mutually exclusive; without either, output is CSV.

Notes

  • Both scripts log out of the Pi-hole API session (DELETE /auth) on exit, including when an error occurs partway through, so sessions are not left open.
  • Neither script currently supports IPv6 DHCP/DNS entries; both are written and tested against IPv4 static leases and host mappings.
  • These scripts modify live DNS/DHCP configuration (with the exception of dhcp-leases.py, which is read-only). Use -n/--dry-run on dhcp-dns-sync.py before running it unattended in a new environment.
S
Description
A collection of helper scripts for Pi-hole v6
Readme 34 KiB
Languages
Python 100%