Concept · backup

S3 backup & restore — your tenants are portable.

One command snapshots a tenant to S3 or any S3-compatible bucket. One command restores it on a different gateway. Path-traversal-safe both ways.

Why backup is built-in

Multi-tenant gateways earn an enormous amount of trust from their tenants — sessions, memory, channel pairings, paid-for cost history. Lose any of it and the tenant churns. So OpenClawMU treats backup as a first-class primitive, not a "you should run pg_dump in cron" afterthought.

A tenant tarball captures everything reproducible — every directory under tenants/<name>/ except for ephemeral pty state. Restore on the same or a different gateway, with the same or a different name, and the tenant resumes — same token, same sessions, same memory, same channel pairings (you'll need to re-pair WhatsApp by QR but Telegram/Slack tokens survive).

Backup

bash
# To AWS S3
openclaw tenants backup acme \
  --to s3://my-bucket/acme/2026-06-03.tar.zst \
  --aws-profile production

# To MinIO / R2 / any S3-compatible
openclaw tenants backup acme \
  --to s3://my-bucket/acme/2026-06-03.tar.zst \
  --endpoint https://minio.internal:9000 \
  --access-key $S3_AK --secret-key $S3_SK

# To local file (for ops sanity checks)
openclaw tenants backup acme \
  --to /var/backups/openclawmu/acme/2026-06-03.tar.zst

# Encrypted (pipe through age before upload)
openclaw tenants backup acme \
  --to s3://my-bucket/acme/2026-06-03.tar.zst.age \
  --pipe "age -r age1abc..."

Restore

bash
# Restore on a fresh gateway (tenant slot must be empty)
openclaw tenants restore \
  --from s3://my-bucket/acme/2026-06-03.tar.zst

# Restore with a new name (useful for staging clones)
openclaw tenants restore \
  --from s3://my-bucket/acme/2026-06-03.tar.zst \
  --as acme-staging

# Restore over an existing tenant (requires --force)
openclaw tenants restore \
  --from s3://my-bucket/acme/2026-06-03.tar.zst \
  --force

Path-traversal hardening

Both endpoints sanitize the source / destination paths to prevent a malicious tarball from writing outside the tenant root, and to prevent a misconfigured CLI from reading a host file as a tenant source. Specifically:

  • Tarball entries are restricted to the tenants/<name>/... prefix.
  • Symlinks inside the tarball are dereferenced relative to the tenant root and rejected if they escape.
  • Restore destination is always under the configured tenant base dir; .. in the --as name is rejected.
  • The S3 key is validated to contain no .. segments before being passed to the S3 client.

Automation

Schedule backups by tenant via the gateway's cron primitive — yes, the same cron primitive you give your tenants. Or run them from your own cron / Kubernetes CronJob.

bash
# Schedule a nightly backup for one tenant
openclaw cron add acme \
  --schedule "0 3 * * *" \
  --name "nightly-backup" \
  --cmd "openclaw tenants backup acme --to s3://my-bucket/acme/\$(date +%F).tar.zst"

# Or do all of them
for t in $(openclaw tenants list --names); do
  openclaw tenants backup $t --to s3://my-bucket/$t/$(date +%F).tar.zst
done

EXFOLIATE!

Run your own gateway today.

Apache-2.0, self-hosted, no SaaS layer between you and your users. Install the CLI, create your first tenant, mint a token — you're routing traffic in 60 seconds.