SOPS and age Secret Workflow¶
This repository is being prepared to use SOPS with age for Git-friendly secret files used by Kubernetes, Rancher Fleet, and future Ansible automation. This first phase only adds repository configuration, examples, and local test commands. It does not encrypt existing files, replace current Secret manifests, replace Ansible Vault, or add a SOPS operator.
Key Material¶
The repository uses this age recipient:
The private key should live only on trusted operator machines:
Never commit the private key, key backups, decrypted files, temporary plaintext files, or filled local .env files. The root .gitignore blocks the expected local key paths and common decrypted output names, but Git ignore rules are only a safety net.
File Naming¶
Use these names when real migration starts later:
app-name.secret.sops.yaml
app-name.secret.sops.yml
app-name.sops.yaml
app-name.sops.yml
app-name.sops.env
Kubernetes Secret manifests should use the *.secret.sops.yaml or *.secret.sops.yml suffix. The root .sops.yaml keeps metadata readable and encrypts only data and stringData for those files.
Generic YAML files for Ansible variables or application secret settings should use *.sops.yaml or *.sops.yml. Dotenv-style secret files should use *.sops.env.
Dummy Local Tests¶
The example files under examples/sops/ contain fake values only and are intentionally plaintext. They exist so the workflow can be tested safely before real migration.
Check tools:
Encrypt the dummy Kubernetes Secret using the repo .sops.yaml demo rule:
Equivalent explicit command:
sops --encrypt \
--age age1qz3p7ugntvalmdcn8ggzx39ktw7nszmwe8lchxcpmv80u3argdws95w9s2 \
--encrypted-regex '^(data|stringData)$' \
examples/sops/kubernetes/demo.secret.yaml > /tmp/demo.secret.sops.yaml
Decrypt only locally:
Dry-run the decrypted Kubernetes Secret without applying it:
Encrypt and decrypt the dummy Ansible-style YAML:
sops --encrypt \
--age age1qz3p7ugntvalmdcn8ggzx39ktw7nszmwe8lchxcpmv80u3argdws95w9s2 \
examples/sops/ansible/demo-secrets.yml > /tmp/demo-secrets.sops.yml
sops --decrypt /tmp/demo-secrets.sops.yml
The same workflow is available through Makefile targets:
make sops-demo-encrypt-kubernetes
make sops-demo-decrypt-kubernetes
make sops-demo-dry-run-kubernetes
make sops-demo-encrypt-ansible
make sops-demo-decrypt-ansible
make sops-demo-clean
Kubernetes and Fleet¶
Fleet should deploy normal manifests. SOPS-encrypted secrets are either manually decrypted/applied for now, or later handled by a dedicated SOPS operator if we choose that route. For this initial phase, do not add a SOPS operator.
Temporary manual workflow for a future real Secret:
Future naming examples using the current top-level service layout:
vaultwarden/overlays/local/vaultwarden.secret.sops.yaml
traefik/overlays/local/cloudflare.secret.sops.yaml
authelia/overlays/local/authelia.secret.sops.yaml
Fleet should continue managing non-secret resources normally:
Do not commit decrypted Kubernetes Secret manifests. Do not replace existing Kubernetes Secret manifests in this phase.
Ansible¶
No standard ansible/group_vars/, ansible/host_vars/, group_vars/, host_vars/, or inventories/ tree was found in this repository during this preparation pass. The only tracked Ansible Vault marker found by path was pulp3/overlays/ozirepo/ansible_vault; it is not changed by this phase.
Future Ansible usage can load SOPS-encrypted YAML like this:
homelab_secrets: "{{ lookup('community.sops.sops', 'group_vars/all/secrets.sops.yml') | from_yaml }}"
The Ansible controller or AWX execution environment will need:
No repository-level Ansible requirements.yml was found, so this phase does not add community.sops. Add it later only where the repository's Ansible execution environment is defined.
Current Secret Locations¶
The current repository contains many secret-like tracked paths. This inventory was based on filenames, Kustomize references, and Kubernetes kind: Secret markers only; secret values were not opened, decrypted, printed, or classified.
Current patterns include:
- Hand-written Kubernetes Secret manifests, including paths under
argocd/,authelia/,csi-driver-nfs/,fleet/,home-assistant/,homepage/,robusta/, andvelero/. - Kustomize
secretGeneratorenv/file sources under workloads such asbichon/,cloudflared/,defectdojo/,forgejo/,gitea/,grafana-dashboard/,infisical/,k8s-monitoring/,minio/,openvas/,pulp3/,renovate/,semaphore/,traefik/,vaultwarden/, andwazuh/. - Credential text files such as
*-creds.txt,*-credentials.txt,*-token.env,*-secrets.env,*-private.asc, and cloud/API token files across several overlays. - Example and placeholder files already used by some workloads, such as
*.exampleand*.env.example.
Treat this as migration inventory, not approval to edit or print those values.
Safety Checks¶
Before introducing or migrating any real secret file, review the diff and run local scans. Do not paste scan output into chat or issue comments if it may contain real values.
git diff --check
git status --short
git grep -nE '(password|passwd|secret|token|api_key|apikey|private_key|smtp_password)' -- .
For a path-only review, use:
Possible future tooling, not required for this phase:
Do not add a heavy dependency or blocking pre-commit policy until the current tracked secret-like files have been reviewed and a migration/rotation plan exists.
Later Migration Plan¶
Use small, reviewable units when moving real secrets:
- Pick one workload and identify its current secret source of truth by path, Secret name, namespace, and required keys.
- Create a new
*.secret.sops.yaml,*.sops.yml, or*.sops.envfile using existing values only from a safe operator workflow. - Test decrypt locally and run
kubectl apply --dry-run=client -f -for Kubernetes manifests. - Apply the decrypted Secret manually, then confirm the workload still consumes the same Secret name and keys.
- Update the workload README, service docs, and runbook with the new secret creation and rotation workflow.
- Remove old plaintext sources only after rotation and rollback are planned.
Do not do these in this initial phase:
- Encrypt existing Kubernetes secrets.
- Encrypt existing Ansible vars.
- Remove Ansible Vault.
- Add
sops-secrets-operator. - Add External Secrets Operator.
- Change Fleet behavior.
- Rotate production secrets.
- Refactor applications to consume new secrets.