Feature permissions
A few of Kopiur’s features need the operator to write Secrets in namespaces it manages. That is a broader privilege than a backup operator needs day to day, so those writes are off by default, and each one is gated behind a single Helm flag.
This page explains which features those are, which flag maps to which feature, the security trade-off, and how to recognize and fix the error you get if you turn a feature on in a custom resource but forget the matching flag.
The two flags
Section titled “The two flags”# =============================================================================# Feature permissions# =============================================================================# A few opt-in features need the operator to WRITE Secrets in the namespaces it# manages, so each grants extra RBAC. All are OFF by default (least privilege):# the chart does not hand out cluster-wide `secrets` write until you turn on the# feature you use. The flag names match the CRD fields that trigger them.## Symptom → fix: if you enable the feature in a CR but forget the flag here, the# resource's `.status` shows an actionable condition like# "... (HTTP 403). ... Fix: set features.<name>.enabled: true ..."# Set the matching flag below and the operator heals on the next reconcile.# See https://kopiur.home-operations.com/feature-permissions/ for the full mapping and security trade-offs.features: credentialProjection: # -- Enable `spec.credentialProjection` (copy a repository's credential # Secret(s) into each mover Job's namespace) by granting the operator `secrets` # create+patch+delete. The chief win is a shared ClusterRepository whose Secret # is pinned to one namespace; the operator also cleans its copies up again # (legacy-copy sweep, reap-on-shrink, reap-on-disable). # SECURITY TRADE-OFF: `create` cannot be scoped to a Secret name, so the # operator can write a Secret in any namespace it manages. enabled: false kopiaUi: # -- Enable `spec.server` (the kopia web-UI) by granting the operator `secrets` # create+patch+delete. The server needs a generated-auth Secret, a mirror of # each of a ClusterRepository's credential Secrets in the server namespace, and # deletion of all of them on teardown. # SECURITY TRADE-OFF: grants unscoped create/delete on Secrets in any namespace # the operator manages. enabled: false| CRD field you set… | …needs this Helm flag | Grants the operator secrets |
|---|---|---|
spec.credentialProjection on a SnapshotPolicy / Restore / Maintenance |
features.credentialProjection.enabled |
create, patch, delete |
spec.seed.credentialProjection on a Repository / ClusterRepository (migrate-mode seeding) |
features.credentialProjection.enabled |
create, patch, delete |
spec.server on a Repository / ClusterRepository (the kopia web-UI) |
features.kopiaUi.enabled |
create, patch, delete |
Both default to false. With both off, the operator’s secrets access is read-only, which is exactly what a plain backup deployment needs.
Why each feature needs it
Section titled “Why each feature needs it”-
Credential projection (Movers → projection) copies a repository’s credential
Secretinto each mover Job’s namespace, so a sharedClusterRepositorywhoseSecretlives in one place works across many workload namespaces.The operator therefore needs to create and patch
Secrets in those namespaces, and to delete them, because a copy only needs to live as long as a mover Job can still read it. Kopiur reclaims each copy once the run that needed it has finished, rather than leaving live repository credentials sitting in your app namespaces. TheownerReferenceon the copy is a backstop for the case where the whole custom resource is removed; it is not the cleanup mechanism, because aSnapshotis kept for your entire retention window and waiting for garbage collection would mean waiting months. -
Seeding from another repository (Repositories →
seed) is the same mechanism aimed at a different Secret.A migrate-mode seed opens two repositories from one bootstrap pod, and the source repository’s credentials usually live in another namespace.
seed.credentialProjection.enabledcopies them into the seeding Job’s namespace for the run, and the copies are reclaimed when the seed finishes. Without the flag the bootstrap fails closed, with a message naming both the CRD field and the install flag, rather than launching a Job that cannot authenticate. -
The kopia web UI server (Web UI) creates a generated-auth
Secretfor the UI login, whenauth: generate. For aClusterRepositoryit also mirrors the repository’s credentials into the server’s namespace, because the Deployment’senvFromonly reads the local namespace. Both are deleted on teardown or on a namespace migration, so this feature needscreate,patchanddelete.
Enabling a feature
Section titled “Enabling a feature”Turn on the flag for the feature you use, in Helm values:
features: credentialProjection: enabled: true # if you use spec.credentialProjection kopiaUi: enabled: true # if you use spec.serverOr on the command line:
$ helm upgrade kopiur oci://ghcr.io/home-operations/charts/kopiur \ --reuse-values --set features.kopiaUi.enabled=trueSymptom → fix
Section titled “Symptom → fix”If you enable a feature in a custom resource while the matching flag is still false, RBAC forbids the operator’s write and the affected resource degrades with a clear, actionable condition. It does not crash, and it heals the moment you grant the flag.
Here is what you will see:
$ kubectl describe snapshotpolicy app-backup -n apps... Message: the operator may not write the projected credentials Secret `app-backup-...-creds-0` in namespace `apps` (HTTP 403). Fix: set `features.credentialProjection.enabled: true` in the Helm chart, or disable `spec.credentialProjection` ...$ kubectl describe repository nas-primary -n apps... Message: the operator may not write the kopia web-UI Secret `nas-primary-kopia-ui-auth` in namespace `apps` (HTTP 403). Fix: set `features.kopiaUi.enabled: true` in the Helm chart, or remove `spec.server` from the repository.| Symptom | Cause | Fix |
|---|---|---|
SnapshotPolicy/Restore/Maintenance status shows a 403 about a projected credentials Secret |
spec.credentialProjection is on but features.credentialProjection.enabled is false |
Set features.credentialProjection.enabled: true (or manage the Secret yourself and drop spec.credentialProjection) |
Repository/ClusterRepository bootstrap fails naming spec.seed.credentialProjection and the install flag |
spec.seed.credentialProjection.enabled is on but features.credentialProjection.enabled is false |
Set features.credentialProjection.enabled: true (or put the source repository’s Secrets in the seeding Job’s namespace yourself and drop the block) |
Repository/ClusterRepository status shows a 403 about a kopia web-UI Secret |
spec.server is set but features.kopiaUi.enabled is false |
Set features.kopiaUi.enabled: true (or remove spec.server) |
After you grant the flag, the operator re-reconciles and the condition clears on its own. No restart or manual retrigger is needed.
See also
Section titled “See also”- Movers, RBAC & credentials covers the full credential-projection model.
- Web UI (kopia server) is the
spec.serverfeature guide. - Helm chart values is where these flags live.
- Streamed command sources is the other gated capability, authorized by a namespace annotation rather than by a
secretsflag.