Adds named storage locations as a generic, pluggable capability, with backup as its first consumer. - Core storage owner (src/storage): storage.locations config, a location marker that binds identity (runtime never creates it, so unplugged disks and different disks at the same path are refused), client-side streaming encryption (scrypt key from a SecretRef passphrase, per-object HKDF keys, AES-256-GCM segments), and a built-in filesystem provider for external disks and mounts. - Plugin SDK: api.registerStorageProvider plus manifest contracts.storageProviders; providers move opaque bytes only. - Bundled cloudflare plugin: an r2 provider over the S3 API with conditional writes and bounded multipart uploads; auto-enabled when a location uses provider "r2". - Backups: backup create --to <location> with verified archives, UTC retention, list/verify/restore --from, Gateway-owned offsite schedules (installed Git schedules unchanged), per-installation namespace claims fenced at publication and deletion, backup record for external jobs, backup.status RPC, Doctor/status hints, and a Systems page Backups section. No config or state migration; the storage section is new and optional. Proof: live R2 and mounted-disk round trips, namespace takeover trace, and a published 2026.9.7 upgrade cell with an existing Git backup schedule.
7 KiB
| summary | title | read_when | |||
|---|---|---|---|---|---|
| Configure Cloudflare R2 as an encrypted OpenClaw storage location | Cloudflare |
|
Cloudflare
The bundled Cloudflare plugin provides r2 storage locations through Cloudflare's
S3-compatible API. OpenClaw handles location identity and encryption; the plugin
transfers objects to your bucket. Configuring a location does not schedule backups
or move existing data.
Create a bucket and credentials
- In the Cloudflare dashboard, open R2 object storage and create a private
bucket, such as
openclaw-artifacts. Bucket names must contain 3–63 lowercase letters, digits, or hyphens, and cannot begin or end with a hyphen. - Record your Cloudflare account ID and the bucket's jurisdiction, if any.
- From R2's Account Details, select Manage next to API Tokens, then Create Account API token.
- Select Object Read & Write and limit access to the bucket you created.
- Save the Access Key ID and Secret Access Key in your secret manager. Cloudflare shows the secret access key only once.
Use the R2 S3 credentials from this flow. See Cloudflare's bucket creation guide and R2 token guide.
Configure a location
Make the saved credentials available as R2_ACCESS_KEY_ID and
R2_SECRET_ACCESS_KEY in the environment that runs the CLI and Gateway. Create a
separate encryption passphrase, keep a recoverable copy in your secret manager,
and provide it as OPENCLAW_STORAGE_PASSPHRASE in that environment.
Add this to your OpenClaw config, replacing the example account ID and bucket:
{
storage: {
locations: {
offsite: {
provider: "r2",
settings: {
accountId: "00000000000000000000000000000000",
bucket: "openclaw-artifacts",
prefix: "openclaw",
accessKeyId: {
source: "env",
provider: "default",
id: "R2_ACCESS_KEY_ID",
},
secretAccessKey: {
source: "env",
provider: "default",
id: "R2_SECRET_ACCESS_KEY",
},
},
encryption: {
passphrase: {
source: "env",
provider: "default",
id: "OPENCLAW_STORAGE_PASSPHRASE",
},
},
},
},
},
}
R2 credential settings require SecretRefs; plaintext credential strings are rejected. You can use another configured secret provider instead of environment variables. A Gateway running as a service needs the values in its own environment, not just in your interactive shell.
Referencing provider: "r2" automatically enables the bundled cloudflare plugin
under the normal plugin policy. Explicit disablement and deny rules still apply.
Initialize and test
Confirm the bucket and prefix, then initialize the location and verify a complete write/read/delete cycle:
openclaw storage init offsite
openclaw storage test offsite
openclaw storage list --json
Initialization writes the location marker at
openclaw/openclaw-storage.json for the example above. The displayed target is
r2://openclaw-artifacts/openclaw. A successful test confirms that it wrote, read,
verified, and deleted its probe object; add --json for state: "ok".
Keep the marker and encryption passphrase: losing either can make encrypted
objects unreadable. R2 health checks verify bucket access without reporting free
or total space.
Settings
All fields below belong to storage.locations.<name>.settings.
| Field | Required | Meaning |
|---|---|---|
accountId |
Yes | Cloudflare account ID: exactly 32 lowercase hexadecimal characters. |
bucket |
Yes | Existing R2 bucket name, following the naming rules above. |
prefix |
No | Object-key prefix. Use slash-separated segments containing only letters, digits, ., _, and -; no empty, . or .. segments, or leading/trailing slash. Omit it to use the bucket root. |
jurisdiction |
No | "eu" or "fedramp", matching the bucket's jurisdiction. Omit for the default endpoint. |
accessKeyId |
Yes | SecretRef for the R2 access key ID. |
secretAccessKey |
Yes | SecretRef for the R2 secret access key. |
sessionToken |
No | SecretRef for the session token when using R2 temporary credentials. |
The plugin uses region auto. It chooses
https://<accountId>.r2.cloudflarestorage.com by default,
https://<accountId>.eu.r2.cloudflarestorage.com for "eu", or
https://<accountId>.fedramp.r2.cloudflarestorage.com for "fedramp".
No custom endpoint is required. A prefix is a namespace within the bucket, not a
separate permission boundary; the token remains scoped to the bucket.
Troubleshooting
For a 401 or 403 error, check that the R2 token has Object Read & Write on the configured bucket and that both SecretRefs resolve in the process running the command. For temporary credentials, also verify that the session token is present and has not expired.
If the bucket is missing, create it in the configured account or correct
accountId, bucket, and jurisdiction. OpenClaw does not create buckets.
If the location has no initialization marker, confirm that the prefix is correct before
running openclaw storage init <name>. Changing the prefix selects a different
location root. For wrong-key, restore the original encryption passphrase;
replacing the marker does not recover encrypted data.
See Storage locations for encryption and location lifecycle, and the storage CLI reference for command output.