on
Packaging Helm charts to OCI registries and keeping values secure
Helm remains the go-to packaging tool for Kubernetes apps. Two recent shifts are shaping how teams package and distribute charts in production: first, the move to OCI-based registries for chart storage and delivery; second, the need to keep environment-specific values out of plaintext in repos by using tools like Mozilla SOPS and the helm-secrets plugin. This article walks through a compact, practical workflow that combines OCI publishing, automated semantic versioning, and encrypted values so your chart releases are reproducible, discoverable, and safe to store in Git.
Why this matters now
- Helm supports storing charts in OCI registries (so you can co-locate images and charts in the same artifact store). (helm.sh)
- The Helm project recently shipped Helm 4 and set an end-of-life schedule for older Helm 3 clients, so modern workflows should be OCI-aware and Helm-4-compatible. (helm.sh)
- Teams shipping many charts benefit from automation that versions and publishes charts consistently to OCI registries; community tools now fill that gap. (pkg.go.dev)
A concise hands-on workflow 1) Author a chart as usual
- Use helm create myapp and keep environment overrides in separate values files (values-dev.yaml, values-prod.yaml). Keep secrets out of these plain files; encrypt sensitive values (next section).
2) Package the chart
- Build a chart package tarball that contains Chart.yaml (with a SemVer chart version) and templates:
helm package ./myapp # produces myapp-0.3.0.tgz (version comes from Chart.yaml) - Helm requires the chart package tag to match the chart version when pushing to OCI registries. (helm.sh)
3) Publish to an OCI registry
- Login to the registry (domain-scoped login is emphasized in Helm 4):
echo "$REGISTRY_PASSWORD" | helm registry login my-registry.example.com -u myuser --password-stdin - Push the chart tarball:
helm push myapp-0.3.0.tgz oci://my-registry.example.com/helm-charts # Result: my-registry.example.com/helm-charts/myapp:0.3.0 - OCI registries store charts as artifacts. Not all registries support Helm artifacts — confirm provider support. (helm.sh)
4) Automate semantic versioning and publishing in CI
- Manual version bumps are error-prone. Tools such as helm-semver (and other CI helpers) read commit history (Conventional Commits), bump Chart.yaml versions, package charts, and push them to OCI in a single pipeline step — ideal for monorepos and multi-chart repos. Integrate that into your CI pipeline to ensure consistent, repeatable chart releases. (pkg.go.dev)
Keeping secret values out of plaintext
- Kubernetes Secrets in manifests are base64-encoded, not encrypted by default; cluster operators should enable etcd-at-rest encryption and follow least-privilege access patterns. Storing secret data in your Git repo in plaintext is unsafe. (kubernetes.io)
Use SOPS + helm-secrets for Git-stored encrypted values
- Mozilla SOPS encrypts YAML/JSON files using KMS, GPG, or Age keys. The helm-secrets plugin integrates SOPS into the Helm workflow so encrypted values files can live in Git and be decrypted at deployment time by authorized CI agents or dev machines. Typical commands:
```
install sops and the helm-secrets plugin (example)
brew install sops helm plugin install https://github.com/jkroepke/helm-secrets
encrypt a values file locally
sops -e -i values-prod.yaml
with helm-secrets, helm commands can use encrypted files transparently
helm secrets upgrade –install myapp oci://my-registry.example.com/helm-charts/myapp –values values-prod.yaml
- The helm-secrets plugin remains widely used and integrates with SOPS backends (GPG, Age, cloud KMS). As always, ensure the decrypting identities are controlled (CI service accounts, key material guarded). ([github.com](https://github.com/jkroepke/helm-secrets/issues?utm_source=openai))
Practical tips and gotchas
- Chart names and tags: When you push a chart to an OCI registry, the registry path basename must match the chart name and the tag must match the chart’s semver version — you cannot push a chart with a non-semver tag like latest. Plan your Chart.yaml naming/versioning accordingly. ([helm.sh](https://helm.sh/docs/v3/topics/registries/))
- Registry feature parity: OCI registries don’t provide the same search/discovery APIs as traditional chart repos; Artifact Hub can list OCI-backed charts, but consider your discovery needs when you choose a registry. ([docs.helm.sh](https://docs.helm.sh/blog/storing-charts-in-oci/))
- CI secrets and key management: Your CI runner or GitOps agent must have secure access to SOPS keys/KMS permissions to decrypt values. Do not bake keys into images or expose them in pipeline logs. Follow least-privilege and rotate keys regularly. ([kubernetes.io](https://kubernetes.io/docs/concepts/security/secrets-good-practices/))
- Plugin compatibility: Helm’s plugin subsystem changed in Helm 4 (including an optional WebAssembly runtime and some CLI flag renames). Test plugins (like helm-secrets) against your Helm version in a staging pipeline to catch compatibility issues early. ([helm.sh](https://helm.sh/blog/helm-v3-end-of-life/))
Example minimal CI snippet (conceptual)
- This is a short conceptual snippet showing the sequence inside a CI job (assumes helm-semver or similar tool is in use to bump and package):
login
echo “$REGISTRY_PASSWORD” | helm registry login my-registry.example.com -u ci-user –password-stdin
decrypt values using CI-held key material (sops uses KMS/GPG/age under the hood)
sops -d values-prod.yaml > values-prod.dec.yaml
install/upgrade from OCI registry
helm upgrade –install myapp oci://my-registry.example.com/helm-charts/myapp –values values-prod.dec.yaml ``` (Replace the sops usage with helm-secrets wrapper if you prefer plugin-driven decryption.)
A short security reminder Encrypting values in Git reduces exposure, but you should still rely on cluster-side protections: enable encryption at rest for etcd, limit who can read Secrets, avoid logging secret contents, and rotate credentials regularly. The Kubernetes docs include a thorough set of good practices for Secrets that are worth reviewing for your environment. (kubernetes.io)
Final note (summary) OCI registries and encrypted values are complementary changes that modernize a Helm packaging pipeline: OCI makes distribution cleaner and co-locates artifacts, while SOPS + helm-secrets keeps sensitive configuration safe in GitOps workflows. Together with semantic-versioned automation in CI, you get reproducible chart releases that play well with Helm 4’s modernized CLI and plugin model. (helm.sh)
References
- Use OCI-based registries (Helm docs). (helm.sh)
- Storing Helm Charts in OCI Registries (Helm blog). (docs.helm.sh)
- Helm 3 End of Life / Helm 4 overview (Helm blog). (helm.sh)
- helm-semver (semantic version automation for charts). (pkg.go.dev)
- jkroepke/helm-secrets plugin and SOPS ecosystem references. (github.com)
- Kubernetes: Good practices for Secrets. (kubernetes.io)