mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
docs(backup): describe manual restore flow (#86971)
* docs(backup): describe manual restore flow * docs(backup): make restore copy-back fail closed * docs(backup): make inspect-and-stage block fail closed Add set -euo pipefail to the first restore staging snippet so a failed openclaw backup verify stops before mktemp/tar extraction, matching the fail-closed copy-back block. Addresses ClawSweeper P1 on docs/cli/backup.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(backup): reconcile restore guidance with exclusions Punchcard-Session: brisk-harbor-harbor-6w * docs(backup): centralize archive restore guidance Punchcard-Session: calm-cedar-workshop-by --------- Co-authored-by: clawSean <260045960+clawSean@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -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/<snapshot-id> --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)
|
||||
|
||||
+99
-12
@@ -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 <snapshot-directory>
|
||||
--target <new-database-path>` 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
|
||||
<archive-root>/manifest.json
|
||||
<archive-root>/payload/posix/<absolute-source-path-without-leading-slash>/...
|
||||
<archive-root>/payload/windows/<DRIVE>/<rest>/...
|
||||
<archive-root>/payload/relative/<relative-source-path>/...
|
||||
```
|
||||
|
||||
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 <snapshot-directory> --target
|
||||
<new-database-path>` 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
|
||||
|
||||
Reference in New Issue
Block a user