Skip to content

breed007/Cryoframe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

16 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Cryoframe

Back up live macOS media libraries into sealed, verifiable archives, on a schedule, without quitting the app that owns the library.

macOS 15+ Β· Apple Silicon Β· MIT licensed

πŸ“– User guide β€” install, jobs, formats, encryption, restoring, and troubleshooting.

Cryoframe main window


The problem it solves

The hard part of backing up a media library is not the copy. It is taking a consistent point-in-time copy of a library whose database is being written to while the backup runs. If you zip a .photoslibrary while Photos has its database open, you can seal a half-written, corrupt database into the archive. The backup looks fine until the day you need it.

Cryoframe avoids that with APFS snapshots. For each run it freezes the volume, mounts the snapshot read-only, archives the library from that frozen copy, then deletes the snapshot. The library stays open the whole time, and the archive is a consistent moment in time.

It also verifies. Every archive gets a checksum manifest, and the strong mode mounts the finished archive and runs a database integrity check, so you find out a backup is bad now instead of during a restore.

Features

  • Consistent snapshots of live libraries using APFS, created and torn down per run.
  • Several libraries per job, archived from one snapshot into their own subfolders, so a job captures a consistent set in a single pass.
  • Several destinations per job (the 3-2-1 rule): a local drive plus a NAS plus a cloud-sync folder, all from the same snapshot. Sealed archives are compressed once and copied to each. The primary must be reached; a downed secondary finishes the run as a partial backup instead of failing it.
  • Three output formats: an incremental sparsebundle mirror that only rewrites the bands that changed (the default), or a sealed zip or DMG β€” immutable, checksummed, split into volumes when the target caps file size.
  • Resumable transfers to network shares and external drives: the archive ships in part files and picks up from the last whole part after a dropped connection or unplugged drive.
  • Restore built in: find an archive, verify it, and copy the library back out with its original folder name β€” beside the live one, or in place over it (staged and verified first, with the old copy moved to the Trash). Browse inside an archive and extract just the files you need.
  • Optional AES-256 encryption for sealed-DMG and live-mirror archives, with the passphrase kept in the Keychain so scheduled runs encrypt without prompting.
  • Versioned sealed archives with a retention policy β€” keep all, the last N, or a daily/weekly/monthly scheme β€” so you can restore a point in time without the disk filling up.
  • Verification built in: a checksum manifest on every archive, plus an optional mount-and-open check that confirms the library's database opens clean.
  • Archive health monitoring: re-hash existing archives against their manifests on demand or on a weekly/monthly schedule, to catch bit rot before a restore needs them β€” works on encrypted archives with no passphrase.
  • Restore drills: a deeper check that reassembles, mounts or extracts, and reopens each archive (a database integrity check), proving the restore path itself works β€” not just that the bytes match.
  • Remote alerts over ntfy or a webhook (Slack/Discord/custom), so an unattended Mac whose backups are failing can push a message to your phone, independent of local notifications.
  • Recovery-key escrow: export every archive passphrase into one master-password-encrypted file (PBKDF2 + AES-GCM), so encrypted backups survive a lost Mac.
  • Storage overview: per-job, per-version sizes against the free space on each destination volume.
  • In-app updates over an Ed25519-signed appcast, and a first-run walkthrough for the helper and Full Disk Access.
  • Targets for local disks, network shares, and cloud-sync folders, each with its own size cap and an availability preflight so a run never starts against an unmounted drive.
  • Cloud-sync aware: detects OneDrive/Dropbox/Google Drive/Box/iCloud folders, splits sealed archives under the plan's single-file limit, and skips offloaded (placeholder) archives during scheduled checks instead of silently re-downloading them.
  • Run jobs concurrently up to a configurable limit, with live progress β€” speed, time elapsed, and time remaining β€” and pause, resume, or stop a run in flight.
  • Durable run history: every run, manual or scheduled, is recorded with its outcome, per-library detail, duration, size, and any error, and survives quitting the app.
  • Scheduling through a launchd agent, with per-job control over what happens if the owning app is open.
  • Keeps the Mac awake while a backup runs, and can optionally wake it for a scheduled run, so unattended backups actually finish.
  • A menu-bar status item and notifications, so you know at a glance whether the last run β€” including scheduled ones β€” succeeded.
  • Owns its snapshots end to end. It never touches Time Machine's snapshots.

Supported libraries

Built in (fixed locations, detected automatically):

Library Location Owning app
Photos ~/Pictures/Photos Library.photoslibrary Photos
Apple Music ~/Music/Music/Music Library.musiclibrary Music
iMovie ~/Movies/iMovie Library.imovielibrary iMovie
GarageBand ~/Music/GarageBand GarageBand
Messages ~/Library/Messages Messages
Mail ~/Library/Mail Mail
Microsoft Outlook default Outlook profile Outlook

Built-in library picker

Templates (you point at the library, since these live anywhere β€” often on external drives):

  • Final Cut Pro libraries
  • Lightroom Classic catalogs
  • Capture One catalogs
  • Logic Pro projects

Library templates for Final Cut, Lightroom, Capture One, and Logic Pro

Anything else: point at any folder with "Add library", and it is treated as static content.

A built-in library kept somewhere other than its default location β€” an external drive, say β€” can be repointed in Settings β–Έ Libraries. The owning app and integrity check stay attached.

Install

Download

Grab Cryoframe-x.y.z.dmg from Releases. It is signed with a Developer ID and notarized, so it opens with no Gatekeeper warnings. Open the DMG and drag Cryoframe to Applications.

Build from source

brew install xcodegen
git clone https://github.com/breed007/Cryoframe.git
cd Cryoframe
xcodegen generate
open Cryoframe.xcodeproj

Set DEVELOPMENT_TEAM in project.yml to your own Team ID first β€” the privileged helper will not register without a Developer ID. The .xcodeproj is generated and gitignored; edit project.yml, never the project file. To build, sign, and install in one step:

./scripts/build-and-install.sh

First run

Three one-time steps, shown at the top of the window:

  1. Enable the helper. This installs the background service that takes snapshots. Approve it in System Settings β–Έ Login Items when asked, and authenticate (installing a root service needs admin).
  2. Grant Full Disk Access to Cryoframe, then relaunch. The dot turns green once it can read protected libraries. Full Disk Access is required because a snapshot of Photos content is still Photos content as far as macOS privacy controls are concerned.
  3. Enable the schedule if you want jobs to run in the background.

Using it

Press New Job and pick a library, a destination, a format, and how often to run. Every field has a tooltip.

Choosing a destination: local or cloud-sync folder

Formats:

  • Live mirror (default). A sparsebundle with about 8 MB bands. The first run copies everything; later runs only write the bands that changed.
  • Sealed zip or DMG. One immutable, checksummed file for cold storage. Larger than the target's cap splits into volumes, so it fits cloud single-file limits.

Archive format options: sealed DMG, sealed zip, or live mirror

Verification:

  • Checksum hashes every archive after writing. Always on. A manifest (cryoframe-manifest.json) is written next to the archive.
  • Mount and open also mounts the finished archive and runs a SQLite integrity check on the library's database. This is the strong check for live-database libraries.

Schedule and run policy:

  • Daily at a set time, every N hours, once, or manual.
  • "If app is open" controls what happens when the owning app is running. The default is proceed, because the snapshot is already consistent. Choose warn or defer if you would rather skip a run while the library is in use.

The Help button in the app has worked examples for Apple Photos and Apple Music.

How it works

  app (you, Full Disk Access)              helper (root LaunchDaemon)
  ───────────────────────────              ──────────────────────────
  create snapshot          ──── XPC ────▢  freeze the Data volume
  mount snapshot           ──── XPC ────▢  mount read-only
            ◀──── MountRef ────────────
  read the frozen library, archive it
  unmount + delete         ──── XPC ────▢  tear down

The privilege split is the core of the design. A root helper takes, mounts, and deletes the snapshot. The app reads the frozen library and writes the archive, running as you with Full Disk Access. Root does not bypass macOS privacy controls, so the reader needs Full Disk Access; the helper rides the app's grant for the snapshot mount.

Snapshot create runs through tmutil localsnapshot, which needs no special entitlement. The raw fs_snapshot_create syscall would need an Apple-granted entitlement that root alone does not satisfy, so Cryoframe uses the path that works for everyone. The snapshot is mounted immediately after creation, which pins it for the run regardless of how Time Machine thins its own snapshots.

Project layout

  • CryoframeShared β€” the XPC contract and shared types
  • CryoframeKit β€” the engine: snapshot backends, content-type registry, archive engines, verification, targets, scheduling (covered by unit tests that run with fakes, so no root or snapshot is needed)
  • CryoframeHelper β€” the root LaunchDaemon
  • Cryoframe β€” the SwiftUI app
  • spike/ β€” the throwaway spikes that proved the snapshot and syscall approach
  • docs/guide/ β€” the user guide; docs/ also holds design notes
  • scripts/ β€” build, install, icon, notarize, and DMG scripts

Building and testing

xcodegen generate
xcodebuild test -scheme Cryoframe-Core -destination 'platform=macOS'

The engine is fully unit-tested without root. The archive and strong-verify tests shell out to hdiutil, ditto, and sqlite3 against tiny fixtures, so the suite takes about half a minute.

Releasing

Maintainer steps to cut a notarized release:

xcrun notarytool store-credentials cryoframe-notary \
    --apple-id <your-apple-id> --team-id <your-team-id> --password <app-specific-password>   # once
./scripts/notarize.sh        # signed Release build, notarize, staple the app
./scripts/make-dmg.sh        # wrap in a DMG, notarize and staple the DMG

The build number is stamped with the build time as YYYYMMDD.HHMM on every build. The marketing version is set by hand in project.yml (MARKETING_VERSION).

Security notes

Cryoframe runs a root LaunchDaemon and reads protected libraries, so it asks for real trust. What it does and does not do:

  • The helper runs as root only to create, mount, and delete APFS snapshots. It never reads library contents.
  • The app and helper verify each other's code signature on every XPC connection, so only the signed app can talk to the helper.
  • Cryoframe writes archives to wherever you point it. It does not upload anything. Cloud backup happens because you wrote the archive into a cloud-sync folder and the sync client uploads it.

Not in scope

  • Intel or universal builds. Apple Silicon only.
  • The Mac App Store. The root helper, Full Disk Access, and snapshot mounts are incompatible with the App Sandbox.
  • A built-in cloud uploader (direct S3/OAuth). Write to a cloud-sync folder instead β€” Cryoframe detects the provider and splits to its single-file limit.

License

MIT. See LICENSE.

About

Back up live macOS media libraries (Photos, Apple Music, Final Cut, and more) into sealed, verifiable archives using APFS snapshots, on a schedule.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors