how-to
Back up and restore
Back up and restore
What this guide does
Configure backups for an deputyOS device, take an immediate snapshot,
schedule a recurring snapshot, list snapshots in your bucket, and
restore from a snapshot id. deputyOS uses rclone as the data plane
(any rclone-supported remote works: S3, B2, Google Drive, OneDrive,
SFTP, …) and a small TOML file at /etc/deputyos/backup.toml plus an
rclone.conf as the control plane.
Snapshots cover the active profile’s data_dir — for OpenClaw,
Hermes, and Khoj this means chat history, embeddings, vector indexes,
and per-skill state. They do not cover provider keys
(secrets.env) — those live in your password manager / secret store
of record.
Prerequisites
- A working deputyOS device with the wizard finished.
- A reachable rclone-supported remote — S3 bucket, B2 bucket, GCS, OneDrive folder, SFTP server, …
- Either rclone configured during the wizard, or knowledge of the remote’s auth (so you can configure it post-wizard).
The recipe
1. Configure during the wizard’s backup step
The wizard’s backup step (route /wizard/backup — see
Reference → APIs → wizard HTTP)
prompts for:
- The rclone-style remote spec —
<remote-name>:<bucket-or-path>. - Optional retention in days (default: keep all).
The apply step writes:
-
/etc/deputyos/backup.toml(mode0644):[backup] remote = "<name>:<bucket>" retention_days = 30 -
/etc/deputyos/rclone.conf(mode0600, owneragent:agent) — the rclone config the wizard collected.
2. Or configure post-wizard
sudo install -m 0644 /dev/null /etc/deputyos/backup.toml
sudo tee /etc/deputyos/backup.toml >/dev/null <<'EOF'
[backup]
remote = "deputyos-bucket:deputyos-snapshots"
retention_days = 30
EOF
# rclone.conf — generated by `rclone config` on a workstation, then copied.
sudo install -m 0600 -o agent -g agent /tmp/rclone.conf /etc/deputyos/rclone.conf
3. Take an immediate snapshot
sudo deputyctl backup now
deputyctl backup now runs:
rclone --config /etc/deputyos/rclone.conf sync \
<data_dir> <remote>:<bucket>/<host>-<utc-iso>/
The snapshot id is <hostname>-<utc-iso>, filename-safe.
Preview without uploading:
sudo deputyctl backup now --dry-run
4. Schedule a recurring snapshot
sudo deputyctl backup schedule --every 6h # every 6 hours
sudo deputyctl backup schedule --at 02:00 # daily at 02:00 local
deputyctl backup schedule writes a systemd timer + service:
deputyos-backup.timer—OnCalendar=…orOnUnitActiveSec=….deputyos-backup.service—ExecStart=/usr/local/bin/deputyctl backup now.
Inspect and remove:
sudo deputyctl backup schedule --list
sudo deputyctl backup schedule --disable
In dev mode (DEPUTYOS_DEV_OUT=<dir>), the timer/service files are
written under <dev-out>/systemd/ and daemon-reload is skipped, so
contributors can exercise the wiring without root.
Restoring
1. List snapshots
sudo deputyctl restore list
sudo deputyctl restore list --json
Prints one row per snapshot: id, size, last-modified, plus a
human-friendly age (3h ago, 2d ago).
2. Restore a snapshot
sudo deputyctl restore snapshot --snapshot <id> --yes
The restore is atomic with a pre-restore safety copy. The flow:
- Stop the active profile (
deputyctl down). - Create a safety copy at
<data_dir>.pre-restore-<utc-iso>/. rclone sync <remote>:<bucket>/<id>/ <data_dir>/.- Start the active profile (
deputyctl up).
If step 3 fails, the safety copy is renamed back to <data_dir> and
the unit restarts on the original data. If step 4 fails, the safety
copy is preserved next to the (broken) data dir for forensics.
The safety copy is kept by default — deputyctl factory-reset is
the only command that removes it. Sweep periodically:
sudo find /home/agent/.<profile>.pre-restore-* -maxdepth 0 -mtime +14 \
-exec rm -rf {} +
Verification
# Take a dry-run; rclone reports what *would* be uploaded.
sudo deputyctl backup now --dry-run
# After a real run, list to see your fresh snapshot.
sudo deputyctl restore list
# Round-trip on a test device:
sudo deputyctl backup now
sudo deputyctl restore list
sudo deputyctl restore snapshot --snapshot <id> --yes
sudo deputyctl status # active profile is back up
Failure modes
| Failure | Symptom | Recovery |
|---|---|---|
| rclone not on PATH | backup now exits 127 | apt install rclone (the bake usually does this; check if the image is degraded) |
| remote credentials expired | rclone exits with auth error | Re-run rclone config on a workstation; reinstall /etc/deputyos/rclone.conf |
| destination full | rclone exits with quota error | Free space at the remote; deputyctl backup now is idempotent |
| network down mid-restore | restore exits non-zero, safety copy survives | Pre-restore data is at <data_dir>.pre-restore-<ts>/; mv it back, then investigate |
| restore from unrelated profile | data dir contents mismatch the running gateway | Stop the gateway, restore the right snapshot, restart |
Troubleshooting
Snapshot upload silently exits 0 but bucket is empty rclone’s exit code is the source of truth, but your remote may be misconfigured (wrong bucket, wrong region, IAM denies put). Run
rclone --config /etc/deputyos/rclone.conf lsd <remote>:<bucket>to confirm the credentials work end-to-end.
Restore puts data back but channels stop working Channel-specific tokens (Telegram, Slack, Matrix) live in
/etc/deputyos/<profile>/channels.d/, NOT in the data dir. They are not part of the snapshot. After restore, re-run the wizard’s channels step or copy the env files manually.
Restoring an old snapshot rolls back the upstream agent No — the agent binary is in the image at
/opt/deputyos/profiles/<id>/, not in the data dir. The restore only touchesdata_dir(~/.<id>/). The agent binary stays at the version the current image baked. If the data schema changed incompatibly between versions, the agent’s startup migration handles it (or fails loudly). Test restores in a non-production flow first.
Run
backup nowbefore every update Update is staged-only today but a snapshot beforedeputyctl update --applyis the safest rollback path. Wire it as a pre-update hook if you script updates.
Related
- Reference → CLI → deputyctl (
backup,restoresubcommand trees) - Reference → APIs → wizard HTTP (the
/wizard/backuproute) - Operations → Update and rollback
- Security → Secrets storage