Repository navigation
WP Complete Example
This example demonstrates a complete Timonel composition pattern with two typed subcharts. It is a learning example, not a production WordPress architecture: the MySQL workload below is ephemeral so the focus stays on Timonel, cdk8s-plus, Secrets, Services, and umbrella composition.
For production, add durable storage, backups, disruption planning, probes, resource sizing, and a proper database lifecycle strategy.
pnpm add timonel cdk8s cdk8s-plus-33 constructsimport * as kplus from 'cdk8s-plus-33';
import { Rutter } from 'timonel';
export function createMysql(): Rutter {
const chart = new Rutter({
meta: {
name: 'mysql',
version: '1.0.0',
description: 'MySQL subchart',
},
});
const credentials = new kplus.Secret(chart.getChart(), 'Credentials', {
metadata: { name: 'mysql-credentials' },
stringData: {
password: 'replace-before-deploy',
'root-password': 'replace-before-deploy',
},
});
const deployment = new kplus.Deployment(chart.getChart(), 'Mysql', {
metadata: { name: 'mysql' },
containers: [
{
name: 'mysql',
image: 'mysql:8.4',
portNumber: 3306,
envVariables: {
MYSQL_DATABASE: kplus.EnvValue.fromValue('wordpress'),
MYSQL_USER: kplus.EnvValue.fromValue('wordpress'),
MYSQL_PASSWORD: credentials.envValue('password'),
MYSQL_ROOT_PASSWORD: credentials.envValue('root-password'),
},
},
],
});
deployment.exposeViaService({ name: 'mysql' });
return chart;
}Do not use literal passwords like these in a real chart. This demonstrates the Kubernetes Secret reference mechanics only. Supply secret material through your platform's secure delivery path.
export function createWordpress(): Rutter {
const chart = new Rutter({
meta: {
name: 'wordpress',
version: '1.0.0',
description: 'WordPress subchart',
},
});
const databaseCredentials = kplus.Secret.fromSecretName(
chart.getChart(),
'MysqlCredentials',
'mysql-credentials',
);
const deployment = new kplus.Deployment(
chart.getChart(),
'Wordpress',
{
metadata: { name: 'wordpress' },
containers: [
{
name: 'wordpress',
image: 'wordpress:6.8-apache',
portNumber: 80,
envVariables: {
WORDPRESS_DB_HOST: kplus.EnvValue.fromValue('mysql:3306'),
WORDPRESS_DB_USER: kplus.EnvValue.fromValue('wordpress'),
WORDPRESS_DB_NAME: kplus.EnvValue.fromValue('wordpress'),
WORDPRESS_DB_PASSWORD: databaseCredentials.envValue('password'),
},
},
],
},
);
deployment.exposeViaService({ name: 'wordpress' });
return chart;
}There is an important Helm boundary here: Kubernetes Secret lookup by name assumes both subcharts are installed into the same namespace and the MySQL secret name is stable.
For a more isolated architecture, move shared credentials into a dedicated external secret flow or model the secret at the parent/platform layer.
import { UmbrellaRutter } from 'timonel';
const mysql = createMysql();
const wordpress = createWordpress();
const umbrella = new UmbrellaRutter({
meta: {
name: 'wordpress-stack',
version: '1.0.0',
description: 'WordPress with MySQL',
},
subcharts: [
{
name: 'mysql',
version: '1.0.0',
rutter: mysql,
},
{
name: 'wordpress',
version: '1.0.0',
rutter: wordpress,
},
],
});
await umbrella.write('./dist/wordpress-stack');dist/wordpress-stack/
├── Chart.yaml
├── values.yaml
├── templates/
│ └── NOTES.txt
└── charts/
├── mysql/
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/
└── wordpress/
├── Chart.yaml
├── values.yaml
└── templates/
helm lint ./dist/wordpress-stack
helm template wordpress ./dist/wordpress-stackInspect the rendered Secret, Deployment, and Service resources before deploying.
The source example intentionally makes the unsafe placeholder obvious. A production design should
not commit database passwords into TypeScript, values.yaml, or Git history.
Common production approaches include:
- External Secrets Operator;
- Secrets Store CSI Driver;
- a platform controller that materializes Kubernetes Secrets;
- pre-provisioned Secrets referenced by the chart.
Timonel's Environment Variables Configuration helper can
create secretKeyRef entries, but it does not fetch external secrets itself.
The example uses an ephemeral MySQL Deployment. Do not call that production-ready.
For production, prefer a managed database where appropriate or add a correctly designed persistent workload using the typed storage constructs available in your cdk8s-plus version. If you need AWS storage classes, see AWS Resources.
After replacing the demo secret strategy and validating storage/lifecycle:
helm upgrade --install wordpress ./dist/wordpress-stack \
--namespace wordpress \
--create-namespace- each subchart is a normal independently testable
Rutter; - Kubernetes resources stay typed through cdk8s-plus;
- the parent chart handles composition, not resource reimplementation;
- Secrets are Kubernetes resources, not values-file strings;
- cross-subchart names are an architectural contract and should be intentional;
- generated Helm output must be rendered and reviewed before deployment.
Timonel documentation · Repository · npm · Issues