--- myst: html_meta: "description": "Configure environment variables and secrets on Plone backend and frontend pods with cdk8s-plone using the cdk8s-plus Env API." "property=og:description": "Configure environment variables and secrets on Plone backend and frontend pods with cdk8s-plone using the cdk8s-plus Env API." "property=og:title": "Configure environment variables and secrets" "keywords": "Plone, cdk8s, Kubernetes, environment variables, secrets, ConfigMap, imagePullSecrets, Env" --- # Configure environment variables and secrets This guide shows you how to set environment variables on Plone backend and frontend pods and how to source sensitive values from Kubernetes Secrets and ConfigMaps. Use it to inject a RelStorage DSN, an admin password, or any runtime configuration without baking values into the image. ## Prerequisites - A working Plone deployment using `cdk8s-plone`. - Familiarity with the cdk8s-plus `Env` API and the `EnvValue` helpers it provides. - `kubectl` access to the target namespace for creating Secrets and ConfigMaps. ## Set a plain environment variable on the backend Pass an `environment` object to `backend`. Build each value with `Env.value` for a literal string. ```typescript import { Plone, PloneVariant } from '@bluedynamics/cdk8s-plone'; import { Env } from 'cdk8s-plus-30'; new Plone(chart, 'plone', { variant: PloneVariant.VOLTO, backend: { image: 'plone/plone-backend:6.1.3', environment: { variables: { PLONE_TIMEZONE: Env.value('Europe/Vienna'), ZSERVER_THREADS: Env.value('4'), }, }, }, }); ``` The `environment` option is typed as the cdk8s-plus `Env` construct. Its `variables` map takes an `EnvValue` for every entry, so always wrap raw strings in `Env.value`. ## Reference a value from a Secret Store sensitive values such as a RelStorage DSN or an admin password in a Kubernetes Secret, then reference them with `Env.fromSecret`. First create the Secret in the cluster. ```shell kubectl create secret generic plone-backend-secrets \ --namespace \ --from-literal=relstorage-dsn='dbname=plone host=db user=plone password=s3cret' \ --from-literal=admin-password='change-me' ``` Reference the existing Secret by name, then read individual keys from it. ```typescript import { Plone, PloneVariant } from '@bluedynamics/cdk8s-plone'; import { Env, Secret } from 'cdk8s-plus-30'; const backendSecret = Secret.fromSecretName( chart, 'backend-secret', 'plone-backend-secrets', ); new Plone(chart, 'plone', { variant: PloneVariant.VOLTO, backend: { image: 'plone/plone-backend:6.1.3', environment: { variables: { RELSTORAGE_DSN: Env.fromSecret(backendSecret, 'relstorage-dsn'), ADMIN_PASSWORD: Env.fromSecret(backendSecret, 'admin-password'), }, }, }, }); ``` `Env.fromSecret` renders a `secretKeyRef` in the pod template, so the value never appears in plain text in the synthesized manifest. ## Reference a value from a ConfigMap For non-sensitive configuration that you manage separately from the chart, read keys from a ConfigMap with `Env.fromConfigMap`. ```typescript import { Env, ConfigMap } from 'cdk8s-plus-30'; const settings = ConfigMap.fromConfigMapName( chart, 'settings', 'plone-settings', ); // inside backend.environment.variables: // LOG_LEVEL: Env.fromConfigMap(settings, 'log-level'), ``` ## Set variables on the frontend The frontend accepts the same `environment` option as the backend. ```typescript import { Plone, PloneVariant } from '@bluedynamics/cdk8s-plone'; import { Env } from 'cdk8s-plus-30'; new Plone(chart, 'plone', { variant: PloneVariant.VOLTO, frontend: { image: 'plone/plone-frontend:16.0.0', environment: { variables: { RAZZLE_API_PATH: Env.value('https://plone.example.com/++api++'), }, }, }, }); ``` The Volto frontend automatically injects `RAZZLE_INTERNAL_API_PATH` when you do not set it. Override it through `environment` only when your service topology requires a non-default internal address. ```typescript frontend: { image: 'plone/plone-frontend:16.0.0', environment: { variables: { RAZZLE_INTERNAL_API_PATH: Env.value('http://plone-backend:8080/Plone'), }, }, } ``` ## Pull from a private registry Image registry credentials are not environment variables. List the names of existing pull secrets in the top-level `imagePullSecrets` option. ```typescript new Plone(chart, 'plone', { variant: PloneVariant.VOLTO, imagePullSecrets: ['my-registry-credentials'], backend: { image: 'registry.example.com/plone-backend:6.1.3', }, frontend: { image: 'registry.example.com/plone-frontend:16.0.0', }, }); ``` Create the pull secret beforehand with `kubectl create secret docker-registry `. ## Verify Synthesize the manifests and inspect the rendered Deployment for the expected entries. ```shell cdk8s synth # Confirm literal values and secret references appear on the backend container grep -A 3 'RELSTORAGE_DSN' dist/*.yaml grep -B 1 -A 4 'secretKeyRef' dist/*.yaml ``` A `secretKeyRef` block in the output confirms the value resolves at runtime from the Secret rather than being stored in the manifest. After applying, check that the variables reach the container. ```shell kubectl apply -f dist/ kubectl exec -n deployment/ -- env | grep RELSTORAGE_DSN ``` ## See also - {doc}`/reference/api/index` — full construct and option reference. - {doc}`/reference/configuration-options` — guide to `environment` and `imagePullSecrets`. - {doc}`/how-to/configure-security-context` — harden the pods that run with these variables.