Skip to content

Backend configuration

This is the index for Kopiur's storage backends. Each backend has its own dedicated page with provider prerequisites, the exact Secret shape, a field-by-field reference, customization knobs, and backend-specific troubleshooting. Start here for the cross-cutting rules (the mental model, the credential-key conventions), then jump to your backend below. For the concepts behind a repository (the namespaced-vs-cluster split, encryption, repository creation) read Repositories & backends first.

The mental model (read this once)

A Repository is where snapshots live. It splits cleanly into two halves:

  • Non-secret connection identifiers — bucket, container, endpoint, host, path. These go in spec.backend.<kind>.
  • Secrets — backend access keys and the kopia encryption password. These live in a Kubernetes Secret, read by well-known keys, and are passed to kopia as environment variables (never on argv, never in status).

SnapshotPolicy / Snapshot / Restore never repeat any of this — they point at the Repository by name.

Externally tagged — there is no kind: field

A backend is chosen by which key you set (backend.s3, backend.azure, …), not a kind: discriminator. backend: { kind: S3 } will not admit. Exactly one backend key is allowed. (Why: API conventions.)

Pick your backend

Backend Covers Spec key
S3 & S3-compatible Amazon S3, MinIO, RustFS, Ceph RGW, Wasabi, Cloudflare R2, … backend.s3
Azure Blob Storage Azure Blob containers (key or SAS token) backend.azure
Google Cloud Storage GCS buckets (service-account key) backend.gcs
Backblaze B2 Backblaze B2 native API backend.b2
Filesystem (PVC / NFS) A NAS/PVC or inline NFS export mounted into the mover backend.filesystem
SFTP Any server reachable over SSH/SFTP backend.sftp
WebDAV Nextcloud, Apache mod_dav, … backend.webDav
rclone Google Drive, OneDrive, Dropbox, and dozens more backend.rclone
Google Drive (native) Google Drive via kopia's native gdrive (experimental) backend.gdrive

How to use these pages

  1. Find your backend above.
  2. Provider prerequisites — create the bucket/container/share and a scoped credential on the provider side.
  3. Copy the manifest on the page, fill in every REPLACE_ME, set a long random KOPIA_PASSWORD, and kubectl apply -f.
  4. Watch it become Ready (see Watching a repository).

Lose the password, lose the backups

KOPIA_PASSWORD encrypts the repository. kopia cannot decrypt without it and there is no recovery. Use a long random value, store it outside the cluster (a password manager / external secret store), and back up the Secret itself. The three create-time tunables (encryption/splitter/hash) are fixed forever at creation — see Encryption and repository creation.

Credential keys at a glance

The mover reads these exact key names from the Secret you reference and feeds them to kopia. KOPIA_PASSWORD is required for every backend.

Backend Secret keys (besides KOPIA_PASSWORD) Spec key
S3 / S3-compatible AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, (opt) AWS_SESSION_TOKEN backend.s3
Azure AZURE_STORAGE_KEY or AZURE_STORAGE_SAS_TOKEN backend.azure
Google Cloud Storage KOPIA_GCS_CREDENTIALS (the SA-key JSON) backend.gcs
Backblaze B2 B2_KEY_ID, B2_KEY backend.b2
Filesystem (none — only KOPIA_PASSWORD) backend.filesystem
SFTP KOPIA_SFTP_KEY_DATA, KOPIA_SFTP_KNOWN_HOSTS backend.sftp
WebDAV KOPIA_WEBDAV_USERNAME, KOPIA_WEBDAV_PASSWORD backend.webDav
rclone KOPIA_RCLONE_CONFIG (via configSecretRef) backend.rclone
Google Drive KOPIA_GDRIVE_CREDENTIALS (via credentialsSecretRef) backend.gdrive

Cloud clusters: workload identity instead of static keys

On EKS, AKS, or GKE the three cloud backends can skip the static keys entirely: auth.workloadIdentity.serviceAccountName runs the mover Jobs as a user-supplied, IAM-federated ServiceAccount, and only KOPIA_PASSWORD remains in the cluster. See S3 / IRSA, Azure / AKS, and GCS / GKE. The non-cloud backends (B2, SFTP, WebDAV) are Secret-only — they have no IAM plane to federate with.

Env-delivered vs. file-delivered credentials

Most backends authenticate via environment variables kopia reads directly — the mover loads the Secret with envFrom, so the keys above become env vars. Four backends need their credentials as files instead (kopia's SFTP/GCS/rclone/gdrive flags have no env form, and a Secret key like ssh-privatekey isn't a valid env-var name so envFrom would silently drop it). For those, the mover reads a well-known env key and writes it to a private (0600) file, then points kopia at the path:

Secret key Becomes kopia flag
KOPIA_SFTP_KEY_DATA the SSH private key file --keyfile
KOPIA_SFTP_KNOWN_HOSTS the known_hosts file --known-hosts
KOPIA_GCS_CREDENTIALS the service-account JSON file --credentials-file
KOPIA_RCLONE_CONFIG the rclone.conf file rclone --config
KOPIA_GDRIVE_CREDENTIALS the service-account JSON file --credentials-file

You don't manage the files — just put the value under the right key; the secret never lands on kopia's argv.

ClusterRepository: where Secret refs resolve

The per-backend pages use a namespaced Repository. The same backend stanzas apply to a cluster-scoped ClusterRepository, with one wrinkle: it has no namespace of its own, so "absent = the referrer's namespace" has nothing to resolve to.

  • When the operator itself reads the Secret — to connect, to bootstrap, or to run the repository server — a Secret reference with no namespace: resolves to the operator's namespace (KOPIUR_NAMESPACE, which the Helm chart sets for you). Setting namespace: explicitly always wins. This is what makes a ClusterRepository with no namespaces on its refs reach Ready at all.
  • When a workload mover reads it — a Snapshot, Restore or Maintenance Job — the Secret must exist in that workload's namespace, because envFrom is namespace-local. Either replicate it there yourself, or turn on credential projection (recommended for shared repos) and let Kopiur copy it in.

Set namespace: explicitly if anything other than the operator reads the Secret

The operator-namespace default above applies only to the repository's own connect / bootstrap / server. The mover side does not default it: credential projection needs an explicit namespace: on the reference to know what to copy, and without projection a mover looks for a same-named Secret in its own namespace. So a ClusterRepository with no namespace: on its refs will reach Ready and then fail its Snapshot/Restore Jobs with a MissingDependency naming the Secret.

If you run backups (i.e. almost always), pin the namespace:

encryption:
  passwordSecretRef:
    name: kopiur-repository-secret
    namespace: kopiur-system # where the Secret actually lives
    key: KOPIA_PASSWORD

A worked S3 example is on the S3 page.

See also