rclone (everything else)
kopia shells out to rclone, so the rclone backend reaches any rclone-supported provider: Google Drive, OneDrive, Dropbox, pCloud, Box, Mega, and dozens more. This is the escape hatch for providers without a native kopia backend.
If a native backend exists for your provider, prefer it. It is simpler and has fewer moving parts. Those are S3, Azure, GCS, B2, and WebDAV. Use rclone for everything else.
Provider prerequisites
Section titled “Provider prerequisites”-
A working
rclone.confthat defines the remote you’ll reference. Build and test it on your own machine first:Terminal window $ rclone config # interactively create a remote, e.g. named "mydrive"$ rclone ls mydrive: # confirm it works before putting it in a Secret -
The remote name in your
remotePath, which ismydrive:below, must match a section header in thatrclone.conf, which is[mydrive].
The Secret shape
Section titled “The Secret shape”rclone is one of the three file-delivered backends. The mover reads the whole config from a well-known environment key, writes it to a private file with mode 0600, and runs rclone with --config.
| Secret key | Required | What it is |
|---|---|---|
KOPIA_RCLONE_CONFIG |
yes | The entire rclone.conf, exactly as printed. Written to a file, then passed to rclone as --config. |
KOPIA_PASSWORD |
yes | The repository encryption password. |
stringData: KOPIA_RCLONE_CONFIG: | [mydrive] type = drive scope = drive token = {"access_token":"REPLACE_ME", ...} KOPIA_PASSWORD: "choose-something-long-and-random"The Repository
Section titled “The Repository”---apiVersion: v1kind: Secretmetadata: name: rclone-config namespace: backupstype: OpaquestringData: # A standard rclone.conf defining the remote referenced by remotePath below # (here the remote is named `mydrive`). Generate it with `rclone config`. The # operator's mover writes this to a file and runs rclone with `--config`. The # key is KOPIA_RCLONE_CONFIG (a valid env identifier), not `rclone.conf` # (a dotted key is dropped by Kubernetes envFrom). KOPIA_RCLONE_CONFIG: | [mydrive] type = drive scope = drive token = {"access_token":"REPLACE_ME","token_type":"Bearer","refresh_token":"REPLACE_ME"} KOPIA_PASSWORD: "choose-something-long-and-random"---apiVersion: kopiur.home-operations.com/v1alpha1kind: Repositorymetadata: name: rclone-primary namespace: backupsspec: backend: rclone: remotePath: mydrive:backups/kopia # rclone remote:path; `mydrive` is defined in rclone.conf configSecretRef: name: rclone-config # Secret holding the rclone.conf above (NOT `auth`) encryption: passwordSecretRef: name: rclone-config # may be the same Secret; it also carries KOPIA_PASSWORD key: KOPIA_PASSWORD create: enabled: trueFields reference (backend.rclone)
Section titled “Fields reference (backend.rclone)”| Field | Required | Default | Example | What it controls |
|---|---|---|---|---|
remotePath |
yes | — | mydrive:backups/kopia |
rclone path in remote:path form. The part before : must match a [section] in the config. The part after it is the folder. |
configSecretRef |
no¹ | — | { name: rclone-config } |
Secret holding the rclone.conf, under the key KOPIA_RCLONE_CONFIG. This is not auth. A ClusterRepository adds namespace:. |
startupTimeout |
no | 15s |
2m |
How long kopia waits for its embedded rclone serve to come up before failing the connect. It takes a Go duration. Raise it for slow remotes whose metadata and indexes load through the rclone-to-WebDAV bridge. |
¹ Optional in the schema, but required in practice. rclone can’t reach a remote without its config.
Customization — the values you actually change
Section titled “Customization — the values you actually change”remotePathis theremote:path. The remote name must exist in the config.KOPIA_RCLONE_CONFIGholds the config contents. Re-paste it when tokens rotate.create.enabledinitializes the repository if it’s missing.
As a ClusterRepository
Section titled “As a ClusterRepository”The same backend.rclone stanza works on a cluster-scoped ClusterRepository, with two requirements. The configSecretRef, and the encryption.passwordSecretRef, must carry an explicit namespace:. And the Secret must exist in the namespaces the movers run in. See Movers.
Try it end-to-end
Section titled “Try it end-to-end”Prove this backend really takes a backup. The same example file carries a tiny smoke-test: a throwaway PVC, a SnapshotPolicy, and a Snapshot, all pointed at the rclone-primary repository above. It takes you from “applied” to “a snapshot on my remote” in one go.
1. Apply the bundle. That is the backups namespace, the Secret, the Repository, and the smoke-test objects:
$ kubectl apply -f deploy/examples/backends/rclone.yaml2. Wait for the repository to be Ready. Everything else waits on this:
$ kubectl -n backups wait --for=condition=Ready repository/rclone-primary --timeout=2mrepository.kopiur.home-operations.com/rclone-primary condition met3. Take the smoke backup. The Snapshot uses generateName, so create it rather than apply it. The namespace, Secret, Repository, PVC, and policy already exist and report unchanged. The Snapshot is the one new object:
$ kubectl create -f deploy/examples/backends/rclone.yamlsnapshot.kopiur.home-operations.com/smoke-now-abc12 created4. Watch it succeed:
$ kubectl -n backups get snapshots -wNAME PHASE ORIGIN SNAPSHOT AGEsmoke-now-abc12 Pending manual 2ssmoke-now-abc12 Running manual 7ssmoke-now-abc12 Succeeded manual k1f1ec0a8 38sThe output above is illustrative. The Snapshot has no fixed Succeeded condition, so to wait on it in a script, key on the phase:
$ kubectl -n backups wait --for=jsonpath='{.status.phase}'=Succeeded \ snapshot/smoke-now-abc12 --timeout=5m5. Prove the data really moved. status.stats shows non-zero bytesNew and filesNew, and status.snapshot.kopiaSnapshotID is the kopia snapshot ID on your remote:
$ kubectl -n backups get snapshot smoke-now-abc12 -o jsonpath='{.status.stats}'{"sizeBytes":4096,"bytesNew":1280,"filesNew":2,"filesUnchanged":0}
$ kubectl -n backups get snapshot smoke-now-abc12 -o jsonpath='{.status.snapshot.kopiaSnapshotID}'k1f1ec0a8Both outputs are illustrative; sizes and the ID vary. Non-zero bytesNew proves the backup uploaded real content through rclone.
6. Clean up the smoke-test when you’re done:
$ kubectl -n backups delete snapshot --all # finalizer also deletes the kopia snapshot$ kubectl -n backups delete snapshotpolicy smoke$ kubectl -n backups delete pvc smoke-dataFrom here the rest of the lifecycle is the same on every backend. Only the Repository differs. Put it on a cron with a SnapshotSchedule, described in Backups & schedules and Example 01. Restore by picking a Snapshot, described in Restores and Example 03.
Troubleshooting
Section titled “Troubleshooting”- Auth or token errors. Tokens in
rclone.confexpire or get revoked. Re-runrclone config reconnect <remote>:on your own machine and re-paste the config. configSecretRefignored. Make sure you usedconfigSecretRef, notauth. rclone has noauthblock.- Always validate with
rclone ls <remote>:on your own machine before applying.
See also
Section titled “See also”- Repositories & backends: the concepts, meaning scope, encryption, and creation.
- Movers, RBAC & credentials: where the config Secret must live.
- Native backends, which you should prefer where one exists: S3 · Azure · GCS · B2 · WebDAV.