Learnings: Using the 1Password Operator with Flux
A personal note documenting what I learned while migrating Linkding from SOPS secrets to 1Password.
The Challenge
1Password items have standard field names like username and password, but applications often expect specific environment variable names (e.g., LD_SUPERUSER_NAME, LD_SUPERUSER_PASSWORD). The OnePasswordItem CRD creates K8s secrets with keys matching the 1Password field names directly—no built-in field mapping.
Solution: valueFrom.secretKeyRef
Replace envFrom.secretRef (which imports all keys as-is) with explicit env entries using valueFrom.secretKeyRef:
Before: All secret keys become env vars with same names
After: Explicit mapping from secret keys to env var names
env:
- name: LD_SUPERUSER_NAME # Target env var name
valueFrom:
secretKeyRef:
name: linkding-container-env
key: username # Source key from 1Password
- name: LD_SUPERUSER_PASSWORD
valueFrom:
secretKeyRef:
name: linkding-container-env
key: password
Steps Taken
1: Created the OnePasswordItem Resource
apiVersion: onepassword.com/v1
kind: OnePasswordItem
metadata:
name: linkding-container-env
annotations:
operator.1password.io/auto-restart: "true"
spec:
itemPath: "vaults/apps/items/linkding"
The auto-restart annotation tells the operator to restart pods when the secret changes.
2: Updated the Deployment
Modified apps/base/linkding/deployment.yaml to use explicit field mapping instead of envFrom.
3: Updated Kustomization
Removed the old SOPS-encrypted secret from apps/staging/linkding/kustomization.yaml and kept the OnePasswordItem resource.
4: Committed and Pushed
Two commits: - feat: migrate linkding secret to 1password - test: change secret name
Debugging: Flux Not Picking Up New Commits
Problem: After pushing and running flux reconcile kustomization apps, Flux applied a revision from 2 commits ago.
Root cause: The GitRepository source hadn't fetched the latest commits yet. Reconciling a Kustomization only re-applies from the cached source.
Solution: Reconcile the source first, then the kustomization:
Step 1: Fetch latest from git
flux reconcile source git flux-system
Step 2: Apply the kustomization
flux reconcile kustomization apps
Key insight: Flux has a two-stage pipeline: 1. Source controller fetches from git → caches artifacts 2. Kustomize controller applies from cached artifacts
If you only reconcile the kustomization, it uses whatever revision the source already has cached.
Verification Commands
Check what revision Flux has cached
kubectl get gitrepository -n flux-system flux-system -o jsonpath='{.status.artifact.revision}'
Check what revision each kustomization has applied
kubectl get kustomization -n flux-system -o wide
Verify the 1Password-generated secret exists
kubectl get secret linkding-container-env -n linkding -o yaml
Check the linkding pod restarted
kubectl get pods -n linkding
Files Modified
- apps/base/linkding/deployment.yaml — Changed envFrom to explicit env mapping
- apps/staging/linkding/linkding-container-env-secret.yaml — OnePasswordItem with itemPath
- apps/staging/linkding/kustomization.yaml — Removed SOPS secret reference
Key Takeaways
- envFrom vs env: Use envFrom when secret keys match env var names; use env with valueFrom.secretKeyRef when you need to rename them
- Flux reconciliation order: Source first (flux reconcile source git), then kustomization
- auto-restart annotation: Add operator.1password.io/auto-restart: "true" to automatically restart pods when secrets change