Skip to main content
CleanStart

Knowledge Hub

Bitnami Helm Chart Values: CleanStart Drop-In Reference

Bitnami Helm charts are the most widely used open-source Helm charts in production Kubernetes environments. CleanStart images work as drop-in replacements in Bitnami charts because they maintain API compatibility while adding security hardening, reduced attack surface, and verifiable provenance. This reference shows exactly which values.yaml fields to change and which to keep unchanged.

How Bitnami Charts Work

Bitnami Helm charts follow a consistent structure where a values.yaml file provides default configuration, Jinja2 templates consume these values, and the templates generate Kubernetes manifests. The key integration point for container images lives in the image: section of values.yaml. This section contains the registry (where the image comes from), the repository (the image name), and the tag (version). These three fields determine which container image Kubernetes pulls, while everything else—persistence, networking, RBAC, resource limits—remains unchanged. This is why migrating to CleanStart images requires modifying only this section.

The Universal Swap Pattern

Every Bitnami chart to CleanStart migration follows the same three-line pattern. The before state shows Bitnami with registry docker.io, repository bitnami/postgresql, and tag 15.2-debian-11-r0. The after state shows CleanStart with registry registry.cleanstart.com, repository cleanstart/postgresql, and tag 15.2. You should change three fields: image.registry becomes registry.cleanstart.com, image.repository becomes cleanstart/{app-name}, and image.tag becomes the matching version (use 15.2, not Bitnami's full suffix).

Every other value in the chart remains identical. CleanStart images inherit the same interface, environment variables, volumes, and configuration patterns as Bitnami equivalents.

Complete values.yaml Examples

PostgreSQL with CleanStart

# PostgreSQL Helm Chart - values.yaml with CleanStart Imagesglobal:  postgresql:    auth:      username: appuser      password: "changeme-in-production"      database: appdb image:  registry: registry.cleanstart.com  repository: cleanstart/postgresql  tag: "15.2"  pullPolicy: IfNotPresent auth:  username: appuser  password: "changeme-in-production"  database: appdb primary:  persistence:    enabled: true    size: 10Gi    storageClassName: "standard"   resources:    requests:      memory: "256Mi"      cpu: "250m"    limits:      memory: "512Mi"      cpu: "500m"   securityContext:    enabled: true    fsGroup: 65532    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    capabilities:      drop:        - ALL   containerSecurityContext:    enabled: true    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    allowPrivilegeEscalation: false    capabilities:      drop:        - ALL   livenessProbe:    enabled: true    initialDelaySeconds: 30    periodSeconds: 10    timeoutSeconds: 5    failureThreshold: 6   readinessProbe:    enabled: true    initialDelaySeconds: 5    periodSeconds: 10    timeoutSeconds: 5    failureThreshold: 6 metrics:  enabled: false backup:  enabled: false

Redis with CleanStart

# Redis Helm Chart - values.yaml with CleanStart Imagesarchitecture: standalone image:  registry: registry.cleanstart.com  repository: cleanstart/redis  tag: "7.2"  pullPolicy: IfNotPresent auth:  enabled: true  password: "changeme-in-production" master:  persistence:    enabled: true    size: 8Gi    storageClassName: "standard"   resources:    requests:      memory: "256Mi"      cpu: "100m"    limits:      memory: "512Mi"      cpu: "500m"   securityContext:    enabled: true    fsGroup: 65532    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    capabilities:      drop:        - ALL   containerSecurityContext:    enabled: true    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    allowPrivilegeEscalation: false    capabilities:      drop:        - ALL   livenessProbe:    enabled: true    initialDelaySeconds: 5    periodSeconds: 5    timeoutSeconds: 5    failureThreshold: 5   readinessProbe:    enabled: true    initialDelaySeconds: 5    periodSeconds: 5    timeoutSeconds: 5    failureThreshold: 5 metrics:  enabled: false sentinel:  enabled: false

NGINX with CleanStart

# NGINX Helm Chart - values.yaml with CleanStart ImagesreplicaCount: 2 image:  registry: registry.cleanstart.com  repository: cleanstart/nginx  tag: "1.25"  pullPolicy: IfNotPresent service:  type: LoadBalancer  port: 80  targetPort: 8080 ingress:  enabled: false resources:  requests:    memory: "128Mi"    cpu: "100m"  limits:    memory: "256Mi"    cpu: "250m" securityContext:  enabled: true  fsGroup: 65532  runAsUser: 65532  runAsNonRoot: true  readOnlyRootFilesystem: true  capabilities:    drop:      - ALL containerSecurityContext:  enabled: true  runAsUser: 65532  runAsNonRoot: true  readOnlyRootFilesystem: true  allowPrivilegeEscalation: false  capabilities:    drop:      - ALL livenessProbe:  enabled: true  initialDelaySeconds: 10  periodSeconds: 10 readinessProbe:  enabled: true  initialDelaySeconds: 5  periodSeconds: 5 metrics:  enabled: false persistence:  enabled: false startupProbe:  enabled: false

MongoDB with CleanStart

# MongoDB Helm Chart - values.yaml with CleanStart Imagesarchitecture: standalone image:  registry: registry.cleanstart.com  repository: cleanstart/mongodb  tag: "6.0"  pullPolicy: IfNotPresent auth:  enabled: true  rootPassword: "changeme-in-production"  username: appuser  password: "changeme-in-production"  database: appdb persistence:  enabled: true  size: 20Gi  storageClassName: "standard" resources:  requests:    memory: "512Mi"    cpu: "250m"  limits:    memory: "1Gi"    cpu: "500m" securityContext:  enabled: true  fsGroup: 65532  runAsUser: 65532  runAsNonRoot: true  readOnlyRootFilesystem: true  capabilities:    drop:      - ALL containerSecurityContext:  enabled: true  runAsUser: 65532  runAsNonRoot: true  readOnlyRootFilesystem: true  allowPrivilegeEscalation: false  capabilities:    drop:      - ALL livenessProbe:  enabled: true  initialDelaySeconds: 30  periodSeconds: 10  failureThreshold: 6 readinessProbe:  enabled: true  initialDelaySeconds: 5  periodSeconds: 10  failureThreshold: 6 metrics:  enabled: false replicaSet:  enabled: false

Kafka with CleanStart

# Kafka Helm Chart - values.yaml with CleanStart ImagesreplicaCount: 3 image:  registry: registry.cleanstart.com  repository: cleanstart/kafka  tag: "3.6"  pullPolicy: IfNotPresent broker:  resources:    requests:      memory: "512Mi"      cpu: "250m"    limits:      memory: "1Gi"      cpu: "500m"   persistence:    enabled: true    size: 30Gi    storageClassName: "standard"   securityContext:    enabled: true    fsGroup: 65532    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    capabilities:      drop:        - ALL   containerSecurityContext:    enabled: true    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    allowPrivilegeEscalation: false    capabilities:      drop:        - ALL   livenessProbe:    enabled: true    initialDelaySeconds: 10    periodSeconds: 10   readinessProbe:    enabled: true    initialDelaySeconds: 5    periodSeconds: 10 zookeeper:  enabled: true  image:    registry: registry.cleanstart.com    repository: cleanstart/zookeeper    tag: "3.9"   persistence:    enabled: true    size: 8Gi   resources:    requests:      memory: "256Mi"      cpu: "100m"    limits:      memory: "512Mi"      cpu: "250m" metrics:  kafka:    enabled: false  jmx:    enabled: false

Security Defaults That Come Free

When you swap to CleanStart images in any Bitnami chart, several hardening features activate automatically. CleanStart applications run as UID 65532 (Bitnami uses UID 1001), which is standardized across Linux distributions as the unprivileged "nobody" equivalent, preventing privilege escalation attacks targeting fixed UIDs.

The root filesystem is mounted read-only, so applications write only to /tmp and mounted volumes. This prevents attackers from modifying binaries or system libraries after container start.

CleanStart images contain no shell, no package manager, and no debugging tools. Attackers cannot exec into containers or install backdoors even if they gain container access.

All Linux capabilities are dropped by default (--cap-drop=ALL). The image runs without the ability to load kernel modules, change file ownership, modify network settings, or access raw sockets.

CleanStart offers FIPS 140-3 variants where cryptographic operations use FIPS-validated modules. Request images tagged -fips (e.g., cleanstart/postgresql:15.2-fips) for compliance environments.

Every image includes a Bill of Materials (SBOM) in SPDX format and SLSA Level 3 provenance. Verify with cosign:

cosign verify-attestation \  --certificate-identity-regexp=".*@cleanstart.dev" \  --certificate-oidc-issuer-regexp="https://token.actions.githubusercontent.com" \  registry.cleanstart.com/cleanstart/postgresql:15.2 | jq '.payload | @base64d | fromjson'

Bitnami Values You Can Remove

Several fields in standard Bitnami values.yaml become unnecessary with CleanStart. Remove vulnerability scanning configuration since CleanStart images ship verified and scanned. Simplify or remove custom security contexts for hardening since CleanStart handles these by default. Remove package manager or init container updates since there's no package manager in CleanStart images. Remove shell or debugging sidecars since distroless design has no shell. Simplify vulnerability patch version pinning since CleanStart handles patch updates (use "15.2" instead of "15.2-debian-11-r42").

Handling the UID Difference

Bitnami uses UID 1001; CleanStart uses UID 65532. This affects file permissions in persistent volumes. Choose a migration strategy based on your persistence layer.

Strategy 1: Init Container for Permission Fixes uses a busybox init container to fix ownership before the main container starts. Strategy 2: fsGroup for Automatic Permission Delegation lets Kubernetes automatically chown mounted volumes based on the fsGroup setting. Strategy 3: Replace Volume Content exports data from old pods, deletes old PVCs, deploys with CleanStart, and restores the data. Strategy 4: Accept Temporary Permission Warnings mounts volumes with default Kubernetes permissions and uses fsGroup in securityContext to fix automatically on pod start.

Multi-Service Stack Example

Migrating a full Bitnami-based stack requires changing only the image sections. Here's a complete Helm umbrella chart values.yaml deploying PostgreSQL, Redis, and NGINX with CleanStart images:

# Umbrella Chart - values.yaml with CleanStart Images# Deploy: helm install mystack bitnami/common -f values.yaml postgresql:  enabled: true  auth:    username: postgres    password: "changeme-in-production"    database: appdb   image:    registry: registry.cleanstart.com    repository: cleanstart/postgresql    tag: "15.2"   primary:    persistence:      enabled: true      size: 20Gi     securityContext:      enabled: true      fsGroup: 65532      runAsUser: 65532      runAsNonRoot: true      readOnlyRootFilesystem: true      capabilities:        drop:          - ALL     resources:      requests:        memory: "256Mi"        cpu: "250m"      limits:        memory: "512Mi"        cpu: "500m" redis:  enabled: true  auth:    enabled: true    password: "changeme-in-production"   image:    registry: registry.cleanstart.com    repository: cleanstart/redis    tag: "7.2"   master:    persistence:      enabled: true      size: 10Gi     securityContext:      enabled: true      fsGroup: 65532      runAsUser: 65532      runAsNonRoot: true      readOnlyRootFilesystem: true      capabilities:        drop:          - ALL     resources:      requests:        memory: "256Mi"        cpu: "100m"      limits:        memory: "512Mi"        cpu: "250m" nginx:  enabled: true   image:    registry: registry.cleanstart.com    repository: cleanstart/nginx    tag: "1.25"   replicaCount: 2   service:    type: LoadBalancer    port: 80   securityContext:    enabled: true    fsGroup: 65532    runAsUser: 65532    runAsNonRoot: true    readOnlyRootFilesystem: true    capabilities:      drop:        - ALL   resources:    requests:      memory: "128Mi"      cpu: "100m"    limits:      memory: "256Mi"      cpu: "250m"

Deploy the full stack:

helm repo add bitnami https://charts.bitnami.com/bitnamihelm repo add cleanstart https://helm.cleanstart.devhelm repo update helm install mystack bitnami/common \  --values values-cleanstart.yaml \  --namespace production \  --create-namespace

Verifying Your Migration

After deploying CleanStart images via Helm, verify the migration completed correctly.

Check Image References by running kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\n"}{end}'. Expected output includes registry.cleanstart.com/cleanstart/* for all CleanStart services.

Verify Running UID by running kubectl exec -it postgresql-0 -- id. Expected output is uid=65532(nobody) gid=65532(nogroup) groups=65532(nogroup).

Confirm Read-Only Root Filesystem by running kubectl exec -it postgresql-0 -- touch /test-file. Expected error is "Read-only file system".

Verify No Shell Access by running kubectl exec -it postgresql-0 -- /bin/sh. Expected error is "OCI runtime exec failed: exec failed: unable to start container process".

Check Signatures and SBOM using cosign to verify image authenticity and extract SBOM details.

Verify Pod Security Policy Compliance by checking that all CleanStart pods run with UID 65532 and have read-only root filesystem enabled.

Monitor Resource Usage with kubectl top pods to verify CleanStart images typically use 20-30% less memory than Bitnami equivalents.

Cross-References

Migrating from Bitnami: Step-by-Step Guide. Bitnami Compatibility Matrix. Helm Charts in Kubernetes. Helm Fundamentals and Best Practices.