Backup e ripristino
Una foto del config tree, un ripristino atomico, il daemon che continua a girare.
Cos’è
warden config backup scrive un singolo archivio tar.gz con l’albero
di configurazione di Warden — il config.toml master più ogni directory
sorella *.d/ che Warden sta usando in quel momento.
warden config restore <archivio> prende uno di quegli archivi, sostituisce
l’albero live in modo atomico e segnala al daemon di ricaricare — niente
systemctl restart.
Sono checkpoint operativi, non snapshot differenziali. Ne fai uno prima di una modifica rischiosa (“sto per cambiare le blocklist”), tieni qualche copia rotante su un disco separato, e ripristini la più recente che funziona quando qualcosa va storto. Warden può anche prendere questi checkpoint in automatico, su pianificazione — vedi backup automatici più sotto.
Quando ti serve
- Prima di una modifica strutturale. Toccare
[server], cambiare i resolver upstream, importare un nuovo set di blocklist — qualunque cosa in cui un refuso o un errore di validazione può lasciarti senza DNS sulla LAN. Fai prima il backup; se va male, ripristini in pochi secondi. - Migrazione su una nuova macchina. Esegui
warden config backupsulla vecchia, copi l’archivio, eseguiwarden config restoresulla nuova. Il daemon sulla nuova macchina prende la config senza riavvio. - Recupero da un’edit sbagliata. Una
warden config editche ha introdotto un errore logico notato un’ora dopo? Ripristina l’archivio pre-modifica più recente e lascia che il daemon faccia hot-reload. - Backup off-host periodico. Un cron notturno che esegue
warden config backup --out /mnt/backup/warden/e ruota gli archivi vecchi ti dà una finestra rotante senza toccare il daemon — oppure lascia fare allo scheduler integrato.
Non ti servono backup/restore per i dati delle blocklist, per le
statistiche, per il log di audit o di query — non fanno parte dell’albero
di configurazione (vedi sotto). Per lo stato di sistema completo,
snapshotta /var/lib/purge-warden/ separatamente.
Cosa contiene
Un backup è un tar.gz dell’albero di configurazione, ancorato alla
directory padre del config.toml master. Contiene:
- Il TOML master (
config.toml, o il path che Warden sta usando). - Ogni directory sorella
*.d/esistente al momento del backup:devices.d/,profiles.d/,groups.d/,blocklists.d/,subnets.d/,schedules.d/,rules.d/.
Non contiene:
- Le blocklist scaricate sotto
/var/lib/purge-warden/lists/. - Gli snapshot di statistiche sotto
/var/lib/purge-warden/data/. - Il log di audit né il log di query.
- Token IPC, token REST API, file
*.secret. - Il PID file.
Niente manifest, niente schema-version embedded, nessuna cifratura —
l’archivio è un tar -czf standard. Sorgente:
src/cli/commands/config/backup.rs.
CLI
| Comando | Cosa fa |
|---|---|
warden config backup | Scrive <backup-dir>/config-<UTC-timestamp>.tar.gz (dir di default <config-parent>/backups). |
warden config backup --out <dir> | Scrive invece l’archivio in <dir>/config-<UTC-timestamp>.tar.gz. La directory deve esistere. |
warden config restore <archivio> | Valida l’archivio, sostituisce l’albero live, segnala al daemon di ricaricare. |
warden config restore --list | Elenca i restore point nella backup dir (data, età, dimensione, dal più recente). Non ripristina nulla. |
warden config restore --latest | Ripristina l’archivio più recente nella backup dir senza nominarlo. |
Il nome del file dell’archivio è sempre config-YYYYMMDDTHHMMSSZ.tar.gz;
solo la directory è configurabile ([backup] dir o --out). Sorgente:
src/cli/mod.rs, src/cli/commands/config/backup.rs.
Non c’è output --json né backup info. Per vedere cosa puoi ripristinare,
usa warden config restore --list. Per ispezionare il contenuto di un
archivio senza ripristinarlo, estrailo in una directory di lavoro e lancia
warden config lint <estratto>/config.toml.
I flag dedicati allo scheduler --auto e --reset-auto-failure sono
trattati in backup automatici.
Dove finiscono gli archivi
Di default gli archivi finiscono in <config-parent>/backups/ — la
directory backups/ accanto al tuo config.toml master. Puoi spostarli
altrove con la sezione opzionale [backup]:
[backup]
dir = "/srv/purge-backups" # default: <config-parent>/backupsIl daemon ignora del tutto [backup] — è solo per il tooling. La CLI
(warden config backup, restore --list) e il restore picker della
dashboard leggono tutte questa singola impostazione. (Modificarla dalla
dashboard non è in questa release — impostala nel file.)
Permessi della backup dir. I backup girano come utente del daemon
(purge-warden), con gate peer-uid, sia da CLI sia da dashboard. La
directory di backup deve essere scrivibile da quell’utente — altrimenti
tar fallisce con Permission denied. L’installer (scripts/install.sh)
prepara la default <config-parent>/backups con l’ownership corretto,
quindi su un’installazione standard non serve fare niente. Se punti dir
a un percorso custom (es. /srv/purge-backups, un volume dedicato),
i permessi di quel path sono responsabilità tua:
sudo install -d -m 0755 -o purge-warden -g purge-warden /srv/purge-backups
Esempi
Un checkpoint manuale prima di un’edit:
sudo warden config backup
# → /etc/purge-warden/backups/config-20260505T091322Z.tar.gz
sudo warden config edit
Un backup notturno rotante su un mount off-host:
# Snapshot notturno della config Warden, rotazione dopo 30 giorni.
15 3 * * * root /usr/bin/warden config backup --out /mnt/backup/warden/ && \
find /mnt/backup/warden/ -name 'config-*.tar.gz' -mtime +30 -deleteUna migrazione verso una nuova macchina:
# sulla vecchia
sudo warden config backup --out /tmp/
scp /tmp/config-*.tar.gz nuovo-host:/tmp/
# sulla nuova (dopo `warden init`)
sudo warden config restore /tmp/config-20260505T091322Z.tar.gz
Un recupero da un’edit sbagliata — elenca i restore point, poi prendi il più recente:
sudo warden config restore --list
# config-20260505T091322Z.tar.gz 2 minuti fa 14.2 KiB
# config-20260504T031500Z.tar.gz 1 giorno fa 14.1 KiB
# config-20260503T031500Z.tar.gz 2 giorni fa 13.9 KiB
sudo warden config restore --latest
Dalla dashboard
La tab Settings della TUI pilota lo stesso engine:
b— backup immediato. Il path dell’archivio compare nel footer.R— apre il restore picker: ogni restore point con data, età relativa e dimensione, dal più recente. Ne scegli uno, premiEnter, confermi cony; Warden lo ripristina e ricarica il daemon. La config precedente resta accanto come copia.pre-restore, quindi il restore è recuperabile.
Backup automatici
Tutto quanto sopra è manuale. Warden può anche fare backup su
pianificazione: un timer systemd sveglia il binario ogni ora, e
warden config backup --auto decide se un backup è davvero dovuto. Il
daemon resta intatto — lo scheduler è puro tooling, nessuna nuova superficie
IPC.
Configurazione
Estendi [backup] con fino a cinque campi opzionali:
[backup]
dir = "/var/lib/purge-warden/backups" # esisteva già
auto_interval = "24h" # off quando assente. "<N>h" o "<N>d", range 1h..720h (30d).
on_change = false # riservato a una release futura; parsato ma inerte.
retention_count = 30 # tieni al massimo N archivi (0 = illimitato).
retention_days = 90 # scarta archivi più vecchi di D giorni (0 = illimitato).
disable_after_failures = 3 # auto-disabilita dopo N fallimenti consecutivi (0 = mai).Tutti opzionali; le config esistenti continuano a caricarsi invariate.
Senza auto_interval lo scheduler non fa niente. retention_count e
retention_days sono in OR — un archivio viene scartato se supera anche
solo una delle due soglie. La retention rimuove solo file
config-*.tar.gz; i file .lock, .auto_state e .pre-restore-* non
vengono mai potati.
Come gira la pianificazione
Due unit systemd, installate entrambe per te:
purge-warden-backup.timer— scatta ogni ora (OnUnitActiveSec=1h,OnBootSec=15min,Persistent=true), e recupera al boot se la macchina era spenta quando un tick era dovuto.purge-warden-backup.service—Type=oneshot, eseguewarden config backup --autocome utente del daemon.
Il timer non conosce il tuo intervallo. Ogni run --auto legge lo state
file e decide:
disabled = true→ exit 0.- Nessun
auto_intervalimpostato → exit 0. now - last_attempt < auto_interval→ exit 0 (“non dovuto”).- Altrimenti → acquisisce il lock, fa il backup, aggiorna lo stato, applica la retention.
Cambiare auto_interval ha effetto al tick orario successivo — niente
systemctl daemon-reload, niente reinstall.
State file
<backup-dir>/.auto_state — JSON, scritto in modo atomico, leggibile a mano:
sudo cat /var/lib/purge-warden/backups/.auto_state
# {
# "consecutive_failures": 0,
# "last_attempt": "2026-05-29T03:00:00Z",
# "last_outcome": { "kind": "ok" },
# "disabled": false
# }
consecutive_failures— quanti run--autodi fila sono falliti. Azzerato al primo successo. I run manuali non lo toccano mai.last_attempt— RFC3339 UTC del run più recente (anche il manuale lo aggiorna, così le altre viste restano coerenti).last_outcome—{"kind":"ok"}oppure{"kind":"err","message":"…"}.disabled—truedopodisable_after_failuresfallimenti auto consecutivi. I backup manuali lo ignorano e girano comunque.
Riabilitare dopo l’auto-disable
Dopo disable_after_failures fallimenti consecutivi lo scheduler imposta
disabled = true e i tick successivi diventano no-op. Per sbloccarlo:
sudo -u purge-warden warden config backup --reset-auto-failure
Azzera consecutive_failures e disabled, non scrive alcun archivio e
preserva la storia (last_attempt / last_outcome). È idempotente — un
no-op quando non c’è niente da resettare. Il prossimo tick --auto riprova
normalmente, e il banner rosso sulla tab Settings sparisce.
Lock file
<backup-dir>/.lock viene creato all’inizio di ogni backup (manuale o auto)
e rimosso alla fine:
- Un altro backup già in corso → exit
75(EX_TEMPFAIL) conbackup in progress (lock held since <ts>)su stderr. - Un lock stale (mtime più vecchio di 5 minuti, lasciato da un run crashato) viene rimosso automaticamente dal run successivo.
Ispezionare lo scheduler
systemctl status purge-warden-backup.timer # quando scatta il prossimo tick
systemctl status purge-warden-backup.service # ultimo tick + exit code
journalctl -u purge-warden-backup.service # storia dei tick (incl. "non dovuto" / "disabled")
Come funziona il restore
Conoscere l’ordine delle operazioni aiuta a capire cosa è sicuro e cosa no.
- Estrazione. L’archivio viene scompattato in una directory di
staging dedicata sotto
$TMPDIR. La directory di staging viene pulita automaticamente all’uscita, anche in caso di fallimento. - Localizzazione del master. L’handler cerca, nell’albero estratto,
un file con lo stesso nome del master live; se non lo trova, ricade
sul primo
*.tomlalla radice dello staging. - Validazione. Il master estratto viene caricato attraverso il
loader v1 completo di Warden (
loader::load_config) — lo stesso validatore che usawarden config lint. Se la validazione fallisce, l’albero live non viene toccato. Exit code 1, errori stampati con file e linea. - Snapshot del master live. Il master live corrente viene rinominato
in
<live>.pre-restore-<UTC-timestamp>come via di rollback. - Replace atomico del master. Il master estratto viene scritto in
posizione tramite
atomic_write_and_validate— file temp nella stessa directory, seguito da rename POSIX. Se il processo crasha a metà scrittura, il file live è intatto. - Replace di ogni sorella
.d/. Per ogni directory*.d/presente nell’albero estratto, quella live viene rimossa e quella estratta ricopiata ricorsivamente. Questo passo non è atomico fra directory — un crash fra due sorelle lascia un mix. - Segnale al daemon. Se il PID file è presente, l’handler invia un
SIGHUP. Il daemon ricarica da disco viaArcSwap— niente riavvio, niente query perse. Se il SIGHUP fallisce, il restore va comunque a buon fine e stampa un warning; il prossimowarden reload(o l’avvio del daemon) prenderà il nuovo stato.
Sorgente: src/cli/commands/config/restore.rs.
*.d/ live vengono rimosse e sostituite per intero. Se hai
file slice locali in devices.d/ o profiles.d/ che non sono
nell’archivio, verranno cancellati. Se è un problema, copiali da
parte prima del restore e rimettili dopo.config.toml.pre-restore-<ts>), non le sorelle .d/. Per fare il
rollback completo di un restore, ripristina dall’archivio precedente,
non dal file .pre-restore.Exit code
| Code | Significato |
|---|---|
0 | Successo — backup scritto, restore applicato (SIGHUP recapitato, se applicabile), o un run --auto non dovuto. |
1 | Validazione del restore fallita (l’albero live è invariato, l’errore nomina file e chiave), oppure errore I/O: archivio mancante, illeggibile, tarball malformato, destinazione non scrivibile. |
75 | EX_TEMPFAIL — un backup è già in corso (lock occupato). Riprova fra poco. |
Sorgente: src/cli/commands/config/restore.rs, src/cli/commands/config/backup.rs.
Sicurezza
- Gli archivi contengono config in chiaro, inclusi eventuali token o
segreti che hai inserito direttamente nel TOML. Trattali come sensibili:
niente push su un Git remoto pubblico, e preferisci
chmod 600sulla directory di destinazione. - Nessuna cifratura. Se ti serve un backup off-host cifrato, avvolgi
l’archivio:
gpg --encrypt,age, oppure includilo in uno snapshot di un filesystem cifrato. - Nessuna firma. L’handler di restore si fida del contenuto dell’archivio oltre il validatore v1. Non ripristinare archivi da fonti non fidate.
- Audit trail. Le azioni di backup e restore sono registrate nel log di audit con uid invocante, path dell’archivio e risultato.
Troubleshooting
warden config restore esce con 1 e schema_version mismatch.
L’archivio è di una versione di Warden precedente a 1.x. Lancia
warden migrate v0-to-v1 sul master estratto prima di ripristinarlo,
oppure ripristina un archivio della stessa major version.
warden config restore esce con 0 ma il daemon serve ancora la
config vecchia.
Il SIGHUP è andato perso (di solito perché il PID file era stale o il
daemon era stato riavviato sotto un PID diverso). Lancia warden reload
manualmente; se anche quello dice “no daemon”, il daemon non era in
esecuzione durante il restore.
warden config backup esce con 75 e backup in progress.
Un altro backup tiene il lock — di solito un run --auto pianificato che
si sovrappone al tuo manuale. Aspetta un attimo e riprova. Se non c’è
nessun backup davvero in corso, un .lock stale più vecchio di 5 minuti
viene ripulito dal run successivo.
I backup pianificati hanno smesso di partire.
Lo scheduler si è auto-disabilitato dopo fallimenti ripetuti. Controlla
sudo cat <backup-dir>/.auto_state per "disabled": true e il messaggio
last_outcome, risolvi la causa (di solito i permessi della directory),
poi riabilita con warden config backup --reset-auto-failure.
tar: Cannot open: Permission denied da warden config backup.
La directory di backup non esiste o non è scrivibile dall’utente del daemon.
Creala con l’ownership giusto (vedi dove finiscono gli archivi)
o scegli un --out scrivibile.
La dimensione del backup cresce nel tempo.
Probabilmente una directory .d/ ha accumulato file slice obsoleti.
Esegui warden config lint per individuare gli orfani e ripulirli prima
del prossimo backup.
warden config restore ha avuto successo ma un file slice custom è
sparito.
Il restore sostituisce le .d/ per intero. Lo slice non era nell’archivio.
Se ti serve, ripristinalo da un archivio più vecchio che lo contiene, o
ricrealo a mano.
Per altri problemi operativi, vedi troubleshooting.
Vedi anche
- Riferimento
warden config— tutti i verbi config in un colpo d’occhio. - Impostazioni globali — cosa vive nel TOML master.
- Percorsi file — dove Warden legge e scrive su disco.
- Servizio systemd — le unit timer e service.
- Log di audit — conferma ogni backup/restore.
- Troubleshooting — flussi di recupero più ampi.