From 293e6ddd33040cbe7fd39813464cd69d1c94537c Mon Sep 17 00:00:00 2001 From: abrown38 Date: Thu, 8 Oct 2026 19:02:34 +0000 Subject: [PATCH] Add backups, token expiry warnings and name server checks - Daily database backups: jarl-backup.timer runs 'jarld backup', which writes jarl-.db into backup.dir, checks it before naming it, and prunes by the time in the name while always keeping the newest keep_at_least. New backup: section in jarl.yaml; the dashboard and 'jarl status' show the newest backup and warn when it is stale or failed. The Debian package enables the timer. - 'jarld restore [FILE | latest]': checks the backup, shows it next to the current database, keeps the current one aside and records the restore. 'jarld serve' holds a database lock, so a restore can't run under a live jarld and two jarlds can't share a database. - Token expiry warnings from 14 days ahead: dashboard, token lists, a daily log line, and a CLI warning via the Jarl-Token-Expires header; 'jarl token list --expiring'. - 'jarl zone serials' and the zone page's Name servers tab: compare the serial on a primary zone's secondaries (NS records, also-notify) or a secondary zone's primaries with this server's. - 'jarl zone delegation': for zones on the internet, check the parent's delegation and glue against the zone; an undelegated zone gets a note. - Server: Jarl/ header; CLI exit code 2 for failed checks. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 34 ++ Makefile | 14 +- README.md | 10 +- cmd/jarl/admin_cmds.go | 76 ++- cmd/jarl/main.go | 42 ++ cmd/jarl/nscheck.go | 269 +++++++++++ cmd/jarl/zones.go | 2 +- cmd/jarld/admin.go | 24 - cmd/jarld/backup.go | 374 +++++++++++++++ cmd/jarld/lock.go | 40 ++ cmd/jarld/main.go | 12 +- deploy/debian/postinst | 18 + deploy/debian/postrm | 19 +- deploy/debian/prerm | 10 +- deploy/systemd/jarl-backup.service | 47 ++ deploy/systemd/jarl-backup.timer | 20 + deploy/tmpfiles.d/jarl.conf | 2 + docs/api.md | 38 +- docs/cli.md | 19 +- docs/configuration.md | 19 + docs/development.md | 6 +- docs/install.md | 36 +- docs/operations.md | 249 +++++++++- docs/permissions.md | 19 + internal/api/types.go | 52 ++ internal/backup/backup.go | 256 ++++++++++ internal/backup/backup_test.go | 151 ++++++ internal/client/client.go | 8 + internal/config/config.go | 53 ++- internal/engine/engine.go | 14 + internal/model/changeset.go | 10 + internal/nscheck/delegation.go | 449 ++++++++++++++++++ internal/nscheck/nscheck.go | 338 +++++++++++++ internal/nscheck/nscheck_test.go | 245 ++++++++++ internal/server/authn.go | 57 ++- internal/server/expiry_test.go | 117 +++++ internal/server/h_changes.go | 48 +- internal/server/h_nscheck.go | 269 +++++++++++ internal/server/nscheck_test.go | 71 +++ internal/server/routes.go | 2 + internal/server/server.go | 14 + internal/store/store.go | 63 +++ internal/web/static/assets/pages/dashboard.js | 32 +- internal/web/static/assets/pages/users.js | 12 +- internal/web/static/assets/pages/zone.js | 101 ++++ scripts/e2e.sh | 45 ++ scripts/mkdeb.sh | 6 +- 47 files changed, 3717 insertions(+), 95 deletions(-) create mode 100644 cmd/jarl/nscheck.go create mode 100644 cmd/jarld/backup.go create mode 100644 cmd/jarld/lock.go create mode 100644 deploy/systemd/jarl-backup.service create mode 100644 deploy/systemd/jarl-backup.timer create mode 100644 internal/backup/backup.go create mode 100644 internal/backup/backup_test.go create mode 100644 internal/nscheck/delegation.go create mode 100644 internal/nscheck/nscheck.go create mode 100644 internal/nscheck/nscheck_test.go create mode 100644 internal/server/expiry_test.go create mode 100644 internal/server/h_nscheck.go create mode 100644 internal/server/nscheck_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index a934f57..458e85b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,40 @@ The first version, to be released as 0.1.0. ### Added +- Daily database backups: the `jarl-backup.timer` systemd timer (turned on + by the Debian package) runs `jarld backup`, which writes + `jarl-.db` into `backup.dir` (`/var/backups/jarl`), checks it + with SQLite's integrity check before giving it that name, and deletes + backups older than `backup.retention` (30d) while always keeping the + newest `backup.keep_at_least` (7). Ages come from the names, and only + files named like backups are ever deleted. Settings are in the new + `backup:` section of jarl.yaml; the schedule is the timer's. The dashboard + and `jarl status` show the newest backup, and warn when it is older than + `backup.warn_after` (2d) or the last attempt failed. `backup.stats` also + backs up the statistics database. +- `jarld restore [FILE | latest]`: lists backups, or checks one, shows what + it holds next to the current database, and after confirmation replaces + the database with it, keeping the current one as + `jarl.db.before-restore-