Last updated: March 2026 Β· Source: openclaw-backup
Encrypted State Archive
Automated encrypted, deduplicated backup of the OpenClaw workspace and local projects to Google Drive β using restic for encryption and snapshot management, rclone for transport, with the encryption password stored in macOS Keychain.
What
openclaw-backup creates incremental, encrypted, point-in-time snapshots of the OpenClaw workspace and local project directories and stores them on Google Drive. Each backup run adds a new snapshot; unchanged blocks are deduplicated so only changed data is uploaded. A retention policy automatically prunes old snapshots. The encryption password never touches disk β it's retrieved from macOS Keychain on each run.
Why
An agent system accumulates state that's difficult to reconstruct: memory files built up over months of sessions, project code in progress, configuration that took time to tune. Disk failure, accidental deletion, or a corrupted workspace without backups means complete loss of that state.
Standard cloud sync tools (iCloud, Dropbox) don't encrypt before upload, don't track snapshot history, and don't deduplicate. A user can't restore to "the state of my workspace three days ago" β only to the current synced state. restic solves all three problems: client-side encryption (Google Drive only ever sees ciphertext), content-addressed deduplication (fast incrementals), and immutable point-in-time snapshots with a configurable retention policy.
Architecture
Two layers collaborate on each backup run:
restic β encryption + deduplication + snapshot management
restic creates content-addressed, encrypted snapshots. Only changed blocks are stored; unchanged blocks reference existing data. The encryption password is read from macOS Keychain on each run β never written to disk.
rclone β Google Drive transport
rclone provides the backend that restic writes to. It handles Google Drive OAuth and the file transfer layer. The OAuth token lives in a config file that is excluded from git.
~/.openclaw/ βββ
ββββΆ restic (encrypt + dedup) βββΆ rclone βββΆ Google Drive
~/projects/ βββ What gets backed up:
| Path | Approx Size | Contents |
|---|---|---|
| ~/.openclaw/ | ~2.9 GB | Config, workspace, memory files, logs, media |
| ~/projects/ | ~1.3 GB | Source code, experiments |
Exclusions (not backed up):
node_modules/β reinstallable from package.json.venv/β recreatable Python environmentsbrowser/β Chromium binary cache.git/objectsβ already on GitHub
Retention policy:
| Period | Kept |
|---|---|
| Daily | Last 7 days |
| Weekly | Last 4 weeks |
Older snapshots are automatically pruned at the end of each backup run.
Key Design Decisions
restic over tar/zip β content-addressed deduplication
restic splits files into variable-size chunks and identifies them by content hash. Only chunks that don't already exist in the repository are uploaded. This makes incremental backups fast β a session where only memory files changed uploads only those chunks, not the full 4 GB workspace.
macOS Keychain β password never on disk
The restic encryption password is stored in Keychain under a service/account key pair. The backup script retrieves it at runtime using the security CLI. No plaintext password ever appears in a config file, environment variable export, or shell history.
Active secret scanning in test.sh
The test script actively scans all git-tracked files for patterns that look like secrets (API keys, tokens, passwords). This runs before any backup to prevent accidentally committing credentials alongside the backup infrastructure code.
Immutable snapshots β never overwrite, always prune
Each backup run adds a new snapshot to the repository. Old snapshots are removed only by the retention policy pruning step, not by overwriting. At any point you can restore to any snapshot in the retention window β not just the most recent one.
How to Build Your Own
1. Use restic with any rclone-supported backend
The same architecture works with any rclone backend: S3, Backblaze B2, Azure Blob, SFTP. Google Drive is used here because it's free up to 15 GB and requires no credit card. Swap the rclone remote name in the backup script to change backends.
2. Store the encryption password in a system secrets manager
On macOS, Keychain is the right choice. On Linux, use pass (GPG-backed) or the RESTIC_PASSWORD environment variable set by a secrets manager at runtime. Never store the password in a dotfile.
3. Build a comprehensive exclusion list
node_modules, Python virtualenvs, browser caches, and compiled output can easily add several gigabytes that are fully reinstallable. Exclude them. A good rule: if a directory can be recreated from committed source (package.json, requirements.txt, etc.), exclude it.
4. Test your restore process before you need it
A backup that has never been tested is not a backup. Include a dry-run restore in your testing checklist. Restore to a temporary directory and verify that key files are present and intact. The worst time to discover a broken restore process is during an actual recovery.
5. Fire a system event notification on backup failure
Silent backup failures are the most dangerous kind. The backup script should send a notification (via OpenClaw system event, email, or any other channel you'll actually see) when a backup fails. A successful backup should log silently; a failure should be loud.
Security
- No hardcoded secrets β all credentials use macOS Keychain or environment variables
- restic encrypts all data before upload; Google Drive stores only ciphertext
- OAuth tokens in rclone config are excluded from git via .gitignore
- test.sh actively scans for secrets in all git-tracked files
Frequently Asked Questions
Where is the restic encryption password stored?
In macOS Keychain under service name openclaw-backup, account restic-password. The setup script generates and stores it automatically. You can also override it with the RESTIC_PASSWORD environment variable.
Will backups overwrite each other?
No. restic creates immutable snapshots. Each backup run adds a new snapshot; old ones are only removed when the retention policy prunes them. You can restore to any historical snapshot within the retention window.
Does this work on Linux?
The Keychain integration is macOS-specific. On Linux you would need to substitute a different secret store (e.g. pass) or use the RESTIC_PASSWORD environment variable directly. The restic and rclone commands themselves are cross-platform.
Authors: Qiushi Wu & Orange π