-
v0.10.0
StableAll checks were successfulCI / Build / Publish / Shellcheck (push) Successful in 2sCI / Build / Publish / Validate CHANGELOG structure (push) Successful in 1sCI / Build / Publish / PR build & smoke test (push) Has been skippedCI / Build / Publish / Round-trip + scheduler smoke (push) Successful in 4m0sCI / Build / Publish / Workflow summary (push) Successful in 1sCI / Build / Publish / Bats unit tests (push) Successful in 6sCI / Build / Publish / Host-driven integration (entrypoint + storage sidecars) (push) Successful in 1m51sCI / Build / Publish / Build multi-arch and push (push) Successful in 2m6sCI / Build / Publish / Reconcile releases across registries (push) Successful in 55sreleased this
2026-07-12 11:49:44 -07:00 | 9 commits to main since this releaseBreaking
- Backups and maintenance are now two independent pipelines. The backup run is hooks → backup → copies, nothing else; storage check and prune moved to a separate maintenance pipeline with its own schedule, lock, and log (
maintenance.log). Nightly-cost consequence: the multi-hour storage-wide chunk listings that used to run inside every backup (check on every storage plusprune -exhaustiveon every storage — up to three full sftp/B2 enumerations per storage per night) are gone from the backup path entirely; secondaries are verified by the copy itself (its destination enumeration re-uploads anything missing, healing instead of just reporting). The two pipelines coordinate through per-storage locks, so a check/prune never overlaps a copy on the same storage (the copy-vs-prune concurrency duplicacy does not document as safe is excluded structurally); the waiting side logs who holds the storage. A maintenance overrun can never delay the next backup. CRON_SCHEDULEwas renamed toBACKUP_SCHEDULE, and the newMAINTENANCE_SCHEDULEdrives the maintenance pipeline (unset = maintenance only runs viaarchiver maintenance). A container started withCRON_SCHEDULEset fails fast with a rename message — silently ignoring it would mean no scheduled backups. The scheduled crontab now invokes the synchronous verbs (archiver backup/archiver maintenance), so supercronic sees real job durations and adds its own overlap-skip on top of the pipeline locks. A scheduled deployment withoutMAINTENANCE_SCHEDULEgets a prominent startup warning, and healthcheck warns when any storage has gone more than 8 days without a successful check or prune.ROTATE_BACKUPSwas renamed toPRUNE_BACKUPS(old name still translated silently for old bundle configs, with a startup warning when set as an env var), joined byCHECK_BACKUPS(default true) so shared-storage deployments can disable either phase independently, andPRUNE_EXHAUSTIVE_FREQUENCY(off/daily/weekly/monthly, default monthly): the expensive-exhaustivechunk-listing garbage collection now runs on its own interval per storage instead of on every prune, tracked in a state file and fired belatedly at the next maintenance run if the schedule is sparser than the frequency.archiver maintenance exhaustiveforces it.archiver startandarchiver restartwere removed (they error with guidance):archiver backup --detachis the background form, with the visible already-running refusal. Theprune|retainarguments tobackupwere removed likewise.archiver stoptakes a target:backup,maintenance, orall(default).
Added
archiver maintenance [exhaustive]— the maintenance pipeline verb: per storage,check -all -fossils -resurrect(whenCHECK_BACKUPS) thenprune -allwith the retention policy (whenPRUNE_BACKUPS), recording per-storage last-success timestamps thatarchiver statusdisplays and healthcheck monitors. Also available to external schedulers asrun maintenance(synchronous, exit code propagates).- Secondary copies now run in parallel. Each
duplicacy copyto a secondary is launched concurrently (still direct children, so pause/stop keep working); on an upload-capped link one storage's bandwidth-free destination enumeration overlaps another's upload, so the copy phase approaches max(legs) instead of sum(legs). - Phase durations in the logs: each service backup, each copy, and each check/prune logs how long it took, so slow nights are diagnosable from the summary instead of by archaeology.
Deprecated
- Bundle mode remains supported through 0.10.x.
Fixed
archiver backup --detach(the background form, formerlyarchiver start) now refuses visibly when a backup is already running (non-zero exit and the same "A backup is already running (PID …)" message the synchronous path prints). Previously the dispatcher backgroundedmain.shwith its output discarded and printed the success line unconditionally, so a refused start looked like a successful one. A stale lock (dead PID) still starts normally.- The copy phase now holds the primary storage's lock (as source) for its whole duration, not just each destination's lock, so a maintenance prune can no longer fossilize chunks a concurrent copy is still reading from the primary — closing the one copy-vs-prune overlap the per-storage locks had left open.
- The container clears any leftover pipeline lock and stop-flag files at startup, so a lock left by an unclean prior shutdown can neither fake a live holder (which would refuse every scheduled backup after a PID recycle) nor abort the first backup via a stale stop flag. A stale pipeline lock now reports as a healthcheck warning (self-healing, reaped on the next run) rather than flipping the container UNHEALTHY.
Dependencies
- chore(deps): update docker/login-action action to v4.4.0
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Backups and maintenance are now two independent pipelines. The backup run is hooks → backup → copies, nothing else; storage check and prune moved to a separate maintenance pipeline with its own schedule, lock, and log (