---
title: "Pi-hole HA Deployment Notes"
description: "Deployment log for dual Pi-hole HA setup including v5-to-v6 upgrade issues, Orbital Sync auth failures, known issues, and blocklist restoration steps."
type: runbook
domain: networking
tags: [pihole, dns, high-availability, deployment, pihole-v6, orbital-sync]
---

# Pi-hole HA Deployment Notes - 2026-02-06

## Deployment Summary

Successfully deployed dual Pi-hole high availability setup with the following configuration:

### Infrastructure

**Primary Pi-hole (npm-pihole)**
- Host: 10.10.0.16 (LXC container)
- Version: Pi-hole v6 (upgraded from v5.18.3)
- Web UI: http://10.10.0.16:81/admin
- Web Password: newpihole456
- App Password: Stored in `~/.claude/secrets/pihole1_app_password`
- DNS Port: 53
- Blocklists: 36 lists (restored from v5 backup)

**Secondary Pi-hole (ubuntu-manticore)**
- Host: 10.10.0.226 (Physical server)
- Version: Pi-hole v6.4
- Web UI: http://10.10.0.226:8053/admin
- Web Password: pihole123
- App Password: Stored in `~/.claude/secrets/pihole2_app_password`
- DNS Port: 53
- Note: systemd-resolved stub listener disabled

### What's Working

✅ **DNS Resolution**
- Both Pi-holes responding to DNS queries
- Ad blocking functional on both instances
- NPM custom DNS sync working (18 domains synced to primary)

✅ **Network Configuration**
- Primary Pi-hole accessible network-wide
- Secondary Pi-hole accessible network-wide
- systemd-resolved conflicts resolved

✅ **NPM Integration**
- npm-pihole-sync.sh script enhanced for dual Pi-hole support
- Script located: `/home/cal/scripts/npm-pihole-sync.sh` on npm-pihole
- Hourly cron configured
- Syncs 18 proxy host domains to primary Pi-hole

### Known Issues

⚠️ **Orbital Sync Authentication Failing**
- Orbital Sync v1.8.4 unable to authenticate with Pi-hole v6
- App passwords generated but login fails
- Location: `~/docker/orbital-sync/` on ubuntu-manticore
- Status: Needs further investigation or alternative sync solution

⚠️ **Secondary Pi-hole NPM Domains**
- Custom DNS entries not synced to secondary yet
- git.manticorum.com resolves to Cloudflare IPs on secondary
- Primary resolves correctly to 10.10.0.16
- Impact: Minimal for HA DNS, but local overrides only on primary

⚠️ **Blocklists Not Synced**
- Primary has 36 blocklists restored from v5 backup
- Secondary still has default lists only
- Orbital Sync would handle this once authentication is fixed

## v5 → v6 Upgrade Notes

### Database Migration Issue

When upgrading Pi-hole from v5 to v6, the gravity database schema changed:
- v5 database: 114MB with 36 adlists
- v6 fresh database: 108KB with 1 default list

**Resolution:**
1. Backup created automatically: `gravity.db.v5.backup`
2. Adlists extracted from backup using Python sqlite3
3. All 36 adlist URLs restored via web UI (comma-separated paste)

**Lesson Learned**: Always export adlists before major version upgrades

### Authentication Changes

Pi-hole v6 uses app passwords instead of API tokens:
- Generated via: Settings → Web Interface / API → Configure app password
- Different from web login password
- Required for API access and tools like Orbital Sync

## Next Steps

### Immediate
1. ✅ Document app password locations (completed)
2. ✅ Update .env.example files (completed)
3. ✅ Update deployment documentation (completed)

### Short Term
1. **Restore blocklists to secondary** - Manually add 36 adlists via web UI
2. **Manually sync NPM domains to secondary** - Update custom.list on secondary
3. **Update UniFi DHCP** - Configure DNS1=10.10.0.16, DNS2=10.10.0.226
4. **Test failover** - Verify DNS works when primary is down

### Long Term
1. **Investigate Orbital Sync v6 compatibility** - Check for updates or alternatives
2. **Consider manual sync script** - Interim solution until Orbital Sync works
3. **Monitor Pi-hole v6 releases** - Watch for stability updates

## File Locations

### Secrets
```
~/.claude/secrets/pihole1_app_password  # Primary app password
~/.claude/secrets/pihole2_app_password  # Secondary app password
```

### Server Configs
```
server-configs/ubuntu-manticore/docker-compose/pihole/
server-configs/ubuntu-manticore/docker-compose/orbital-sync/
server-configs/networking/scripts/npm-pihole-sync.sh
```

### Runtime Locations
```
npm-pihole:
  /home/cal/container-data/pihole/        # Primary Pi-hole data
  /home/cal/scripts/npm-pihole-sync.sh    # NPM sync script
  /home/cal/container-data/pihole/etc-pihole/gravity.db.v5.backup  # v5 backup

ubuntu-manticore:
  ~/docker/pihole/                        # Secondary Pi-hole
  ~/docker/orbital-sync/                  # Sync service (not working yet)
```

## Blocklist URLs (36 total)

Comma-separated for web UI import:
```
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts,https://blocklistproject.github.io/Lists/ads.txt,https://blocklistproject.github.io/Lists/abuse.txt,https://raw.githubusercontent.com/matomo-org/referrer-spam-blacklist/master/spammers.txt,https://someonewhocares.org/hosts/zero/hosts,https://raw.githubusercontent.com/VeleSila/yhosts/master/hosts,https://winhelp2002.mvps.org/hosts.txt,https://v.firebog.net/hosts/neohostsbasic.txt,https://raw.githubusercontent.com/RooneyMcNibNug/pihole-stuff/master/SNAFU.txt,https://paulgb.github.io/BarbBlock/blacklists/hosts-file.txt,https://v.firebog.net/hosts/static/w3kbl.txt,https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts,https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txt,https://v.firebog.net/hosts/Easyprivacy.txt,https://v.firebog.net/hosts/Prigent-Ads.txt,https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts,https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt,https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt,https://hostfiles.frogeye.fr/multiparty-trackers-hosts.txt,https://www.github.developerdan.com/hosts/lists/ads-and-tracking-extended.txt,https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/android-tracking.txt,https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/SmartTV.txt,https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/AmazonFireTV.txt,https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt,https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt,https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt,https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt,https://v.firebog.net/hosts/Prigent-Crypto.txt,https://bitbucket.org/ethanr/dns-blacklists/raw/8575c9f96e5b4a1308f2f12394abd86d0927a4a0/bad_lists/Mandiant_APT1_Report_Appendix_D.txt,https://phishing.army/download/phishing_army_blocklist_extended.txt,https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt,https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt,https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts,https://urlhaus.abuse.ch/downloads/hostfile/,https://v.firebog.net/hosts/Prigent-Malware.txt,https://v.firebog.net/hosts/Shalla-mal.txt
```

## Testing Commands

```bash
# Test DNS on both Pi-holes
dig @10.10.0.16 google.com +short
dig @10.10.0.226 google.com +short

# Test ad blocking
dig @10.10.0.16 doubleclick.net +short  # Should return 0.0.0.0
dig @10.10.0.226 doubleclick.net +short  # Should return 0.0.0.0

# Test NPM custom DNS (primary only currently)
dig @10.10.0.16 git.manticorum.com +short  # Should return 10.10.0.16
dig @10.10.0.226 git.manticorum.com +short  # Currently returns Cloudflare IPs

# Check Pi-hole status
ssh cal@10.10.0.16 "docker exec pihole pihole status"
ssh ubuntu-manticore "docker exec pihole pihole status"
```
