Backups & Migration
Backup/restore, per-profile export, whole-instance migration, and upgrades.
Backup & restore
./deploy/backup.sh # /var/backups/aios/aios-<stamp>.tar.gz (keeps 14)
./deploy/restore.sh <archive> # stops services, safety-snapshots current
# state, restores, restarts
Everything that matters lives in /root/.aios — one archive is a full
recovery point. Cron it nightly. The license signing key
(/root/.aios-license-keys/) deserves its own off-server copy.
The vault in backups and upgrades
Secrets live in the encrypted vault: secrets.db plus a
vault key (KEK) kept outside it. What that means for recovery:
- Both
secrets.dband the owner-read-only.kekvault-key file live inside the AIOS home — the same on every platform — so a whole-home archive is a complete recovery point, secrets included. Anyone holding the archive holds the vault key too — treat backups accordingly. aios secrets kek-backup <file>(passphrase-wrapped, Argon2id) is the offline copy of the vault key: store it away from the box so a lost or corrupted home can never lock you out;aios secrets kek-restoreputs it back. Afteraios secrets rotate-kek, the previous kek-backup no longer opens the store — take a fresh one.- The Keys page’s Export panel (or
aios secrets export --with-secrets) is a lighter alternative when you only need the keys themselves: an Argon2id-passphrase-wrapped bundle you can re-import anywhere. - Upgrading a pre-vault install: the first vault-era
aios update applyimports plaintext.env/license.jsonfiles into the vault and renames them*.migrated. The import is one-way — nothing reads the plaintext files afterwards. Preview withaios doctor --pre-secrets.
Self-service per-profile export (no root/SSH needed)
The backup above is whole-server and needs root. For exporting just one profile’s data — the thing a managed-hosting customer without shell access can actually do themselves:
POST /api/profile/backup?profile=<name> # builds a tar.gz server-side
GET /api/profile/backup # list built archives
GET /api/profile/backup/download?filename=<name> # fetch one
POST /api/profile/restore?profile=<name> # raw tar.gz bytes as the body
No dashboard page for this yet (API only). Credential files (the
encrypted secrets.db, credentials_pool.json, and any pre-vault
.env / .migrated leftovers) are excluded by default — pass
include_credentials=true to the POST /api/profile/backup call if
you need them in the export. The vault key (.kek) is never
exported by this route, opt-in or not. Bound by the app’s 25MB body-size cap; a
profile with a very large sessions.db can’t round-trip through this
route yet — use the whole-server backup above for those.
Migrating a whole instance
To move everything (every profile, kanban, credentials, hooks) to a
different machine — or to bootstrap a brand-new machine from an existing
instance’s data, standing in for aios setup:
aios migrate export --out ~/aios-backup.aiosmig # or: --github owner/repo
aios migrate import --from ~/aios-backup.aiosmig --home ~/.aios
# or: --github owner/repo@tag
Always encrypted (ChaCha20-Poly1305, passphrase-derived key) — you’re
prompted for a passphrase if you don’t pass --passphrase or set
AIOS_MIGRATE_PASSPHRASE (the prompt isn’t hidden yet, it’ll echo as you
type). A wrong passphrase or a corrupted archive fails loudly rather than
silently producing garbage. import refuses to touch a destination that
already has data unless you pass --force — but works exactly as well
against an empty or nonexistent --home, which is what makes it double
as a fresh-install path. The --github target uploads/downloads the
encrypted archive as a Release asset via the gh CLI (needs gh auth login done on both ends) — use a private repo, since the encryption
protects the contents but not the fact that a release exists.
Unlike the per-profile export above, credentials are included by
default here — the whole point of a migration is a working replacement
instance. The archive packs the whole AIOS home — secrets.db and the
.kek vault key included, on every platform — so the destination
decrypts the vault with nothing extra to carry.
Upgrades
Install the new release’s binaries, then re-run provision.sh (idempotent
— it refreshes units and binaries without touching config/data), then
./deploy/e2e.sh <apex> to verify. Take a backup first.