Roadmap
⚠️ marks items that are breaking changes — existing values files or behaviour will need to be updated.
Standard
StatefulSet and DaemonSet support
The single largest missing feature. Deployments alone cannot cover:
- StatefulSet — stable network identity and ordered scaling required by databases, message queues, Elasticsearch, Redis clusters, and any application that uses
volumeClaimTemplatesfor per-pod storage - DaemonSet — one pod per node, required for log shippers, monitoring agents, CNI plugins, and node-level storage drivers
The natural design is a workloadType: field per entry, defaulting to Deployment:
deployments:
postgres:
workloadType: StatefulSet
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
fluentd:
workloadType: DaemonSetStatefulSet-specific additions needed alongside this:
updateStrategy(vsstrategyon Deployment)podManagementPolicy(OrderedReady vs Parallel)volumeClaimTemplatesserviceNamefor headless service binding- Headless service support (
clusterIP: None) inservices:
Template fixes and inconsistencies
PVC safe-by-default: annotate all generated PVCs with
"helm.sh/resource-policy": keepso Helm never deletes them duringhelm uninstall, a release rename, or anameOverridechange. Without this annotation, renaming the release or changingnameOverridecauses Helm to silently create a new empty PVC and delete the old one —helm upgradedoes not error or warn, it just proceeds. Kubernetes'spvc-protectionfinalizer delays the deletion until pods stop using the old PVC, but once the new Deployment is running the old PVC is gone. The annotation makes deletion always explicit (kubectl delete pvc). Add apersistence.<key>.delete: trueopt-in for cases where automatic cleanup is actually desired.Wire top-level
portNumber,healthChecks, andresourcesshorthands into the default container of thedeployment:shorthand (currently documented but not consumed by any template)Remove
metadata.namefrom Job pod templates — Kubernetes ignores pod template names in Jobs, it is unnecessary clutterMake Sealed Secret scope configurable (
cluster-widevsnamespace-wide) instead of hardcodingcluster-wide: truein the templateRemove
_port.tplstub or implement it — currently dead codeAdd
values.schema.json— typos in values keys are silently ignored today; schema validation would catch them athelm installtimeAdd missing checksum annotation for
mountedSealedSecretFilesin deployment pod annotations — changes to sealed secret files currently do not trigger a pod rollout
Configuration improvements
commonLabels/commonAnnotations— apply extra labels and annotations to every generated resource (Deployment, Service, Ingress, PVC, etc.) without having to set them per-resourcepodLabels— extra labels added only to the pod template, not to the Deployment/selector labels; required by Istio, Karpenter, Datadog APM, and other tooling that needs pod-level labels without affecting selectorsexistingSecretpattern — allow referencing a pre-existing Secret by name instead of managing secret values through Helm (plays well with External Secrets Operator, Vault, and avoids values in release history)env/envFrommerging — currently first-wins (container overrides pod overrides global); support additive merging so global base env vars can be combined with per-container additionsenv.valueFrom/ downward API — document and testvalueFrom.fieldRef(pod name, namespace, node name) andvalueFrom.resourceFieldRef(CPU/memory limits as env vars); these work in list-style env today but are undocumented and untested- Per-resource
variables,secrets,mountedFiles, etc. — allow scoping config to a specific deployment, cronJob, or job with resource-unique names (e.g.{fullname}-{resourcename}-variables) so different workloads in the same release can carry their own isolated configuration without sharing the global ConfigMap/Secret podAntiAffinityshorthand — the most common affinity use case (spread pods across nodes/zones) requires a verbose block today; apodAntiAffinity: soft | hardshorthand would cover 90% of cases- Per-PVC annotations — no way to annotate PVCs today; needed for Velero backup policies, storage class migration tooling, and cloud-provider hints
- Support
service.port: 80scalar shorthand that expands intoservice.ports.http.port: 80automatically workingDiron containers — set the working directory inside the container; some applications (Python, Node.js) require this to match the application rootimageas string or dict on all container types —initContainers,sidecarContainers, and namedcontainerscurrently require a full image reference string. Support a dict form that is merged with the globalimage:so only the differing fields need to be specified:yamlThe dict form uses the same fields as the top-level# Current — full string required initContainers: init-data: image: busybox:1.36 # Proposed — string still works initContainers: init-data: image: busybox:1.36 # Proposed — dict merged with global image: initContainers: init-data: image: name: busybox tag: "1.36" # registry and repository inherited from global image:image:block (registry,repository,name,tag) and is shallow-merged so only the specified keys override the global values.- Fix
test-connection.yamlto use the service'sresourcefullnameinstead of the globalfullname, and make the test image configurable instead of hardcodingbusybox imagePullSecretsdict mode — allow specifying registry credentials directly in values and have the chart generate thekubernetes.io/dockerconfigjsonSecret automatically, instead of requiring users to pre-create the secret out of band:yamlThe generated Secret name is then injected into the podimagePullSecrets: my-registry: registry: registry.example.com username: myuser password: mypasswordimagePullSecretslist automatically. The existing list-of-name-references behaviour is preserved for referencing pre-existing secrets.
Security defaults
Harden the default securityContext to match modern best-practice baselines. Stakater defaults to readOnlyRootFilesystem: true and runAsNonRoot: true; this chart currently defaults to empty {}. The right posture is secure-by-default with explicit opt-out:
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop: [ALL]⚠️ Breaking change for applications that write to the filesystem or run as root — needs a migration note and a clear securityContext: {} opt-out path.
Missing Kubernetes features (high value)
podDisruptionBudget—minAvailable/maxUnavailableto protect against node drains taking down all pods simultaneouslylifecycleHooks—preStop/postStarthooks on containers; thepreStop: sleep Npattern is essential for graceful shutdown behind cloud load balancersterminationGracePeriodSeconds— expose at pod level alongsidelifecycleHookstopologySpreadConstraints— spread pods across zones and nodes; the modern replacement for pod anti-affinity rulesrevisionHistoryLimit— control how many old ReplicaSets Kubernetes retains (default 10 adds noise; most charts use 3)startupProbeas an explicit first-class sibling toreadinessProbeandlivenessProbeinhealthChecks— essential for slow-starting applications (JVM, large Python apps) to avoid liveness probes killing a legitimately slow boot
Missing Kubernetes features (medium value)
networkPolicy— NetworkPolicy resource gated behindnetworkPolicy.enabledpriorityClassName— assign PriorityClass to pods for eviction ordering under node pressureminReadySeconds— delay marking a pod available until it has been running N seconds; guards against crashlooping pods receiving traffic immediatelyautomountServiceAccountToken: falseas the default on ServiceAccount — more secure default aligned with hardened chartshostAliases— inject/etc/hostsentries into pods for split-horizon DNS or local overridesdnsPolicy/dnsConfig— custom DNS settings for pods that need non-default resolutionexternalTrafficPolicyon Services — controls whether NodePort/LoadBalancer preserves source IP (LocalvsCluster); important for security auditing and rate limiting by real client IPsessionAffinityon Services —ClientIPstickiness for WebSocket connections and session-heavy applicationsshareProcessNamespace— lets sidecar containers inspect the main container's process tree; useful for signal forwarding and debug sidecars- Headless services (
clusterIP: None) and ExternalName services — headless is required for StatefulSets to get stable per-pod DNS; ExternalName aliases external services inside the cluster - ExternalName service type —
type: ExternalNamewith anexternalNamefield that creates a CNAME DNS alias to an external hostname; useful for abstracting external databases, third-party APIs, or cross-namespace service references behind an in-cluster DNS name. Requires skippingportsandselectorin the rendered spec and suppressing the test-connection pod for that service:yamlservices: external-db: type: ExternalName externalName: postgres.example.com
Velero backup schedules
First-class Velero integration following the same pattern as cronJobs: — named entries that generate Velero Schedule CRs, with sane defaults and a bare-key convention:
backups:
daily: # bare key → uses all defaults
weekly:
schedule: "@weekly"
ttl: 2160h # 90 days
storageLocation: offsite
database:
schedule: "0 1 * * *"
includedResources:
- persistentvolumeclaims
labelSelector:
app.kubernetes.io/component: databaseDefaults:
schedule: "@daily"ttl: 720h(30 days)storageLocation: defaultlabelSelector— the chart's own selector labels so only this release's resources are included
Note: Velero can also be configured at the server level to back up all PVCs automatically without any per-chart config. The backups: feature is for releases that need explicit schedules, custom retention, or multiple backup destinations.
Ecosystem integrations
- Full observability stack — when
metrics.enabled: true, generate the complete set alongsideServiceMonitor:PrometheusRule(alerting rules),GrafanaDashboard, andAlertmanagerConfig; stakater generates all four as a unit which is more useful than ServiceMonitor alone - ExternalSecrets —
ExternalSecretresource as a first-class alternative to Sealed Secrets for teams using Vault, AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault via the External Secrets Operator; Sealed Secrets stays for GitOps-pure setups, ExternalSecrets for operator-based workflows - KEDA —
ScaledObjectresource generation as an alternative to HPA; enables event-driven autoscaling on queue depth, Kafka lag, cron schedules, and custom metrics without requiring users to write the CRD by hand global.imageRegistry/global.imagePullSecrets— standard Bitnamiglobal.*keys so this chart works correctly as a sub-chart in umbrella deploymentsdiagnosticMode— override pod command withsleep infinityfor live debugging without changing real configuration; Bitnami pattern- RBAC — optional
Role/RoleBinding/ClusterRole/ClusterRoleBindinggeneration tied to the chart's ServiceAccount cert-managerCertificate resource — generate acert-manager.io/v1 CertificateCR directly (not just an Ingress annotation) for wildcard certificates, multiple SANs, or certificates used outside Ingress; gated behindcertManager.enabled: true
Future / long-term
- Networking platform abstraction — a
networking.type: Ingress | HTTPRoutefield that switches which resource type is generated; allows Gateway API migration without restructuring values; OpenShift Routes are intentionally out of scope — they can be added viaextraManifests - Canary / blue-green deployment — patterns for Argo Rollouts or Flagger integration via
extraManifestsor dedicated annotation shortcuts - Vertical Pod Autoscaler (VPA) — complement to HPA for right-sizing resource requests; gated behind
autoscaling.vpa.enabled
Template rendering in values
Support Go template expressions inside string values so users can reference release metadata or other values without hardcoding them:
variables:
APP_URL: "https://{{ .Release.Name }}.example.com"Values containing template expressions would need to be explicitly opted in (e.g. via a tpl: prefix or a dedicated tplValues: block) to avoid breaking existing plain-string values.
Documentation
The goal is documentation that exceeds bjw-s/app-template and Bitnami — both rated Excellent in the comparison table. Parity items close the gap; differentiator items go beyond what those charts offer because they cover features unique to this chart.
Parity — match the best charts
- Values reference table — every configurable key with type, default, and description in one scannable table; the first thing users look for and currently missing entirely
- Getting started guide — walks from zero to a running deployment: add repo → write a minimal
values.yaml→ install → verify; the current Install section is just two shell commands - Worked examples for common application types — at minimum: simple web app (image + service + ingress + TLS), app with secrets, multi-workload (API + worker), app with persistence; showing realistic complete
values.yamlfiles values.schema.json— enables IDE hover tooltips and inline validation when writing values files; turns passive docs into active docs (also listed under Template fixes)UPGRADING.md— breaking changes listed per version, separate from the CHANGELOG; operators need a quick reference for what to update on each bump- Expand
tests/README.md— how to run tests (make tests,make test TEST=name), how golden-file comparison works, how to add a new test case - Add
CONTRIBUTING.md— how to add a new template feature end-to-end, coding conventions, test requirements, commit message style
Differentiators — beyond what other charts document
configure.*guide — explain all six flags, how they cascade (global → pod → container), why init/sidecar containers are opt-in, before/after examples of enabling per container; unique to this chart and currently undocumented- Multi-workload cookbook — dedicated guide for defining frontend + API + worker + shared secrets in one
values.yaml; unique feature with no equivalent in competing charts - Environment and secrets comparison — when to use
envvsvariablesvssecretsvssealedSecretsvsenvFrom; trade-offs around GitOps safety, Helm history exposure, and external operator compatibility - Sealed Secrets guide — walk through: generate key → seal a secret → deploy → verify; cover both env-var and file-mount patterns; unique feature
- Base chart authoring guide — how to build an app-specific chart on top of
standard; coverChart.yamldependency declaration, nesting config understandard:, settingchartName/version, and what belongs in chart defaults vs operator config; the existing charts in this repository (archivebox, bookstack, akeneo, etc.) serve as reference implementations - GitOps deployment guide — complete ArgoCD/Flux setup with Sealed Secrets, per-environment values files, and the
releaseNameoverride pattern - GitLab CI/CD guide — deploying with
helm upgrade --installin GitLab pipelines; environment-specific values files, review app patterns, and integration with GitLab Environments - GitHub Actions guide — deploying with
helm upgrade --installin GitHub Actions; OIDC-based cluster auth, environment-specific values files, and PR preview deployments - Datadog guide — enabling APM injection, log collection, and unified service tagging via
podAnnotationsandpodLabels - OpenTelemetry guide — sidecar collector pattern using
sidecarContainers:with opt-inconfigureflags; covers trace export, resource attributes, and collector config as a mounted file - Velero backup guide — documenting pod annotations for file-system backup and when server-side Velero auto-backup is sufficient (already started in README)
debug: truereference — what it renders, when to use it, and how to read the output; currently undocumented despite being the primary troubleshooting tool- Architecture overview — template hierarchy (
_helpers.tpl,_pod.tpl,_container.tpl), how context is passed between templates, how the configure inheritance chain works; useful for contributors and chart authors