mehendocs

GuidesBack up a machine before adopting

Back up a machine before adopting#

How do I keep my own copy of every file mehen adopt reads, so Mehen is never the only copy?

On this page

Before mehen adopt submit sends anything, take a snapshot: one encrypted archive of every file the adopt plan names, byte for byte, with its permissions and times. It is encrypted with age, a small and widely packaged encryption tool, to a key whose private half is on no enrolled machine, and stock age opens it without Mehen. Every mehen backup command runs offline: none talks to the vault.

1. Make the key on another machine#

Make the backup key on a machine no agent uses, not on the machine you are adopting from:

mehen backup keygen --out ~/mehen-backup-key.txt

It writes a new age identity (mode 0600) and prints only its public half, the recipient, a line starting age1. It never writes over a file, and refuses a path under your mehen root or inside a git work tree. On an enrolled machine it refuses unless you add --on-enrolled-machine, because an agent there could read the key. age-keygen -o ~/mehen-backup-key.txt makes the same kind of key and prints the recipient as Public key: age1....

Only plain X25519 recipients work: not post-quantum (age1pq1...), plugin or SSH ones.

2. Keep the private key safe#

The identity file holds one line starting AGE-SECRET-KEY-1. Whoever has it can open every snapshot made to it.

The recipient (age1...) is not secret: copy it to the machine you are adopting from.

3. Take the snapshot#

On the machine you are adopting from, after mehen adopt plan and before mehen adopt submit:

mehen backup snapshot --plan ~/.config/mehen/adopt/<machine>/plan.json --to ~/Backups/mehen --recipient age1...

It reads every file the plan names (each source, each service's unit and env file, each repo's existing mehen.toml) and the plan itself. Give --recipient more than once to encrypt to several keys, or set MEHEN_BACKUP_RECIPIENTS to a comma-separated list instead.

Copy both files off the machine. To read one file back without Mehen:

age -d -i key.txt snp_4fQ9cR2mT7.age | jq -r '.files[] | select(.path == "/Users/sam/code/api/.env") | .content' | base64 -d

4. Check it#

mehen backup check ~/Backups/mehen/snp_4fQ9cR2mT7.age

No key needed. It compares the archive's length and SHA-256 with the sidecar beside it, and checks the age header has one stanza per recipient plus the self-check's. That catches a truncated, damaged or swapped file. It cannot prove which key the archive is for, because age hides that by design: only opening it with your key does. Do that once, on the key machine, with --verify-only below.

5. Restore#

mehen backup restore takes the identity from a file with --identity <file>, or from stdin with --identity - (for example piped from your password manager's command line), never as an argument. It refuses an identity file other users can read. Run it on the machine that holds the key; on an enrolled machine it refuses unless you add --on-enrolled-machine, and you should remove the key from that machine when you are done.

Exactly one of three modes:

mehen backup restore ~/Backups/mehen/snp_4fQ9cR2mT7.age --identity - --verify-only
mehen backup restore ~/Backups/mehen/snp_4fQ9cR2mT7.age --identity key.txt --to ~/mehen-restore
mehen backup restore ~/Backups/mehen/snp_4fQ9cR2mT7.age --identity key.txt --in-place

Restored files never keep a setuid or setgid bit.

Why submit needs the snapshot#

Adopt never moves, rewrites or deletes an original, but once your credentials are in the vault you will start removing the files by hand. The snapshot is your way back that does not depend on Mehen: taken before anything was sent, encrypted to a key no agent can reach, and opened by a tool you can install anywhere. So mehen adopt submit refuses, and sends nothing, until a passed snapshot on this machine holds every file the plan names, with none changed since. There is no flag to skip it. Each machine needs its own snapshot, --join included, and a new one whenever you plan again or a planned file changes.