Secret management
TeslaSync's Helm chart has three mutually exclusive secret modes. No mode generates credentials during rendering, so repeated helm template, Argo CD, and Flux reconciliations are deterministic.
Chart-managed Secret
Chart-managed credentials are explicit opt-in for an interactive local installation. Set secrets.create=true and provide strong PostgreSQL and, when enabled, Grafana passwords. Blank values fail rendering; the chart never falls back to lookup plus a newly generated value.
Known weak values such as teslasync, changeme, password, postgres, and the configured username are rejected during template rendering.
secrets:
create: true
postgresql:
auth:
password: <strong-local-password>
grafana:
adminPassword: <different-strong-local-password>Do not put these values in a checked-in file or shell history. GitOps and offline workflows must use an existing Secret or External Secrets Operator.
Existing Kubernetes Secret
This is the default mode. With secrets.create=false, secrets.existingSecret="", and External Secrets disabled, every workload references the release-scoped <release>-teslasync Secret without rendering it. Provision that Secret before installation. Set secrets.existingSecret for a differently named Secret managed by SOPS, Sealed Secrets, or another GitOps process:
secrets:
existingSecret: teslasync-runtimeAt minimum, the Secret needs DATABASE_PASS. Bundled Grafana also requires GRAFANA_ADMIN_PASSWORD; Tesla Fleet API access requires TESLA_CLIENT_ID and TESLA_CLIENT_SECRET. Add the integration keys documented in values.yaml when those features are enabled.
External Secrets Operator
Set externalSecrets.enabled to let External Secrets Operator materialize the runtime Kubernetes Secret from Vault, AWS Secrets Manager, Azure Key Vault, or Google Secret Manager. The chart creates an ExternalSecret; platform owners create the SecretStore or ClusterSecretStore separately so cloud workload identity and provider permissions remain outside the application release.
An extract-style remote object is the simplest setup:
externalSecrets:
enabled: true
refreshInterval: 1h
secretStoreRef:
name: production-secrets
kind: ClusterSecretStore
target:
name: teslasync-runtime
creationPolicy: Owner
deletionPolicy: Retain
dataFrom:
- extract:
key: teslasync/productionThe remote object must expose keys named like the environment variables: DATABASE_PASS, GRAFANA_ADMIN_PASSWORD, TESLA_CLIENT_ID, TESLA_CLIENT_SECRET, and any enabled optional integration keys.
For stores where secrets are separate objects, map them explicitly:
externalSecrets:
enabled: true
secretStoreRef:
name: production-secrets
kind: ClusterSecretStore
data:
- secretKey: DATABASE_PASS
remoteRef:
key: teslasync/production/database-password
- secretKey: TESLA_CLIENT_SECRET
remoteRef:
key: teslasync/production/tesla-client-secretAWS Secrets Manager values remain protected by the KMS key configured on the store. Vault, Azure Key Vault, and Google Secret Manager use their native encryption and identity controls. Grant the External Secrets workload identity read access only to the TeslaSync paths.
Environment variables are read when a pod starts. After rotating a remote value, restart the affected TeslaSync workloads (or use a Secret-aware rollout controller) after the ExternalSecret reports Ready=True.
Verification
helm lint helm/teslasync --strict
helm template test helm/teslasync
# Repeated offline renders must be byte-identical and contain no Secret.
helm template test helm/teslasync > /tmp/render-1.yaml
helm template test helm/teslasync > /tmp/render-2.yaml
cmp /tmp/render-1.yaml /tmp/render-2.yaml
! grep -q '^kind: Secret$' /tmp/render-1.yaml
# Weak credentials must be refused.
helm template test helm/teslasync \
--set secrets.create=true \
--set-string postgresql.auth.password=teslasync