Skip to content

Non-destructive ARA and AdGuard recovery preparation — 2026-10-24

PR #472 merged the deployment evidence for the first two repairs. Their recovery acceptance remains open. PR #473 addresses REC-002 and REC-003 in source: correct recovery paths and removal of destructive live-volume restore examples. No live preparation or application recovery was performed.

What changed

  • ARA selects the exact nested _data directory from its snapshot, not the outer restic staging tree. The operator supplies the reviewed SQLite-relative path; no database filename is guessed.
  • AdGuard selects only its backed-up configuration volume. Work/query history is not protected by this backup policy, and the archived unbound.conf is not mounted by current Compose. Neither is selected for preparation.
  • A shared preparer defaults to a filesystem-only JSON plan with zero Docker calls. Explicit --prepare may populate only a new labelled recovery volume, after destination/ownership/attachment checks and an empty-target gate.
  • Copying uses a vetted, preloaded digest-pinned utility image, strict read-only source mounting, no network and no implicit image pull. Existing volumes and running services are not changed. Failed/partial recovery volumes are retained.
  • Production cutover remains a separate reviewed change to both GitOps volume mapping and backup paths, with original volumes retained for rollback.

The required utility is GNU cp supporting --update=none-fail (introduced in coreutils 9.5), not generic BusyBox cp. A successful preparation is not SQLite integrity, AdGuard DNS correctness, content/metadata fidelity or recovery acceptance. Trusted stable staging, a trusted local daemon/image, and sufficient storage headroom remain explicit prerequisites.

Validation boundary

Tests use synthetic staged files and fake Docker, covering exact source selection, plan-only refusal to invoke Docker, existing/raced/nonempty/attached destinations, image and endpoint checks, and retained failure data. Separate tests execute the actual fixed shell/copy command with installed GNU cp: hidden files and ordinary modes are preserved, nonempty targets are refused, and conflicting files are not overwritten. This is not a real Docker mount or application restore test.

Independent review found no blocker within the documented trust boundary. Exact commands, local results and limitations are retained privately; check PR #473's exact-head CI before merging. Prior source, deployment and failed-check records remain unchanged.

Phase status and next gates

Concern Status in this slice Remaining gate
REC-001 / INC-002 / OPS-043 Previously observed deployed New local/offsite recovery sets and isolated application integrity/rollback
INC-003 Previously observed deployed Trusted relocated artifacts and isolated application recovery
REC-002 / REC-003 Source implementation under review Exact-head CI, reviewed deployment, approved real preparation and application/rollback checks
Other 249 groups Backlog Separately scoped repairs and evidence
flowchart TD
    Stage[Reviewed snapshot staging] --> Plan[Filesystem-only preparation plan]
    Plan --> Approval[Owner approves image, daemon, storage and destination]
    Approval --> Prepare[Populate a new recovery volume only]
    Prepare --> Validate[Isolated application and metadata validation]
    Validate --> Review[Separate GitOps and backup-path cutover review]
    Review --> Accept[Owner acceptance and rollback retention]

Operating guides: ARA restore, AdGuard restore, and the private registry linked from the repository README. The shared checkout was left untouched; work used an isolated worktree from merged main. No backup, live Docker operation, service restart, restore, cleanup, credential decryption or merge was executed by this source-repair session.