Skip to content

Secrets

Encryption in Git and secret decryption in the cluster

Where they live

Path Format Read by
live/<environment>/secrets/*.env Environment file Terraform, through Make
live/<environment>/secrets/**/*.yaml SopsSecret The cluster
age.key Private key, ignored by Git You, and the secrets operator
live/<environment>/deploy.key SSH key, ignored by Git Argo CD

Edit

sops live/prod/secrets/digitalocean.env # (1)!
  1. Opens the editor and encrypts again on save.
Variable in a .env file Becomes
Provider credential, for example DIGITALOCEAN_TOKEN The variable the provider expects
TF_VAR_<name> var.<name> in Terraform

Situations

Situation Action
New machine Copy age.key to the repository root, then make init
Rotate a token Create the new one, sops <file>, revoke the old one
The hook rejects a commit The file is in plain text: sops -e -i <file>
age.key is lost New key, its public part in .sops.yaml, new credentials, re-encrypt everything

Rotating is not re-encrypting

Earlier versions of a file stay in Git history. A leaked credential must be revoked.

Registry credentials supplied by the platform

The source lives in live/<environment>/secrets/registry/dockerhub.yaml, encrypted with SOPS. The operator creates infra-registry/platform-dockerhub; Reflector copies it only to namespaces labeled blackstorm.dev/registry-access: platform and keeps those copies synchronized. Removing the label removes the automatic mirror.

project-onboarding owns that namespace label and configures the default ServiceAccount with imagePullSecrets: [{name: platform-dockerhub}]. Newly created pods using that account inherit the reference when they do not declare their own image-pull secrets. Workloads with another ServiceAccount must configure that account or explicitly reference platform-dockerhub in their pod specification.

The shared credential grants the same Docker Hub permissions to every authorized namespace. Namespace selection is not per-image authorization. Prefer a pull-only token; Reflector cannot reduce a token's read/write permissions. CI publication uses its own credentials and is unaffected by this distribution mechanism.

Edit the source and let its Argo application synchronize:

SOPS_AGE_KEY_FILE="$PWD/age.key" sops edit live/local/secrets/registry/dockerhub.yaml

Use live/prod/... for the cloud environment. Update the password in the encrypted .dockerconfigjson value; no plaintext copy is needed. Verify a new private-image pull after rotation before revoking the old token. Running application pods do not need a restart just to update image-pull credentials.

Reflector is declared both in bootstrap/helmfile.yaml and in the GitOps application under kubernetes/apps/infra-registry/reflector. Credentials use a separate GitOps application under live/<environment>/kubernetes/infra-registry/credentials.

Existing project-managed Secrets named dockerhub remain separate. A project moving to platform credentials removes its explicit imagePullSecrets declaration (or switches it to platform-dockerhub) and stops generating its own pull Secret. Keep any credential still needed by CI. The Compose converter continues to support explicit project-supplied registries where needed.