If you want to reinstall OpenClaw cleanly, do not copy the entire ~/openclaw directory into the new installation.
The application source can be cloned again. The valuable state is the configuration and runtime data under ~/.openclaw, plus deployment-specific files such as ~/openclaw/.env.
For a Docker-based OpenClaw install on an Azure VM, preserve the state first, then reinstall the source code.
What Must Be Preserved
Back up the entire OpenClaw state directory before deleting or moving anything:
~/.openclawThis can include:
| Path | Purpose | Restore? |
|---|---|---|
openclaw.json | Primary configuration | Yes |
agents/main/agent/auth-profiles.json | Provider, API, and OAuth profiles | Yes, secret |
agents/main/agent/auth.json | Authentication state | Yes, secret |
agents/main/agent/models.json | Agent model configuration | Yes |
agents/main/sessions/sessions.json | Session index and metadata | Optional |
agents/main/sessions/*.jsonl | Conversation transcripts | Optional, private |
credentials/ | Discord, channel, and provider credentials | Yes, secret |
cron/jobs.json | Scheduled jobs | Yes |
workspace/ | Agent identity, instructions, tools, and durable context | Yes |
memory/notes/ | File-backed durable memory | Yes |
memory/main.sqlite | Search/index database | Optional, usually rebuildable |
canvas/index.html | Custom canvas page | Only if customized |
openclaw.json.bak* | Emergency config rollback copies | Optional |
For some Docker deployments, also preserve:
~/.config/openclawThat directory may contain auth-profile encryption material. Treat it as secret.
What Not to Restore
Do not migrate large or rebuildable application files into the fresh install:
~/openclaw/node_modules~/openclaw/.git~/.cache- Docker image layers
- downloaded model caches
- build output
~/.openclaw/update-check.json~/.openclaw/completions/~/.openclaw/cron/*.tmp- session
.bak-*files unless you are debugging an old session
If a file count looks huge, such as hundreds of thousands of files, you are probably counting the source checkout, dependency folders, cache directories, model files, or the whole home directory. OpenClaw configuration alone should be much smaller.
Check where the size is concentrated:
du -h --max-depth=2 ~/.openclaw 2>/dev/null | sort -h | tail -30
find ~/.openclaw -type d | wc -l
find ~/.openclaw -type f | wc -l
du -sh ~/.openclaw
du -h --max-depth=2 ~/openclaw 2>/dev/null | sort -h | tail -30Step 1: Stop OpenClaw Before Copying State
Stop the gateway so files are not changing while you archive them:
cd ~/openclaw
docker compose stop openclaw-gatewayIf you want to be more conservative, stop the whole stack:
docker compose downStep 2: Create a Full State Backup
This is the safest compatible backup for older Docker installs:
umask 077
mkdir -p ~/openclaw-backups
tar -C "$HOME" \
--exclude='.openclaw/agents/main/sessions/*.bak-*' \
--exclude='.openclaw/agents/main/sessions/*.lock' \
--exclude='.openclaw/cron/*.tmp' \
-czf "$HOME/openclaw-backups/openclaw-state-$(date +%Y%m%d-%H%M%S).tar.gz" \
.openclawIf your deployment uses ~/.config/openclaw, back it up too:
if test -d "$HOME/.config/openclaw"; then
tar -C "$HOME" \
-czf "$HOME/openclaw-backups/openclaw-config-dir-$(date +%Y%m%d-%H%M%S).tar.gz" \
.config/openclaw
fiPreserve local deployment files from the source checkout:
cd ~/openclaw
tar -czf "$HOME/openclaw-backups/openclaw-deployment-$(date +%Y%m%d-%H%M%S).tar.gz" \
.env \
docker-compose.yml \
docker-compose.yaml \
compose.yml \
compose.yaml \
2>/dev/null || trueIf the repository has local changes you care about, save a patch:
git rev-parse HEAD > "$HOME/openclaw-backups/openclaw-git-revision.txt"
git status --short > "$HOME/openclaw-backups/openclaw-git-status.txt"
git diff > "$HOME/openclaw-backups/openclaw-uncommitted.patch"Step 3: Verify the Backup
Create and verify checksums:
sha256sum ~/openclaw-backups/openclaw-*.tar.gz \
> ~/openclaw-backups/openclaw-backups.sha256
sha256sum -c ~/openclaw-backups/openclaw-backups.sha256Inspect the archive without extracting it:
ARCHIVE="$(ls -t ~/openclaw-backups/openclaw-state-*.tar.gz | head -1)"
tar -tzf "$ARCHIVE" | head -50
ls -lh "$ARCHIVE"
chmod 600 "$ARCHIVE" ~/openclaw-backups/openclaw-backups.sha256These archives can contain API keys, OAuth tokens, Discord credentials, GitHub credentials, gateway secrets, conversation transcripts, and personal data. Keep them private and encrypted.
Smaller Config-Only Backup
If you do not want to preserve session history or the rebuildable SQLite search index, create a smaller archive:
umask 077
mkdir -p ~/openclaw-backups
tar -C "$HOME/.openclaw" \
-czf "$HOME/openclaw-backups/openclaw-config-only-$(date +%Y%m%d-%H%M%S).tar.gz" \
openclaw.json \
agents/main/agent \
credentials \
cron/jobs.json \
workspace \
memory/notesIf you want conversation continuity too:
tar -C "$HOME/.openclaw" \
-czf "$HOME/openclaw-backups/openclaw-migration-full-$(date +%Y%m%d-%H%M%S).tar.gz" \
openclaw.json \
agents/main/agent \
agents/main/sessions \
credentials \
cron/jobs.json \
workspace \
memory \
canvas/index.htmlThe full state archive is safer when you are unsure. The config-only archive is cleaner when you deliberately want a smaller restore.
Step 4: Confirm Important Files Exist
Check for important state without printing secrets:
for file in \
~/.openclaw/openclaw.json \
~/.openclaw/agents/main/agent/auth-profiles.json \
~/.openclaw/agents/main/agent/auth.json \
~/.openclaw/agents/main/agent/models.json \
~/.openclaw/credentials/discord-pairing.json \
~/.openclaw/cron/jobs.json \
~/openclaw/.env
do
if test -f "$file"; then
echo "FOUND: $file"
else
echo "MISSING: $file"
fi
doneList top-level OpenClaw state directories:
find ~/.openclaw -mindepth 1 -maxdepth 1 -printf '%f\n' | sortLook especially for:
openclaw.json
workspace
memory
identity
plugins
skills
channels
agents
credentials
cronStep 5: Reinstall OpenClaw Cleanly
Move the old source checkout aside:
cd ~/openclaw
docker compose down
cd ~
mv openclaw "openclaw.old.$(date +%Y%m%d-%H%M%S)"Clone a fresh copy:
git clone https://github.com/openclaw/openclaw.git ~/openclaw
cd ~/openclaw
./docker-setup.sh
docker compose downThe new install may create fresh empty state. Preserve it before restoring the old state:
mv ~/.openclaw ~/.openclaw.fresh 2>/dev/null || true
mkdir -p ~/.openclaw
chmod 700 ~/.openclawStep 6: Restore OpenClaw State
Restore the full state archive:
tar -xzf ~/openclaw-backups/openclaw-state-YYYYMMDD-HHMMSS.tar.gz \
-C "$HOME"Or restore the smaller config-only archive:
tar -xzf ~/openclaw-backups/openclaw-config-only-YYYYMMDD-HHMMSS.tar.gz \
-C "$HOME/.openclaw"If you backed up ~/.config/openclaw, restore it too:
tar -xzf ~/openclaw-backups/openclaw-config-dir-YYYYMMDD-HHMMSS.tar.gz \
-C "$HOME"Fix ownership for the Docker user:
sudo chown -R 1000:1000 ~/.openclaw
if test -d "$HOME/.config/openclaw"; then
sudo chown -R 1000:1000 ~/.config/openclaw
fi
chmod 700 ~/.openclawThe Docker container commonly runs as UID 1000, so ownership must match the bind-mounted state path.
Step 7: Restore Deployment Settings Carefully
Do not blindly overwrite every new Compose file with an old one. Start by restoring .env only:
cd ~/openclaw
cp ~/openclaw.old.*/.env .env
chmod 600 .envIf the old install had custom Compose overrides, compare them before copying:
ls -la ~/openclaw.old.*/Only copy overrides you still need, such as explicit volume mounts, ports, or environment variables.
Step 8: Rotate Exposed Credentials
If terminal history, logs, screenshots, or uploaded files exposed tokens, do not restore those exact values as if nothing happened.
Rotate:
- GitHub tokens and GitHub Copilot credentials
- Discord bot tokens and pairing credentials
- model provider API keys
- OAuth refresh tokens where possible
- gateway or Control UI secrets from
.env
Prefer re-authentication for credentials such as:
~/.openclaw/credentials/github-copilot.token.jsonRestore it only when you understand the risk and the token was not exposed.
Step 9: Start and Validate
Start the new install:
cd ~/openclaw
docker compose up -dCheck containers and logs:
docker compose ps
docker compose logs --no-color --tail=200 openclaw-gatewayRun OpenClaw validation:
docker compose run --rm openclaw-cli doctor
docker compose run --rm openclaw-cli status
docker compose run --rm openclaw-cli cron listIf your OpenClaw version supports it, use the repair mode:
docker compose run --rm openclaw-cli doctor --fixdoctor --fix can migrate legacy primary configuration and cron-job formats after an upgrade.
Step 10: Reapply Safe Configuration
If you extracted settings from an old install, reapply only the safe ones. Examples:
docker compose run --rm openclaw-cli config set \
channels.discord.enabled true
docker compose run --rm openclaw-cli config set \
agents.defaults.compaction.memoryFlush.enabled true
docker compose run --rm openclaw-cli config set \
agents.defaults.memorySearch.provider local
docker compose run --rm openclaw-cli config set \
agents.defaults.memorySearch.model all-MiniLM-L6-v2
docker compose run --rm openclaw-cli config set \
agents.defaults.memorySearch.query.hybrid.enabled true
docker compose run --rm openclaw-cli config set \
agents.defaults.memorySearch.query.hybrid.vectorWeight 0.7
docker compose run --rm openclaw-cli config set \
agents.defaults.memorySearch.query.hybrid.textWeight 0.3
docker compose run --rm openclaw-cli config set \
agents.defaults.memorySearch.cache.enabled trueDo not re-enable:
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallbackConfigure explicit allowed origins for the new hostname instead:
docker compose run --rm openclaw-cli config set \
gateway.controlUi.allowedOrigins \
'["https://openclaw.example.com"]'For local SSH tunnel access, prefer loopback binding and avoid public Control UI exposure.
Troubleshooting After Restore
Permission Denied on OpenClaw State
Fix ownership and restrictive permissions:
sudo chown -R 1000:1000 ~/.openclaw
chmod 700 ~/.openclaw
chmod 600 ~/.openclaw/openclaw.jsonMissing Memory Search Results
If you restored only memory/notes, the SQLite index may need to be rebuilt. Start the gateway and run:
docker compose run --rm openclaw-cli doctor --fixThen verify:
ls -la ~/.openclaw/memory/notes
ls -lh ~/.openclaw/memory/Discord Does Not Reconnect
Check whether the channel is enabled and the token was rotated:
docker compose run --rm openclaw-cli config get channels.discord.enabled
docker compose logs --no-color --tail=200 openclaw-gateway | grep -i discordIf a Discord token was exposed, create a new bot token in the Discord Developer Portal and update OpenClaw with the new value.
The Backup Is Massive
You probably included dependency folders or caches. Use the state-only archive:
tar -C "$HOME" \
--exclude='.openclaw/agents/main/sessions/*.bak-*' \
--exclude='.openclaw/cron/*.tmp' \
-czf "$HOME/openclaw-backups/openclaw-state-$(date +%Y%m%d-%H%M%S).tar.gz" \
.openclawOr use the smaller config-only archive:
tar -C "$HOME/.openclaw" \
-czf "$HOME/openclaw-backups/openclaw-config-only-$(date +%Y%m%d-%H%M%S).tar.gz" \
openclaw.json \
agents/main/agent \
credentials \
cron/jobs.json \
workspace \
memory/notesKey Takeaways
Back up ~/.openclaw before reinstalling OpenClaw. It contains the durable state: configuration, credentials, auth profiles, sessions, memory, jobs, and workspace data.
Re-clone the application source instead of copying ~/openclaw wholesale. Do not migrate node_modules, .git, caches, model downloads, or build output.
Treat every backup as secret material. If credentials were exposed in terminal history, screenshots, pasted logs, or uploaded files, rotate them before starting the restored installation.
