A tool to synchronize local DNS entries from a Git repository to a Pi-hole instance. It uses a dedicated Git repository as a source of truth for DNS mappings, allowing you to manage Pi-hole's local DNS records via git.
The tool supports both Pi-hole v5 (modifying custom.list) and Pi-hole v6+ (using the HTTP API) and is designed to be run as a cron job.
This project uses a two-repository system:
- The
dns-syncTool (This Repo): The Bash script that performs the synchronization, handles authentication, and updates Pi-hole. - Your DNS Mappings Repo: A separate Git repository (public or private, Github or Gitlab) that you create and maintain. This repository contains your actual DNS lists.
The tool is designed to support multiple "locations" or Pi-hole instances from a single DNS mappings repository.
- Your DNS Mappings Repo contains your lists (e.g.,
core.conf,servers.conf). - A
servers/directory in that repo defines which lists apply to which location using a YAML file. - For example, a file named
servers/london_server.ymlmight specify that the "london" location should loadcore.confandprinters.conf. - An optional
exceptions/directory can be used to block specific domains for a given location. - When
dns-syncruns, it:- Pulls the latest changes from your DNS Mappings Repo.
- Reads its
LOCATION_CONFIGvariable (e.g.,london). - Parses
servers/london_server.ymlto find which lists to load. - Builds the final list of DNS entries.
- Applies any exceptions from
exceptions/london_exceptions.conf. - Pushes the final, correct list of entries to Pi-hole.
The project was written in bash so that it can run on a wide variery of systems e.g DietPi
Your DNS mappings repository should follow this structure:
.
├── lists/
│ ├── core.conf
│ ├── printers.conf
│ └── servers.conf
│
├── servers/
│ ├── london_server.yml
│ └── home_server.yml
│
└── exceptions/
├── london_exceptions.conf
└── home_exceptions.conf
servers/london_server.yml:
dns_lists:
- core
- servers
- printerslists/core.conf:
# Comments are allowed
192.168.1.1 router.local
10.0.0.1 nas.local
exceptions/london_exceptions.conf:
# This domain will be skipped, even if it's in a list
nas.local
- Git-based Source of Truth: Manage your DNS records using version control.
- Location-Aware: Use one mappings repo to manage multiple, distinct Pi-hole instances.
- Pi-hole v5 and v6 Support: Works with legacy
custom.list(v5) and the modern HTTP API (v6). - Safe and Idempotent: Only applies changes when detected. Uses a lockfile to prevent concurrent runs.
- Resilient: Caches the DNS list repository locally, so a temporary Git outage does not prevent the tool from running.
- Automated: Designed to be run from
cronfor both list syncing and self-updating.
- A Linux host (tested on Debian-based systems).
rootprivileges (for installation, cron setup, and writing to Pi-hole's config).git,curl,jq,cron,logrotate.yq(v4+) - The installer will attempt to download this binary to/opt/dns-sync/yqif it is not found.
-
Clone the Tool Clone this
dns-syncrepository to your Pi-hole machine.git clone https://github.com/your-user/dns-sync.git cd dns-sync -
Create and Edit Configuration Copy the example config and edit it with your specific values.
cp dns-sync.conf.example dns-sync.conf chmod 600 dns-sync.conf nano dns-sync.conf
You must update
DNS_REPO_URLand all placeholder authentication and Pi-hole variables. -
Run the Installer Run the installer from within the cloned directory:
sudo ./dns-sync.sh --install
This script will:
- Install dependencies (on Debian-based systems).
- Copy the
dns-syncscript to/usr/local/bin/. - Copy
dns-sync.confto/etc/dns-sync/. - Create the local repo cache at
/opt/dns-sync/lists. - Install
yqto/opt/dns-sync/yqif needed. - Set up the
cronjobs for syncing and self-updating.
All configuration is handled in /etc/dns-sync/dns-sync.conf (after installation).
| Variable | Description |
|---|---|
| Core | |
LOCATION_CONFIG |
The location profile to apply. ldn expects servers/ldn_server.yml in the DNS repo. |
LOG_FILE |
Path to the log file (e.g., /var/log/dns-sync.log). |
BIN_PATH |
Path to install the tool (e.g., /usr/local/bin). |
| Repositories | |
TOOL_REPO_URL |
URL to this tool's repo, used for self-updating. |
TOOL_TOKEN_NAME |
(Optional) Access token name for a private tool repo. |
TOOL_ACCESS_TOKEN |
(Optional) Access token secret for a private tool repo. |
DNS_REPO_URL |
Required. URL to your separate DNS mappings repo. |
DNS_TOKEN_NAME |
(Optional) Access token name for a private DNS repo. |
DNS_ACCESS_TOKEN |
(Optional) Access token secret for a private DNS repo. |
| Pi-hole | |
PIHOLE_VERSION |
Set to "5" or "6". |
PIHOLE_CUSTOM_LIST |
(v5 only) Path to Pi-hole's list (e.g., /etc/pihole/custom.list). |
PIHOLE_API_URL |
(v6 only) Base URL for the API (e.g., http://127.0.0.1/api). |
PIHOLE_API_TOKEN |
(v6 only) The password for your Pi-hole admin interface. |
PIHOLE_INSECURE |
(v6 only) Set to true to allow curl -k for self-signed certificates. |
| Automation | |
CUSTOM_CRON |
The cron schedule for running the DNS sync (e.g., */2 * * * *). |
CUSTOM_UPDATE_CRON |
The cron schedule for self-updating the tool (e.g., 0 0 * * *). |
The tool supports three methods for accessing your Git repositories:
- Public HTTPS: Use an
https://URL and leave the_TOKEN_variables blank. - Private HTTPS: Use an
https://URL and provide both_TOKEN_NAMEand_ACCESS_TOKEN. - SSH: Use an
git@...URL and leave the_TOKEN_variables blank. Ensure therootuser on the host has a valid SSH key with access to the repo.
Once installed, the tool is run by cron. You can also run it manually at any time.
Run a standard sync:
sudo dns-syncCheck for tool updates:
sudo dns-sync --update-toolValidate your configuration:
sudo dns-sync --validate-h, --help: Display the help message.-i, --install: Run the installation or re-installation.-up, --update-tool: Check for and apply updates to the tool itself.-ul, --update-lists: Force an update of the local DNS lists repo cache.--validate: Check config, repo, and API access without making changes.--dry-run: Run the full sync process but do not apply changes to Pi-hole.-c, --config-file <path>: Use a specific config file for this run.-l, --location <name>: Override theLOCATION_CONFIGfor this run.-ls, --list: List all DNS entries for all locations.--debug-level=<n>: Set verbosity (1=debug, 2=full curl/git trace).-v, --version: Display the tool's version.
- Conflict Resolution: If multiple DNS lists for a single location contain the same hostname, the last one processed (which is determined by the order in the YAML file) will be used.
- Cron Schedule: Be mindful of Git provider rate limits. Syncing more than once a minute is not recommended.
- Pi-hole v6 Token: The
PIHOLE_API_TOKENis your Pi-hole web interface password.
To remove the tool from your system:
-
Remove Cron Jobs:
sudo crontab -l | grep -v '/usr/local/bin/dns-sync' | sudo crontab -
-
Remove Files:
sudo rm -f /usr/local/bin/dns-sync sudo rm -rf /etc/dns-sync sudo rm -rf /opt/dns-sync sudo rm -f /var/log/dns-sync.log sudo rm -f /var/lock/dns-sync.lock sudo rm -f /etc/logrotate.d/dns-sync