← Back to Blog

How to Update OpenClaw and Back Up Its Memory on a VPS: Safe Updates, Rollback, Off-Site Backups and a Server Move

Published · by Leo Gashi, RS Computers

OpenClaw Backups restic

To update OpenClaw safely on a VPS, take a verified backup first with openclaw backup create --verify, read the release notes, preview the update with openclaw update --dry-run, then run openclaw update as the user that owns the install and check the gateway afterwards. Its memory lives in two places, and a backup needs both: the workspace (~/.openclaw/workspace, where MEMORY.md and the daily notes in memory/ sit) and the SQLite databases under ~/.openclaw, which hold sessions, credentials and the memory search index. Never copy those databases with cp while the gateway runs. In our test, a plain copy of a busy database contained 1 row out of 5,001.

This is the maintenance follow-up to our secure OpenClaw VPS setup guide. That guide covers the install, the user without sudo and the sandbox. Here we assume OpenClaw already runs as a user called claw and deal with what comes after: the weekly update, a nightly encrypted copy on another server, a restore you have actually tried, and the day you move to a new VPS.

Facts checked on 24 October 2026:

Where OpenClaw keeps its memory, config and workspace

OpenClaw's install prefix and its state directory are the same folder, ~/.openclaw, so the program, your settings and your agent's memory sit side by side. The workspace is a subfolder, but OpenClaw treats it as a separate thing: the docs call it the agent's home and say it is "separate from ~/.openclaw/, which stores config, credentials, and sessions" (agent workspace docs). With the default profile, this is the layout:

PathWhat is in itBack it up?
~/.openclaw/workspace/MEMORY.mdCurated long-term memory: durable facts and decisionsYes, it is the memory you care about most
~/.openclaw/workspace/memory/YYYY-MM-DD.mdDaily notes, later distilled into MEMORY.mdYes
~/.openclaw/workspace/ (AGENTS.md, SOUL.md, USER.md, IDENTITY.md)Rules, persona and what the agent knows about youYes
~/.openclaw/openclaw.json and .envConfig, gateway token, API keys if you put them thereYes, encrypted
~/.openclaw/state/openclaw.sqliteShared state and model authYes, never with cp while running
~/.openclaw/agents/<id>/agent/openclaw-agent.sqliteSessions, transcripts, auth profiles, memory search indexYes, never with cp while running
~/.openclaw/credentials/Channel logins (WhatsApp, Telegram and others)Yes, encrypted
~/.openclaw/skills/Managed skillsYes
Node runtime and program filesAbout 820 MB in our earlier installNo, reinstall instead

Two details catch people out. The memory files are plain Markdown you can read and edit, but the search over them runs from SQLite tables, so restoring only the .md files brings back the memory without its index and session history. And if you run OpenClaw with a profile, everything moves to ~/.openclaw-<profile>/. Run openclaw status as claw to see which state directory your gateway really uses before you write a backup job around it (migration docs).

Why we got 1 row back out of 5,001

OpenClaw's databases run SQLite in WAL mode: new writes go to a side file ending in -wal first, and are folded into the main file later. A cp or rsync of the main file alone misses whatever is still waiting in that side file. We wanted to see how much that is, so on 24 October 2026 we built a database shaped like openclaw-agent.sqlite on our Debian 13 test server, kept a writer connection open the way a running gateway does, inserted 5,000 rows and copied it two ways:

# as root, on the test server, while the writer was still connected
ls -l openclaw-agent.sqlite*
cp openclaw-agent.sqlite copy-cp.sqlite
sqlite3 copy-cp.sqlite "SELECT count(*) FROM memory_chunks;"
sqlite3 openclaw-agent.sqlite ".backup copy-backup.sqlite"
sqlite3 copy-backup.sqlite "SELECT count(*) FROM memory_chunks;"
-rw------- 1 root root  8192 Oct 24 21:55 openclaw-agent.sqlite
-rw------- 1 root root 32768 Oct 24 21:55 openclaw-agent.sqlite-shm
-rw------- 1 root root 94792 Oct 24 21:55 openclaw-agent.sqlite-wal
1
5001

The main file was 8 KB, the waiting changes were 93 KB, and the plain copy held one row. SQLite's online backup API got all 5,001. That API is what openclaw backup create uses for its own databases, which is why the docs tell you to use it and to "never copy live .sqlite, -wal, -shm, or -journal files directly". A file-level backup tool pointed at a running ~/.openclaw has the same problem as cp. Let OpenClaw write the archive, then back up the archive.

How to update OpenClaw: the routine we use

OpenClaw updates often, and many of those releases are security fixes, so a weekly slot works better than "when I remember". Everything in this section runs as the claw user, not root. The openclaw commands come from the official updating guide; the backup, update status, dry run, update and restore commands are the ones we ran for our first OpenClaw guide on 12 October, during a real update from 2026.10.1 to 2026.10.2.

1. See what you run and what is out

# as the claw user
openclaw --version
openclaw update status
openclaw gateway status --deep

The first line is the CLI version, the second shows your channel and whether an update is available, the third confirms the gateway service points at the same installation. If the versions differ, sort that out first: the rollback docs ask you to compare them before every upgrade. To check from a script or a monitoring box without the CLI, ask the npm registry, which publishes OpenClaw's channels:

# as any user
curl -fsS https://registry.npmjs.org/-/package/openclaw/dist-tags; echo
{"extended-stable":"2026.9.34","beta":"2026.10.10-beta.3","latest":"2026.10.7"}

2. Read the release notes before, not after

Open the releases page and read every version between yours and the new one, not just the newest. Look for three things: a new minimum Node version (2026.10.6 raised it), config keys that are retired or renamed, and anything about channels you use, such as WhatsApp relinking. If your install is older than July 2026, the docs say to go to 2026.9.5 first, run its Doctor, and only then to the latest release.

3. Back up

# as the claw user
mkdir -p ~/backups && chmod 700 ~/backups
openclaw backup create --output ~/backups --verify

The archive is named like 2026-10-24T21-56-33.000+00-00-openclaw-backup.tar.gz. Ours was 190 KB and took 4.7 seconds; it leaves the Node runtime out but includes .env, so treat it as a secret. The automatic config copies the updater makes are not a full backup, the docs say, and openclaw update cleanup deletes the rollback copies the updater keeps, so this archive is your real way back.

4. Preview, then update

# as the claw user
openclaw update --dry-run
openclaw update --yes

The dry run names the checks the updater will run without changing anything. The real update installs the new version next to the old one while the gateway keeps serving, then switches over, runs Doctor for migrations and restarts the gateway. Our 2026.10.1 to 2026.10.2 update took 11 minutes 20 seconds on two busy vCPUs and the gateway was down for 202 seconds, so pick a quiet hour and tell anyone who chats with the agent. On Linux, a masked systemd unit makes the updater refuse; unmask it with systemctl --user unmask openclaw-gateway.service first.

5. Check it works

# as the claw user
openclaw --version
openclaw gateway status --deep
openclaw security audit

Then send the agent a message from each connected channel and ask it about something that should be in its memory. A gateway that starts but has lost its channel login looks healthy in the status output.

6. Clean up later, not now

The updater keeps the previous runtime (about 600 MB in our test) so it can roll back. Leave it for a few days. Once you are sure the new version is fine, openclaw update cleanup --dry-run shows what would be removed; the docs say to stop the gateway before running the real cleanup.

Rolling back an OpenClaw update

There are two ways back, and which one works depends on whether the new version already changed your databases.

  1. If the older release can still read your state, use the updater with an exact version: openclaw update --tag 2026.10.6 --dry-run, then the same without --dry-run. It checks compatibility, asks you to confirm the downgrade and restarts the gateway. If your saved channel is extended-stable, add --channel stable.
  2. If it refuses because the schema is newer, do not edit version markers to force it. Stop the gateway, set the current ~/.openclaw aside, restore the archive from step 3, reinstall the matching OpenClaw version and run openclaw doctor before starting. The docs insist on restoring config, shared database and per-agent databases "from one backup generation", never a mix.

Anything the agent learned between the backup and the rollback is lost in the second case, and WhatsApp in particular may ask you to link the phone again. If you run OpenClaw's auto-updater, set OPENCLAW_NO_AUTO_UPDATE=1 in the gateway's environment while you recover, or it will put the new release straight back. For a server that should change less often, the extended-stable channel (2026.9.34 today) gets security fixes without every feature release: openclaw update --channel extended-stable.

Back up OpenClaw memory every night, off the server

The cron line in our first guide keeps 14 days of archives on the same disk. That covers a bad update, not a dead disk, a deleted server or an attacker. The setup below adds an encrypted copy on a second machine, and it is built so the agent cannot touch it:

You need a second server with rest-server. Our restic offsite backup guide sets one up step by step with a login, TLS and --append-only, and shows how to prune old snapshots on the backup server, which is the only place that can. Put it in a different city from your OpenClaw server.

How we tested this part: we could not run the OpenClaw installer on our test server for this article, so we built a folder with the documented layout (config, .env, both SQLite databases in WAL mode, credentials and a workspace with MEMORY.md and a daily note) under a lab directory, ran rest-server 0.13.0 on 127.0.0.1 in append-only mode, and replaced the one openclaw backup create line with a stand-in that writes an archive of the same name and shape using SQLite's backup API. Everything else, restic, the script, the timer, the delete test and the restores, ran exactly as printed, on Debian 13 on 24 October 2026; only the paths pointed at the lab folder.

1. Install restic and store the password (as root)

# as root, on the OpenClaw server
apt install -y restic
install -d -m 700 /root/.openclaw-backup
echo 'rest:https://openclaw:REST_PASSWORD@BACKUP_HOST:8000/openclaw/' > /root/.openclaw-backup/repo
(umask 077; openssl rand -base64 32 > /root/.openclaw-backup/password)
chmod 600 /root/.openclaw-backup/repo
export RESTIC_REPOSITORY_FILE=/root/.openclaw-backup/repo
export RESTIC_PASSWORD_FILE=/root/.openclaw-backup/password
restic init

Expected: created restic repository ... at rest:... and a warning that losing the password means losing the data. Copy the contents of /root/.openclaw-backup/password into your password manager now. Without it, every snapshot on the backup server is noise. Debian 13 installed restic 0.18.0 for us.

2. The backup script

Save this as /usr/local/sbin/openclaw-backup and run chmod 700 /usr/local/sbin/openclaw-backup:

#!/bin/bash
# Nightly OpenClaw backup: OpenClaw's own archive, then an encrypted restic copy off the server.
set -euo pipefail
export RESTIC_REPOSITORY_FILE=/root/.openclaw-backup/repo
export RESTIC_PASSWORD_FILE=/root/.openclaw-backup/password
OC_HOME=/home/claw

# 1. WAL-safe archive written by OpenClaw itself, as the claw user
runuser -u claw -- "$OC_HOME/.openclaw/bin/openclaw" backup create --output "$OC_HOME/backups" --verify

# 2. keep 7 days of local archives
find "$OC_HOME/backups" -name '*-openclaw-backup.tar.gz' -mtime +7 -delete

# 3. encrypted, deduplicated copy on the backup server
restic backup --host openclaw-vps --tag openclaw "$OC_HOME/backups" "$OC_HOME/.openclaw/workspace"

If you installed OpenClaw differently, run command -v openclaw as claw and use that path on the runuser line. Run the script once by hand: /usr/local/sbin/openclaw-backup. The last lines should read snapshot ... saved.

3. A systemd timer instead of cron

A timer logs every run to the journal, catches up after the server was off (Persistent=true), and runs the job at low CPU and disk priority. Create two files as root.

/etc/systemd/system/openclaw-backup.service:

[Unit]
Description=OpenClaw backup (archive + restic)
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/openclaw-backup
Environment=RESTIC_CACHE_DIR=/var/cache/openclaw-backup
CacheDirectory=openclaw-backup
Nice=10
IOSchedulingClass=idle

/etc/systemd/system/openclaw-backup.timer:

[Unit]
Description=Nightly OpenClaw backup

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

Without the two cache lines, our first timed run worked but restic complained: unable to open cache: unable to locate cache directory: neither $XDG_CACHE_HOME nor $HOME are defined. Services started by systemd have no home directory set, and without a cache every run re-reads the index from the backup server. Now switch it on and fire one run:

# as root
systemd-analyze verify /etc/systemd/system/openclaw-backup.service /etc/systemd/system/openclaw-backup.timer
systemctl daemon-reload
systemctl enable --now openclaw-backup.timer
systemctl list-timers openclaw-backup.timer --no-pager
systemctl start openclaw-backup.service
journalctl -u openclaw-backup.service --no-pager -n 9 -o cat

What we saw (trimmed):

NEXT                            LEFT LAST PASSED UNIT                  ACTIVATES
Sun 2026-10-25 03:30:21 UTC 5h 33min -         - openclaw-backup.timer openclaw-backup.service

using parent snapshot 6dbf7774
Files:           1 new,     0 changed,     7 unmodified
Added to the repository: 24.234 KiB (23.155 KiB stored)
snapshot 3c738ddc saved
openclaw-backup.service: Deactivated successfully.
openclaw-backup.service: Consumed 1.749s CPU time, 28.1M memory peak.

systemd-analyze verify prints nothing when the files are fine. The run used 28 MB of RAM at its peak, so it fits next to the gateway even on a 4 GB server.

4. Prove the agent cannot delete it

# as root
export RESTIC_REPOSITORY_FILE=/root/.openclaw-backup/repo RESTIC_PASSWORD_FILE=/root/.openclaw-backup/password
restic forget --keep-last 1 --prune
Remove(<index/d08f866504>) failed: unexpected HTTP response (403): 403 Forbidden
Fatal: unexpected HTTP response (403): 403 Forbidden

That error is what you want. Even root on the OpenClaw server cannot prune the repository, so neither can ransomware or a confused agent that got root somehow. Retention runs on the backup server.

The restore test: do it once now, then monthly

A backup you have never restored is a hope. These are the checks we ran against our repository, as root.

The agent overwrote MEMORY.md and you want yesterday's version. We replaced the file with the word "oops" and pulled the old one out of the latest snapshot:

# as root
restic find MEMORY.md
restic dump latest /home/claw/.openclaw/workspace/MEMORY.md

find lists every snapshot that has the file and dump prints it, so you can read it before you put it back. Add > /tmp/MEMORY.md, compare, then copy it into place and fix the owner with chown claw:claw. Use a snapshot ID instead of latest to go further back.

The whole server is gone. Restore the newest snapshot into an empty folder and check the archive inside it:

# as root
restic snapshots --compact
restic restore latest --target /root/restore-test
ls /root/restore-test/home/claw/backups/
tar -tzf /root/restore-test/home/claw/backups/*-openclaw-backup.tar.gz | head
restic check

Our restore took under a second (Restored 16 files/dirs (63.618 KiB)) and restic check ended with no errors were found. A real OpenClaw archive starts with manifest.json and a payload/ folder. The last step is OpenClaw's own check, which verifies the archive and unpacks it into a folder that must be empty and must not be inside the live state directory:

# as root: hand the archive to claw
install -o claw -g claw -m 600 /root/restore-test/home/claw/backups/ARCHIVE.tar.gz /home/claw/
# as the claw user
openclaw backup restore ~/ARCHIVE.tar.gz --target ~/restore-test

When we ran this for the first guide, it verified and unpacked the archive and warned that WhatsApp may need relinking after a rollback. A restore never replaces your live state by itself; the docs describe the activation steps (stop the gateway, move the current state aside, move the restored state in, run openclaw doctor, start). Delete the test folders afterwards; they contain your keys.

We also opened the restored agent database: PRAGMA integrity_check answered ok and all 5,001 rows were there.

Moving OpenClaw to a new VPS

Moving is a backup and a restore with a stopped gateway in between. The official route is openclaw backup create on the old server, copy, openclaw backup restore into a staging folder on the new one, then move the state into place using the paths in the restored manifest.json, as the migration guide explains.

When both servers use the same user name, the same home path and the same CPU architecture, a cold copy of the whole folder is simpler, and it carries the program along so the version matches by definition. The docs allow it with one condition: stop the gateway first, because "a raw copy of a changing SQLite database can capture mismatched database and WAL files". Prepare the new server with our setup guide first (user, firewall, install, onboarding with --install-daemon), so the user service exists. Then:

# OLD server, as the claw user
openclaw --version
openclaw gateway stop
cd ~
(umask 077; tar -czf openclaw-cold-2026-10-24.tar.gz .openclaw)
sha256sum openclaw-cold-2026-10-24.tar.gz > openclaw-cold-2026-10-24.tar.gz.sha256
scp openclaw-cold-2026-10-24.tar.gz openclaw-cold-2026-10-24.tar.gz.sha256 claw@NEW_SERVER_IP:~/
# NEW server, as the claw user
openclaw gateway stop
mv ~/.openclaw ~/.openclaw.fresh
sha256sum -c openclaw-cold-2026-10-24.tar.gz.sha256
tar -xzf openclaw-cold-2026-10-24.tar.gz
stat -c '%A %U %n' .openclaw .openclaw/.env
awk -F= '/^(OPENCLAW_GATEWAY_TOKEN|TELEGRAM_BOT_TOKEN|DISCORD_BOT_TOKEN)=/ { print $1 "=present" }' ~/.openclaw/.env
openclaw doctor
openclaw gateway start
openclaw status

In our test copy, sha256sum -c printed openclaw-cold-2026-10-24.tar.gz: OK, the folder came back as drwx------ with .env at -rw-------, and the awk line printed OPENCLAW_GATEWAY_TOKEN=present without showing the secret. If you copied as root, run chown -R claw:claw /home/claw/.openclaw: the docs warn the gateway may fail to read its credentials otherwise. Keep the old server for a day, check every channel still answers, then delete ~/.openclaw.fresh and cancel the old VPS. Change the gateway token afterwards if the archive ever travelled through a machine you do not control.

Where git fits

OpenClaw's docs recommend keeping the workspace in a private git repository. That gives you a readable history of how MEMORY.md changed, which restic does not show as nicely. It is an extra, not a replacement: the workspace repo must never contain anything from the rest of ~/.openclaw, so it holds the Markdown memory and none of the sessions, credentials or search index. If you also sync coding-agent memory between machines, our claude-mem sync server guide shows the same idea for Claude Code: keep the memory on a server you control, behind a private network, and back that server up too.

Frequently asked questions

Where does OpenClaw store its memory?

In the agent workspace, ~/.openclaw/workspace by default: MEMORY.md for long-term memory and memory/YYYY-MM-DD.md for daily notes. The search index, sessions and transcripts are in SQLite databases under ~/.openclaw/agents/<id>/agent/, so a complete backup needs both.

How often should I update OpenClaw?

Weekly on the stable channel works for most people; OpenClaw shipped five stable releases between 12 and 24 October 2026. If that is too often, the extended-stable channel (2026.9.34 on 24 October) gets security and reliability fixes without every feature release.

Does openclaw update back up my data first?

It keeps config copies, migration originals and the previous runtime for its own rollback, but the docs say these are not a full backup. Run openclaw backup create --verify yourself before every significant update.

Can I downgrade OpenClaw after an update?

Sometimes. openclaw update --tag <version> works when the older release can still read your data. Downgrading never reverses database migrations, so after a schema change you need the backup taken before the update and the matching OpenClaw version.

Can I back up ~/.openclaw with rsync or restic directly?

Only with the gateway stopped. While it runs, the SQLite files change underneath the copy; our plain copy of a busy database kept 1 row of 5,001. Back up the archive that openclaw backup create writes, or stop the gateway first.

Are OpenClaw backups encrypted?

Local archives are plain .tar.gz files that include your config, tokens and chat history. Encrypt them before they leave the server, for example with restic as above, and keep the encryption password somewhere other than the server.

A server that is easy to replace

With a nightly archive on another machine and one restore drill behind you, the OpenClaw VPS itself stops being precious: if an update goes wrong or the server dies, you rebuild on a fresh server with the memory intact. Put the gateway and the backup target in different cities. RS Computers runs KVM servers in Amsterdam, Dublin and Prishtina, so one plan can host OpenClaw and a smaller one in another city can hold its backups. VPS Mini (4 GB) suits one person's assistant, VDS Small (8 GB, dedicated vCPUs) is the comfortable choice with a sandbox and faster updates, and the plans page lists both. Questions about sizing? Ask us on Telegram.

← All articles

Chat on Telegram