Skip to main content
charts ships site — a Helm chart that deploys a single FrankenPress WordPress site to Kubernetes. Bitnami chart style throughout: every value annotated with ## @param, naming + labels via the bitnami/common library, optional subchart deps via the Bitnami OCI registry.

Install

The chart is published as an OCI artifact on GHCR:
For the kind-cluster quickstart, see Quickstart. For the production topology (DragonflyDB Operator, MariaDB Operator, AWS S3, External Secrets), see Operations → Production topology.

What gets deployed

The install Job is new in chart v0.2.0 — fresh deploys produce a usable site without manual kubectl exec ... wp core install. The sync-admin-credentials initContainer (chart v0.4.0+) reconciles wp_users from the install Secret on every Pod start. See First install for credentials and Operations → Admin credential rotation for the rotation flow.

Subchart dependencies

Bitnami withdrew their bitnami/<name> images from free public Docker Hub in 2025 (“Bitnami Secure Images” commercial pivot). The chart’s default values point at the bitnamilegacy/<name> mirror Bitnami publishes for community use. We track this as a Renovate concern; see the values.yaml comments.

Values reference

The full annotated values reference is in charts/site/values.yaml; the most-used keys: A condensed reference is at Operations → Configuration. The chart deliberately doesn’t ship a log shipper — pod streams are backend-neutral and any cluster-side agent picks them up. Setup for Vector / Grafana Alloy / Datadog Agent is in Operations → Logging.

First install

The chart runs wp core install and wp core update-db from a post-install/post-upgrade Helm hook Job — a fresh helm install produces a usable WordPress site without any manual kubectl exec. The install step is idempotent (wp core is-installed short-circuits re-runs), so the Job is safe across helm upgrades.

Default behavior

By default, the chart creates a <release>-site-install Secret with a random 32-char admin password. Retrieve it after install:
Override the username, email, or password at install:

Bring-your-own Secret

Point at a pre-existing Secret with the admin credentials:
The chart doesn’t care how the Secret got there — kubectl create secret, External Secrets Operator (any provider: AWS Secrets Manager, GCP Secret Manager, Vault, 1Password), Sealed Secrets, SOPS-decrypted, anything works. The configurable key names let the Secret use whatever schema the source system produces.
Already running with auto-generated credentials and now want to move them into your secret manager? See Production → Migrating auto-generated Secrets to a secret manager for the kubectl get secret -o json | jq extract commands (also covers WP keys+salts and the DB / S3 Secrets).

Password rotation

WordPress stores a hash of the admin password in wp_users, so simply updating the Secret value won’t change the live login. The chart’s sync-admin-credentials initContainer (default on) handles this on every Pod start — pair it with Stakater Reloader so the Pod actually rolls when the Secret changes:
Once that’s wired, the full flow is automatic:
Idempotent and multi-replica safe — only the first Pod to roll runs wp user update; subsequent Pods see the DB in sync and short-circuit. One DB write, one WP “Password Changed” notification per rotation, regardless of replica count. Full setup, verification, failure modes, and the syncAdminCredentials: false opt-out are in Operations → Admin credential rotation. The database password rotates differently — the Deployment, wpcron CronJob, and install Job all read DB_PASSWORD from secretKeyRef, so when the Secret value changes, restarting pods picks up the new value automatically. No chart-side reconciliation needed (and Reloader handles the restart trigger).

Skipping install

For sites being restored from an existing database dump:
wp core update-db is skipped too, so make sure your dump is schema-compatible with the WP core version baked into the site image. If it isn’t, re-enable the Job after restore — wp core is-installed will short-circuit and only update-db will run.

Production overrides example

CI / publishing

  • lint.yml — helm lint + helm template + chart-testing ct lint on every push and PR.
  • release.yml — on v*.*.* tag push, helm package + push to oci://ghcr.io/frankenpress/charts/site:<version>. Tag-driven, never push-to-main-driven, so Chart.yaml version and the git tag move together. OCI is the canonical channel — no gh-pages fallback.