Automatically discovers services exposed by Traefik and creates corresponding DNS records in Pi-hole.
- 🔄 Automatically syncs Traefik-exposed services to Pi-hole DNS
- ⏰ Runs on a configurable schedule (default: every 5 minutes)
- 🔍 Dry-run mode to preview changes
- 🐳 Runs as a Docker container
- 📝 Comprehensive logging
- Queries the Traefik API to discover all HTTP routers
- Extracts hostnames from router rules (e.g.,
Host(\example.com`)`) - Connects to Pi-hole and checks existing DNS records
- Adds missing DNS records pointing to your Traefik host IP
Enable API write access in Pi-hole:
- Log in to your Pi-hole web interface
- Navigate to Settings > API / Web interface
- Find the setting
webserver.api.app_sudo - Enable it: "Should application password API sessions be allowed to modify config settings?"
- Click Save
Important
This setting is required for the sync tool to add DNS records. Without it, API sessions will be read-only.
You can retrieve your App Password from the Pi-hole web interface:
- Log in to your Pi-hole web interface.
- Navigate to Settings > API / Web interface.
- Retrieve your App Password (or API Token) from this page.
cp .env.example .envEdit .env and configure:
# Traefik API URL (internal Docker network)
TRAEFIK_API_URL=http://traefik:8080/api/http/routers
# Pi-hole URL (accessible from Docker container)
PIHOLE_URL=https://pihole.example.com
# Pi-hole web admin password
PIHOLE_PASSWORD=your-pihole-password
# IP address that DNS records should point to (your Traefik host)
TRAEFIK_HOST_IP=192.168.1.100
# How often to sync (cron format or @every syntax)
SYNC_INTERVAL=@every 5m
# Log level: info or debug
LOG_LEVEL=infoUsing Docker Compose:
docker compose up -dOr run manually using the pre-built image:
docker run -d \
--name traefik-pihole-dns-sync \
--env-file .env \
ghcr.io/rpressiani/traefik-pihole-dns-sync:latestBefore making actual changes:
docker run --rm --env-file .env ghcr.io/rpressiani/traefik-pihole-dns-sync:latest --dry-runOr run once without scheduling:
docker run --rm --env-file .env ghcr.io/rpressiani/traefik-pihole-dns-sync:latest --onceTest the Traefik API directly:
cd tools
go build -o test-api test-api.go
./test-api --rules| Variable | Default | Description |
|---|---|---|
TRAEFIK_API_URL |
http://traefik:8080/api/http/routers |
Traefik API endpoint |
PIHOLE_URL |
(required) | Pi-hole web interface URL |
PIHOLE_PASSWORD |
(required) | Pi-hole admin password |
TRAEFIK_HOST_IP |
(required) | IP address for DNS A records |
SYNC_INTERVAL |
@every 5m |
Sync frequency (cron or @every) |
LOG_LEVEL |
info |
Log verbosity: info or debug |
RUN_MODE |
(empty) | Run mode: dry-run, once, scheduled-dry-run, or empty for scheduled |
You can use standard cron expressions or the @every syntax:
@every 5m- Every 5 minutes@every 1h- Every hour*/10 * * * *- Every 10 minutes (standard cron)0 */2 * * *- Every 2 hours (standard cron)
--once- Run sync once and exit (useful for testing)--dry-run- Show what would be synced without making changes
View logs:
docker compose logs -f traefik-pihole-dns-syncTo build and test changes locally without pushing to GitHub:
- Edit
docker-compose.ymland uncommentbuild: .(comment outimage: ...) - Build and run:
docker compose up -d --build
You can now control run modes via environment variables in docker-compose.yml:
environment:
- RUN_MODE=dry-run # Run once in dry-run mode
# - RUN_MODE=once # Run once with actual changes
# - RUN_MODE=scheduled-dry-run # Run on schedule in dry-run mode (monitoring)
# Leave RUN_MODE empty or unset for normal scheduled syncThen simply:
docker compose upAlternatively, use command-line flags (these take precedence over RUN_MODE):
# Build the image
docker compose build
# Run once with dry-run (no changes made)
docker compose run --rm traefik-pihole-dns-sync --dry-run --once
# Run once (makes actual changes)
docker compose run --rm traefik-pihole-dns-sync --once- Ensure Traefik API is enabled and accessible
- Check that the container is on the same network as Traefik
- Verify
TRAEFIK_API_URLis correct
- Verify
PIHOLE_PASSWORDis correct - Ensure Pi-hole is accessible from the container
- Check Pi-hole logs for authentication errors
- Verify your Traefik routers have
Host()rules - Check that routers are enabled
- Run with
LOG_LEVEL=debugfor more details
Note
This tool uses Pi-hole v6 session-based authentication. It requires your Pi-hole App Password to generate a session ID. The password is only used to obtain the session and is not stored or logged.
- Add support for removing stale DNS records
- Add Prometheus metrics
- Support for CNAME records instead of A records
- Webhook notifications on sync errors
MIT