Agent instructions, skills, SSH host aliases and expansion triggers are worth having identical on every machine one person owns, and belong in none of the shared configuration. They live in user/ now, with a manifest saying where each piece goes and a link-user stage that puts it there. That stage does nothing unless the machine said yes. Somebody who clones Panama to try the desktop keeps their own ~/.claude/CLAUDE.md exactly where it was; the question names the destinations and defaults to no. Anything displaced goes to config/old rather than being deleted. ~/.claude/CLAUDE.md and ~/.codex/AGENTS.md were byte-identical copies of one file, which is the drift this exists to prevent. Also adds the vitals toggles for the battery and Claude usage readouts, which had preferences and no way to reach them.
6.0 KiB
Kubernetes Operator
The Infisical Secrets Operator syncs secrets from Infisical into Kubernetes Secrets, so pods can consume them as env vars or volume mounts without application-level SDK integration.
Supported versions
Kubernetes: 1.29 – 1.33. Distributions: EKS, GKE, AKS, OKE, OpenShift.
Installation
# Add the Helm repo
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
# Cluster-wide install
helm install --generate-name infisical-helm-charts/secrets-operator
# Namespace-scoped install (if you want to limit the operator's reach)
helm install operator-namespaced infisical-helm-charts/secrets-operator \
--namespace my-namespace \
--set scopedNamespaces=my-namespace \
--set scopedRBAC=true
Connecting to Infisical
By default the operator talks to https://app.infisical.com/api. For self-hosted instances, configure via ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: infisical-config
namespace: infisical-operator-system
data:
hostAPI: https://your-instance.com/api
For in-cluster Infisical: http://<service-name>.<namespace>.svc.cluster.local:4000/api
For custom/self-signed CA certificates:
data:
hostAPI: https://your-instance.com/api
tls.caRef.secretName: custom-ca-certificate
tls.caRef.secretNamespace: default
tls.caRef.key: ca.crt
CRD 1: InfisicalSecret (pull secrets into K8s)
This is the most common use case — syncing secrets from Infisical into a Kubernetes Secret.
Step 1: Create auth credentials
kubectl create secret generic universal-auth-credentials \
--from-literal=clientId="<your-client-id>" \
--from-literal=clientSecret="<your-client-secret>"
Important: The user should create their own machine identity and credentials in the Infisical dashboard. Never generate these on their behalf.
Step 2: Create the InfisicalSecret resource
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: my-app-secrets
spec:
hostAPI: https://app.infisical.com/api
syncConfig:
resyncInterval: 60s
instantUpdates: false
authentication:
universalAuth:
secretsScope:
projectSlug: my-project
envSlug: prod
secretsPath: "/"
credentialsRef:
secretName: universal-auth-credentials
secretNamespace: default
managedKubeSecretReferences:
- secretName: my-app-managed-secret
secretNamespace: default
creationPolicy: "Orphan"
Step 3: Use in your deployment
envFrom:
- secretRef:
name: my-app-managed-secret
Auth methods for Kubernetes
Universal Auth (shown above) — simplest, works anywhere.
Kubernetes Auth (recommended for K8s) — zero-secret, uses pod service account tokens:
- Create a token reviewer service account with
system:auth-delegatorrole - Create a service account for your workload
- Configure the identity with Kubernetes Auth in the Infisical dashboard
- Reference in the CRD:
authentication:
kubernetesAuth:
identityId: <identity-id>
secretsScope:
projectSlug: my-project
envSlug: prod
secretsPath: "/"
serviceAccountRef:
name: my-service-account
namespace: default
With autoCreateServiceAccountToken: true, the operator handles token lifecycle automatically.
Resync interval
- Default: 1 minute (if instantUpdates=false), 1 hour (if instantUpdates=true)
- Minimum: 5 seconds
- Format:
[number][unit]—s,m,h,d,w
Templating
Use Go templates with Sprig functions to transform secrets:
managedKubeSecretReferences:
- secretName: my-tls-secret
secretNamespace: default
template:
data:
tls.crt: "{{ .secrets.TLS_CERT | b64dec }}"
tls.key: "{{ .secrets.TLS_KEY | b64dec }}"
CRD 2: InfisicalPushSecret (push K8s secrets to Infisical)
Pushes secrets from Kubernetes into Infisical — useful for bootstrapping or migration.
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalPushSecret
metadata:
name: push-to-infisical
spec:
resyncInterval: 1m
hostAPI: https://app.infisical.com/api
updatePolicy: Replace # None (skip if exists) or Replace (overwrite)
deletionPolicy: Delete # None (leave in Infisical) or Delete (remove when CRD deleted)
destination:
projectId: <project-id>
environmentSlug: prod
secretsPath: /
push:
secret:
secretName: my-k8s-secret
secretNamespace: default
authentication:
universalAuth:
credentialsRef:
secretName: universal-auth-credentials
secretNamespace: default
CRD 3: InfisicalDynamicSecret (dynamic secret leases)
Generates short-lived credentials (e.g., database passwords) and syncs them to K8s:
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalDynamicSecret
metadata:
name: dynamic-db-creds
spec:
hostAPI: https://app.infisical.com/api
dynamicSecret:
secretName: postgres-dynamic
projectId: <project-id>
secretsPath: /
environmentSlug: prod
leaseRevocationPolicy: Revoke # Revoke lease when CRD is deleted
leaseTTL: 30m # Max 24h
managedSecretReference:
secretName: db-credentials
secretNamespace: default
creationPolicy: Orphan
authentication:
universalAuth:
credentialsRef:
secretName: universal-auth-credentials
secretNamespace: default
The operator automatically rotates the lease before expiration.
Monitoring
The operator exposes Prometheus metrics. Enable ServiceMonitor:
# In Helm values
telemetry:
serviceMonitor:
enabled: true
interval: 30s
Key metrics: controller_runtime_reconcile_total, controller_runtime_reconcile_errors_total, controller_runtime_reconcile_time_seconds.
Troubleshooting
Check the status of an InfisicalSecret:
kubectl get infisicalsecret my-app-secrets -o yaml
Look at status.conditions for error details. Common issues: wrong project slug, missing permissions on the machine identity, credentials secret not found.