deploy: keep config backups out of dnsmasq conf dirs, cap at 10

Backups were written as <conf>.backup.<ts> next to the live file. Both
dnsmasq instances load every file in their conf dir (the host excludes
only .dpkg-*), so each backup was parsed as live config, resurrecting
removed domains and piling up one stale copy per deploy.

Write them to BACKUP_DIR (/var/backups/bbrkn) instead and keep the
newest BACKUP_KEEP (10) per file.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DR7zpSsdX28T4Kn6v4jPSS
This commit is contained in:
goodvin 2026-10-13 20:54:19 +03:00
parent 1dff606865
commit a5ee057c59
2 changed files with 24 additions and 2 deletions

View file

@ -132,6 +132,8 @@ make warm # прогреть nft-сеты (запускать на шл
| `TARGET_DIR` | `/opt/appdata/pihole/etc/dnsmasq.d` | Директория dnsmasq в Pi-hole (для `92-resolve`) | | `TARGET_DIR` | `/opt/appdata/pihole/etc/dnsmasq.d` | Директория dnsmasq в Pi-hole (для `92-resolve`) |
| `DOCKER_CONTAINER` | `pihole` | Имя Docker-контейнера Pi-hole | | `DOCKER_CONTAINER` | `pihole` | Имя Docker-контейнера Pi-hole |
| `HOST_DNSMASQ_SVC` | `dnsmasq` | systemd-сервис host-инстанса dnsmasq | | `HOST_DNSMASQ_SVC` | `dnsmasq` | systemd-сервис host-инстанса dnsmasq |
| `BACKUP_DIR` | `/var/backups/bbrkn` | Куда класть бэкапы конфигов перед деплоем (НЕ в `dnsmasq.d` — оттуда грузится всё) |
| `BACKUP_KEEP` | `10` | Сколько последних бэкапов хранить на каждый файл |
| `NFT_SETS` | `inet filter bbrkn_v4;inet filter bbrkn_v6` | Сеты для flush после деплоя (через `;`) | | `NFT_SETS` | `inet filter bbrkn_v4;inet filter bbrkn_v6` | Сеты для flush после деплоя (через `;`) |
| `DNS_LISTEN_ADDR` | `127.0.0.1` | Адрес, на котором Pi-hole слушает DNS (:53) | | `DNS_LISTEN_ADDR` | `127.0.0.1` | Адрес, на котором Pi-hole слушает DNS (:53) |
| `DNS_CHECK_DOMAIN` | `google.com` | Домен базового DNS health check | | `DNS_CHECK_DOMAIN` | `google.com` | Домен базового DNS health check |

View file

@ -14,6 +14,11 @@ RESOLVE_CONF="${RESOLVE_CONF:-/tmp/92-resolve-bbrkn.conf}"
NFTSET_TARGET_DIR="${NFTSET_TARGET_DIR:-/etc/dnsmasq.d}" NFTSET_TARGET_DIR="${NFTSET_TARGET_DIR:-/etc/dnsmasq.d}"
RESOLVE_TARGET_DIR="${RESOLVE_TARGET_DIR:-${TARGET_DIR:-/opt/appdata/pihole/etc/dnsmasq.d}}" RESOLVE_TARGET_DIR="${RESOLVE_TARGET_DIR:-${TARGET_DIR:-/opt/appdata/pihole/etc/dnsmasq.d}}"
# Бэкапы — ВНЕ conf-dir: dnsmasq (и pihole) грузит из dnsmasq.d все файлы,
# кроме исключённых расширений, так что *.backup.* там стал бы живым конфигом.
BACKUP_DIR="${BACKUP_DIR:-/var/backups/bbrkn}"
BACKUP_KEEP="${BACKUP_KEEP:-10}" # сколько последних копий хранить на каждый файл
DOCKER_CONTAINER="${DOCKER_CONTAINER:-pihole}" DOCKER_CONTAINER="${DOCKER_CONTAINER:-pihole}"
# systemd-сервис host-инстанса dnsmasq (:5350) # systemd-сервис host-инстанса dnsmasq (:5350)
HOST_DNSMASQ_SVC="${HOST_DNSMASQ_SVC:-dnsmasq}" HOST_DNSMASQ_SVC="${HOST_DNSMASQ_SVC:-dnsmasq}"
@ -82,16 +87,31 @@ rollback() {
# ============================== # ==============================
# Бэкап существующих файлов # Бэкап существующих файлов
# ============================== # ==============================
# Оставляет BACKUP_KEEP самых свежих копий <name>.backup.<ts>
# (ts вида YYYYmmdd-HHMMSS сортируется лексикографически).
prune_backups() { # <name>
local name="$1" old
find "$BACKUP_DIR" -maxdepth 1 -type f -name "${name}.backup.*" -printf '%f\n' \
| sort -r | tail -n +"$((BACKUP_KEEP + 1))" \
| while read -r old; do
rm -f -- "$BACKUP_DIR/$old"
echo " pruned old backup $old"
done
}
mkdir -p "$BACKUP_DIR"
ts=$(date +%Y%m%d-%H%M%S) ts=$(date +%Y%m%d-%H%M%S)
if [ -f "$nftset_dest" ]; then if [ -f "$nftset_dest" ]; then
NFTSET_BACKUP="${nftset_dest}.backup.${ts}" NFTSET_BACKUP="$BACKUP_DIR/${nftset_name}.backup.${ts}"
cp "$nftset_dest" "$NFTSET_BACKUP" cp "$nftset_dest" "$NFTSET_BACKUP"
echo "Backed up $nftset_dest → $NFTSET_BACKUP" echo "Backed up $nftset_dest → $NFTSET_BACKUP"
prune_backups "$nftset_name"
fi fi
if [ -f "$resolve_dest" ]; then if [ -f "$resolve_dest" ]; then
RESOLVE_BACKUP="${resolve_dest}.backup.${ts}" RESOLVE_BACKUP="$BACKUP_DIR/${resolve_name}.backup.${ts}"
cp "$resolve_dest" "$RESOLVE_BACKUP" cp "$resolve_dest" "$RESOLVE_BACKUP"
echo "Backed up $resolve_dest → $RESOLVE_BACKUP" echo "Backed up $resolve_dest → $RESOLVE_BACKUP"
prune_backups "$resolve_name"
fi fi
# ============================== # ==============================