diff --git a/docs/cli/backup.md b/docs/cli/backup.md index 5570bfbf1f6e..9d090d5bec1b 100644 --- a/docs/cli/backup.md +++ b/docs/cli/backup.md @@ -4,6 +4,7 @@ read_when: - You want a first-class backup archive for local OpenClaw state - You need a compact, verified snapshot of one OpenClaw SQLite database - You want to preview which paths would be included before reset or uninstall + - You want to restore from a `.tar.gz` archive previously created by `openclaw backup` title: "Backup" --- @@ -30,6 +31,8 @@ openclaw backup sqlite restore ~/Backups/openclaw-sqlite/ --target Archive `create` and `verify`, plus SQLite `create`, `list`, `verify`, and `restore`, accept `--json` for one machine-readable result on stdout. +OpenClaw does not currently provide an `openclaw backup restore` command. Follow [Restore a full archive](/install/backups#restore-a-full-archive) for the manual, manifest-driven copy-back flow. + ## Notes - The archive embeds a `manifest.json` with the resolved source paths and archive layout. @@ -138,3 +141,5 @@ Large workspaces are usually the main driver of archive size. Use `--no-include- ## Related - [CLI reference](/cli) +- [Migrating an OpenClaw install](/install/migrating) +- [Restore a full archive](/install/backups#restore-a-full-archive) diff --git a/docs/install/backups.md b/docs/install/backups.md index 87ad6b556c68..2778053261e9 100644 --- a/docs/install/backups.md +++ b/docs/install/backups.md @@ -140,19 +140,106 @@ encryption rules. ## Restore -Restore is deliberately explicit; nothing overwrites a live database in -place: +Restore is deliberately explicit; nothing overwrites live state in place. -1. Stop the Gateway. -2. For archives: extract into a staging directory and follow the - `manifest.json` source-to-archive mapping to put files back; see - [Updating](/install/updating#rollback) for the rollback workflow. -3. For snapshots: `openclaw backup sqlite restore ---target ` writes a re-verified database to a fresh - target. Move it into place while the Gateway is stopped. -4. For Litestream: `litestream restore` writes a fresh database file; move it - into place the same way. -5. Start the Gateway and check `openclaw health` and `openclaw doctor`. +### Restore a full archive + +Start only from an archive you created or otherwise trust. `openclaw backup +verify` checks archive structure and payload layout, but it does not +authenticate the archive or make untrusted content safe. + +Before a full restore, review [What gets backed +up](/cli/backup#what-gets-backed-up). Archives intentionally omit volatile +files, plugin dependency trees, and installer-managed runtime roots such as +state-local `tmp/`. Recreate those artifacts after restore. + +Verify before extracting, then stage the archive in a private temporary +directory: + +```bash +set -euo pipefail + +ARCHIVE=./2026-03-09T08-00-00.000+08-00-openclaw-backup.tar.gz + +openclaw backup verify "$ARCHIVE" + +restore_dir="$(mktemp -d -t openclaw-restore.XXXXXX)" +trap 'rm -rf "$restore_dir"' EXIT + +tar -xzf "$ARCHIVE" -C "$restore_dir" +manifest_path="$(find "$restore_dir" -mindepth 2 -maxdepth 2 -name manifest.json -print -quit)" +test -n "$manifest_path" +cat "$manifest_path" +``` + +Treat the staging directory as sensitive. It can contain credentials, auth +profiles, sessions, and workspace data. The `trap` removes it when the shell +exits. + +The manifest records `archiveRoot`, the original paths under `paths`, and an +`assets[]` list. Each asset includes its `kind`, original `sourcePath`, and +`archivePath` inside the tarball. Use those fields as the source of truth; do +not derive the archive root from the archive filename. + +The archive layout is: + +```text +/manifest.json +/payload/posix//... +/payload/windows///... +/payload/relative//... +``` + +Before copying files back, stop the Gateway and any node hosts that use them. +Make a fresh backup of the current state or move the current directories +aside. Restore the smallest set of assets needed. + +For example, this restores the state asset to the current user's default +state directory. The target stays absent until `cp -a` creates it, preserving +the staged directory's mode and metadata: + +```bash +set -euo pipefail + +state_archive_path="$( + node -e 'const fs = require("node:fs"); const manifest = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); process.stdout.write(manifest.assets.find((asset) => asset.kind === "state")?.archivePath ?? "");' "$manifest_path" +)" +test -n "$state_archive_path" + +state_source="$restore_dir/$state_archive_path" +state_target="$HOME/.openclaw" +state_backup="$HOME/.openclaw.pre-restore.$(date +%s)" + +test -d "$state_source" +openclaw gateway stop + +if [ -e "$state_target" ] || [ -L "$state_target" ]; then + mv "$state_target" "$state_backup" +fi +test ! -e "$state_target" +test ! -L "$state_target" +cp -a "$state_source" "$state_target" + +openclaw doctor +openclaw gateway start +openclaw health +openclaw status +``` + +For a same-machine restore, the manifest `sourcePath` values are usually the +intended targets. On a new machine or under a different home directory, +choose the new targets first, then copy only the matching asset payloads. +Typical full-restore targets are the state directory, active config file, +credentials directory, and workspace directories. See +[Updating](/install/updating#rollback) for the rollback workflow. + +### Restore a database + +For a snapshot, `openclaw backup sqlite restore --target +` writes a re-verified database to a fresh target. For +Litestream, `litestream restore` writes a fresh database file. Move either +result into place while the Gateway is stopped, then start the Gateway and +check `openclaw health` and `openclaw doctor`. After restoring onto a different OpenClaw version, preflight the database first with `openclaw database preflight`; see