Overview
MySQL is a widely used open-source relational database management system. This template deploys a single-replica MySQL instance with persistent storage, an optional phpMyAdmin web console, and optional scheduled backups to AWS S3 or GCS. Database credentials are not template values. MySQL reads both the application credentials and theroot password from two secrets you create before installing, so no password passes through Helm or lands in the release.
MySQL on Control Plane operates as a single-replica deployment. Do not scale up the replica count, as this would result in multiple isolated instances rather than a replicated cluster.
What Gets Created
- Stateful Workload — (
RELEASE_NAME-mysql): a single-replica MySQL container serving TCP on port3306, with configurable resources. - Volume Set — (
RELEASE_NAME-mysql-vs): anext4volume mounted at/var/lib/mysqlholding all database data, with optional autoscaling. - Identity & Policy — An identity bound to the database and backup workloads, and a policy granting it
revealon exactly the two credential secrets you created — nothing else. When backups are enabled, the identity also carries the Cloud Account binding the backup job uses to reach your bucket. - phpMyAdmin Workload (optional) — (
RELEASE_NAME-mysql-phpmyadmin): a serverless browser console on port80, created whenphpMyAdmin.enabled: true. It has no identity and no access to any secret. - Backup Cron Workload (optional) — (
RELEASE_NAME-mysql-backup): a scheduledmysqldumpto an S3 or GCS bucket, created whenbackup.enabled: true.
This template does not create a GVC. You must deploy it into an existing GVC.
Upgrading From 1.4.3 or Earlier
Template versions up to 1.4.3 took the database credentials as plain Helm values and shipped working defaults for them, and they deployed phpMyAdmin enabled and reachable from the entire internet, with no knob to restrict it short of disabling the console. Version 1.5.0 removes both.1
Read the credentials the database already uses
Credentials are written into the data directory the first time the volume is initialized, so an existing database keeps whatever it was created with. Recover them from your current values file, or from the secret the old version created:The keys are
user, password, database and rootPassword.2
Create the two prerequisite secrets with those same values
Follow Prerequisites, using the existing username, password, database name and root password. Using different values here does not change the database — it just leaves the workload unable to authenticate.
3
Remove the old keys from your values
Delete the entire
config block and enablePhpMyAdmin, then set credentialsSecretName and rootPasswordSecretName to the two secret names. If you were using the console, add phpMyAdmin.enabled: true — it is off by default now, and internal-only unless you also set phpMyAdmin.publicAccess.enabled: true.4
Upgrade, then rotate the passwords
After the upgrade succeeds, change any password that came from a 1.4.x default — those defaults were published in the public template repository, so treat them as compromised. Rotate inside MySQL and update the secret to match:The image creates
root for both localhost and %, so rotating root means changing both. Use your own username in place of appuser, then update the two secrets so the workload can still authenticate after a restart.Prerequisites
Two secrets must exist before you install. They are deliberately separate: an application handedreveal on the database credentials must not also get root. Neither value passes through Helm values, so neither lands in the release. Secrets are org-level, so no GVC flag is involved.
1
Create the application credentials secret
A dictionary secret holding exactly three keys — Set
username, password and database. MySQL creates this user and this database on first boot, and this is the credential your applications put in their connection strings:credentialsSecretName to the name you used.2
Create the root password secret
An opaque secret with encoding Set
plain holding the MySQL root password:rootPasswordSecretName to the name you used.3
Read either secret back later
Installation
To install, follow the instructions for your preferred method:UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
Configuration
The defaultvalues.yaml for this template:
Credentials
credentialsSecretName— Name of the dictionary secret holdingusername,passwordanddatabase. MySQL creates that user and that database on first boot.rootPasswordSecretName— Name of the opaque secret holding therootpassword.
cpln://secret/... references, so the values appear in neither the Helm release nor the stored workload spec.
These credentials are only applied on first startup when the data directory is empty. Rotating either secret afterwards does not change the stored passwords; change them inside MySQL with
ALTER USER and update the secret to match.Resources
resources.minCpu/resources.minMemory— Minimum CPU and memory guaranteed to the workload.resources.maxCpu/resources.maxMemory— Maximum CPU and memory the workload can use.timeoutSeconds— Workload timeout in seconds.
Storage
volumeset.capacity— Initial volume size in GiB (minimum 10).volumeset.autoscaling.enabled— Automatically expand the volume as it fills. When enabled:maxCapacity— Maximum volume size in GiB.minFreePercentage— Trigger a scale-up when free space drops below this percentage.scalingFactor— Multiply the current capacity by this factor when scaling up.
Internal Access
internalAccess.type— Controls which workloads can connect to MySQL on port3306:
The database is never published to the internet by this template. Reach it from inside the GVC, or from outside through your own proxy.
phpMyAdmin
phpMyAdmin.enabled— Whentrue, deploys a phpMyAdmin workload for browser-based database management. Off by default.phpMyAdmin.image— Pinned tophpmyadmin:5.2.3-apachefrom the official Docker library repository.phpMyAdmin.publicAccess.enabled— Whentrue, publishes the console, and its login form, to the whole internet. Off by default.phpMyAdmin.internalAccess— Which workloads may reach the console, using the same four types as the database. This governs the console only; the database has its owninternalAccessknob.phpMyAdmin.resources.cpu/phpMyAdmin.resources.memory— Console resources.
reveal grant, and no password in its environment. It presents a login form, you supply either the application credentials or root plus the root password, and it connects to the database as whoever logged in. Compromising the console container therefore yields no password.
Access changes take up to a couple of minutes to propagate. Enabling public access was measured moving through
421 and 503 before serving 200, settling in about 34 seconds — a request made immediately after the upgrade is not evidence the knob is broken.Backup
Setbackup.enabled: true to enable scheduled database dumps to object storage. The job authenticates as root and dumps the database named in your credentials secret; both come from the same two secrets the database uses.
Set backup.provider to aws or gcp and fill in the corresponding section. The prefix field controls the folder path within the bucket where backups are stored. See Backup Prerequisites for the bucket, Cloud Account and permissions setup.
Backup Prerequisites
Only needed whenbackup.enabled: true.
AWS S3
-
Create an S3 bucket. Set
backup.aws.bucketandbackup.aws.regionin your values file. -
If you do not have a Control Plane Cloud Account set up, follow the Create a Cloud Account guide. Set
backup.aws.cloudAccountNameto the name of your Cloud Account. -
Create an IAM policy with the following JSON, replacing
YOUR_BUCKET_NAME:
- Set
backup.aws.policyNameto the name of the policy created in step 3. The template attaches it to the workload’s identity.
GCS
-
Create a GCS bucket. Set
backup.gcp.bucketin your values file. -
If you do not have a Control Plane Cloud Account set up, follow the Create a Cloud Account guide. Set
backup.gcp.cloudAccountNameto the name of your Cloud Account. -
Add the Storage Admin role to the GCP service account associated with the Cloud Account. The template binds
roles/storage.objectAdminon exactly that bucket.
Restoring a Backup
Run the following from a client with access to the bucket, using theroot password from your rootPasswordSecretName secret. Dumps carry a SET @@GLOBAL.GTID_PURGED statement that must be stripped when loading into a running server:
AWS S3
Connecting
Important Notes
- Create both prerequisite secrets before installing. A reference to a secret that does not exist wedges the workload instead of failing the install.
- Credentials are read only when the volume is first initialized. Rotating a secret afterwards does not change the stored passwords — use
ALTER USERinside MySQL and update the secret to match. - Do not scale past one replica. This is a single instance on a single volume, not a replicated cluster.
- Data lives on the volume set and survives redeploys;
cpln helm uninstalldeletes it, taking the database with it. - Upgrading from 1.4.3 or earlier is a breaking change — the removed keys stop the upgrade rather than resetting a password. See Upgrading From 1.4.3 or Earlier.
External References
MySQL Documentation
Official MySQL documentation
phpMyAdmin Documentation
phpMyAdmin user documentation
Cloud Accounts
Create a Control Plane Cloud Account for backup storage access
Backup Image Source
Source code for the MySQL backup container image
MySQL Template
View the source files, default values, and chart definition