Use environment variables for configuration

This guide shows how to use the transform_from_environment.py helper script to override instance.yaml settings with environment variables. This pattern is essential for containerized (Docker/Kubernetes) deployments.

Step 1: copy the helper script

The transform_from_environment.py script is located in the helpers/ directory of the cookiecutter-zope-instance repository. Copy it into your project:

cp cookiecutter-zope-instance/helpers/transform_from_environment.py .

The script requires Python 3 with PyYAML installed.

Step 2: prepare a base development configuration

Create your base instance.yaml for local development:

default_context:
    wsgi_fast_listen: 0.0.0.0:8080
    initial_user_name: admin
    initial_user_password: admin
    debug_mode: true
    verbose_security: true
    zcml_package_includes: my.fancy.package
    db_storage: direct

Step 3: set environment variables for production

Every environment variable with the INSTANCE_ prefix (configurable) is picked up by the transform script. The prefix is stripped and the remaining name becomes the configuration key:

# Override scalars; the INSTANCE_ prefix is stripped to form the key
export INSTANCE_wsgi_listen=127.0.0.1:8080
export INSTANCE_db_storage=relstorage
export INSTANCE_db_relstorage_postgresql_dsn="host='db' dbname='plone' user='plone' password='verysecret'"

# An empty value clears a key (here, generate a fresh password)
export INSTANCE_initial_user_password=

Setting a variable to an empty string clears that value. For a complete production set applied end-to-end, see Docker deployment.

Step 4: run the transform script

python3 transform_from_environment.py

This produces instance-from-environment.yaml that merges the base file with all INSTANCE_* overrides.

Step 5: use the generated file with cookiecutter

cookiecutter -f --no-input --config-file instance-from-environment.yaml \
    gh:plone/cookiecutter-zope-instance

Dict convention with _DICT_ separator

To set dictionary/mapping values (such as the environment setting), use _DICT_ as a separator:

export INSTANCE_environment_DICT_PTS_LANGUAGES="de en"
export INSTANCE_environment_DICT_zope_i18n_allowed_languages="de en"

See The configuration workflow for how the _DICT_ infix works.

Docker integration pattern

For why the transform runs in the container entrypoint, why the template version is pinned, and how the entrypoint needs no network access at runtime, see The configuration workflow. The Docker deployment tutorial applies the whole pattern end-to-end.

Next steps