Skip to content

feat(backup): backup stacklet v1: append-only sync to attached APFS disk#17

Open
arthware-dev wants to merge 6 commits into
mainfrom
feat/backup-cli-only
Open

feat(backup): backup stacklet v1: append-only sync to attached APFS disk#17
arthware-dev wants to merge 6 commits into
mainfrom
feat/backup-cli-only

Conversation

@arthware-dev

Copy link
Copy Markdown
Contributor

Summary

  • New backup stacklet: append-only sync of photos (Immich originals) and documents (Paperless PDFs) to an attached APFS disk. Files are locked with the kernel uchg flag once on the disk, so accidents and ransomware cannot reach back through.
  • stack backup sync / stack backup status ship as the user-facing CLI. stack up backup walks setup (disk, encryption, nightly time), plants the canary, installs a cron entry, and points the user at the one-time /usr/sbin/cron Full Disk Access grant in System Settings.
  • Manifest contract: [[backup.archive]] declared by photos and docs. Reserved for follow-up: [[backup.snapshot]] for DB dumps, stack backup restore + per-stacklet on_restore hooks, encrypted offsite via restic.

@arthware-dev arthware-dev changed the title feat(backup): backup stacklet — append-only sync to attached APFS disk feat(backup): backup stacklet: append-only sync to attached APFS disk May 15, 2026
@arthware-dev arthware-dev marked this pull request as draft May 15, 2026 14:58
@arthware-dev arthware-dev changed the title feat(backup): backup stacklet: append-only sync to attached APFS disk feat(backup): backup stacklet v1: append-only sync to attached APFS disk May 15, 2026
@arthware-dev arthware-dev marked this pull request as ready for review June 15, 2026 12:25
Append-only backup of stacklet data to an attached APFS disk. Photos
(Immich originals) and documents (Paperless archived PDFs) sync
nightly via cron; every file is locked with the kernel uchg flag once
on the vault, so accidents and ransomware cannot reach back through.

Stacklet:
* host-type stacklet, opt-in via 'stack up backup'
* interactive on_configure prompts for disk, encryption, nightly time
* on_install plants the canary tripwire, generates an FDA-granted .app
  wrapper, installs the cron entry
* on_stop / on_destroy remove the cron defensively; vault data and
  the Keychain entry are preserved

External-disk engine:
* rsync --ignore-existing for append-only writes
* chflags uchg on every new file (kernel-enforced immutability)
* canary + preflight refuse to sync a wiped source
* filesystem probe refuses non-APFS targets at runtime
* per-run JSON appended to history.jsonl (append-only audit trail)

Orchestrator:
* discovers [[backup.archive]] across enabled stacklets
* posts summary to #famstack via stacker-bot

Reserved for follow-up: [[backup.snapshot]] for DB dumps,
'stack backup restore' + per-stacklet on_restore hooks, encrypted
offsite via restic.

Tests: 153 unit + 9 E2E against a real APFS sparse image.
@arthware-dev arthware-dev force-pushed the feat/backup-cli-only branch from 58df414 to 18704d2 Compare June 15, 2026 12:44
@arthware-dev arthware-dev changed the base branch from v0.3-beta to main June 15, 2026 12:58
Dry-run previously reported "0 total, 0 new" because the engine skipped
file counting when no files were written. Now parses rsync --stats output
for the transferred count and displays "N files would be written to
backup archive" per source. Adds bold "Dry run, nothing synced!" footer.
…ications

Cron's minimal PATH finds the system Python (3.9), which is too old.
Prepend /opt/homebrew/bin so the nightly sync finds Homebrew Python.
Also switch notification source lines from em-dashes to colons.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant