paas-config.yaml¶
The paas-config.yaml file is an optional configuration file that charm developers
can include in their charm to customize runtime behavior of 12-factor app charms.
When used, the paas-config.yaml file must be placed in the charm root directory
alongside your charmcraft.yaml file and included in the packed charm file.
For packaging with the uv plugin, see
the packaging instructions.
The file and all of its keys are optional. Omitted settings use the defaults of the
selected framework.
This file is distinct from charm configuration options managed through juju config.
File structure¶
The paas-config.yaml file uses YAML format and follows a structured schema.
It supports generic application settings in addition to the
prometheus, framework_logging_format, and config top-level keys.
Application settings¶
Use the following keys to configure the framework server and its metrics endpoint:
Key |
Type |
Default |
Description |
|---|---|---|---|
|
Integer |
Framework-specific |
Port on which the application server listens. |
|
Integer |
Framework-specific |
Port on which the workload serves metrics. |
|
String |
Framework-specific |
Absolute HTTP path on which the workload serves metrics. |
For example:
port: 8080
metrics-port: 8080
metrics-path: /metrics
Ports must be between 1 and 65535. When Charmcraft builds the project, it requires
metrics-path to be a slash-prefixed RFC 3986 HTTP path. paas-charm treats the
packaged value as a string and does not repeat this build-time validation at runtime.
These values are packaged with the charm and cannot be changed with juju config.
Omitted values use the framework defaults.
The default application port is 8000 for Flask, Django, and FastAPI, and 8080 for
ExpressJS, Go, and Spring Boot. The resolved port is always written to the
workload environment when the framework uses an application port environment variable:
PORT for ExpressJS and Go, UVICORN_PORT for FastAPI, and SERVER_PORT for
Spring Boot. Flask and Django configure the port directly in Gunicorn instead.
The charm always passes the resolved metrics-port and metrics-path values to the workload.
Workload code is responsible for consuming this configuration and exposing the corresponding
endpoint. Flask and Django receive framework-prefixed
METRICS_PORT and METRICS_PATH variables. FastAPI, ExpressJS, and Go receive variables
without framework prefixes. Spring Boot receives native management.* properties.
Flask and Django default to 9102 and /metrics. FastAPI defaults to 8000 and
/metrics. Go defaults to 8080 and /metrics. ExpressJS defaults to 9464
and /metrics. Spring Boot defaults to 8080 and /actuator/prometheus.
Note
For Flask and Django, the statsd exporter port is not changed by metrics-port.
The charm publishes a Prometheus scrape job for the resolved metrics-port and metrics-path.
Additional scrape jobs can be configured independently under prometheus.scrape_configs. Their
targets must match endpoints that the workload actually serves.
See Prometheus configuration for detailed Prometheus configuration options. See Structured logging configuration for detailed structured logging options.
Environment variable name mappings¶
Use config.options to rename environment variables generated from charm configuration
options, including framework-provided options. Mappings refer to existing options; they
do not declare options or set their values.
This example assumes log-level is a string option and credentials has type: secret:
config:
options:
log-level:
env-var: LOG_LEVEL
credentials:
secret-env-vars:
username: SERVICE_USERNAME
password: SERVICE_PASSWORD
Each option must use exactly one field: env-var for a non-secret option, or
secret-env-vars for an option declared with type: secret.
Source names must match options declared in charmcraft.yaml or config.yaml exactly.
Framework options with environment outputs, such as app-secret-key and flask-debug,
can be mapped. Options that only configure files or arguments, such as Gunicorn’s
webserver-workers, cannot. Settings declared only in paas-config.yaml, such as
port, are not charm configuration options and cannot be mapping sources.
Destination names are used exactly as written, without adding prefixes or changing punctuation
or case. They must be non-empty strings without NUL characters or =. Other characters
are accepted, but the workload and any shell scripts must support the chosen names.
Mappings replace default names rather than add aliases. In Flask, the example emits
LOG_LEVEL instead of FLASK_LOG_LEVEL. Unmapped options retain their existing names.
Other sources can still produce a variable with the original name.
Without a mapping, user-defined options cannot replace framework fields with matching names,
even when those fields have no value. For example, a user-defined application-root option
does not replace Flask’s flask-application-root setting unless it is explicitly mapped.
Secret entries¶
Keys under secret-env-vars are exact Juju secret content keys. The example renames
the username and password entries of the secret configured through credentials.
Unmapped entries retain their default environment variable names.
For app-secret-key, use secret-env-vars: {value: SESSION_SECRET} to rename the
application’s secret key. The mapping also applies to the automatically generated key
when no secret is configured.
Configured secrets must pass the option’s usual validation. app-secret-key requires
exactly one content entry named value. If the secret passes validation but does not
contain a mapped key, the charm skips that entry and logs a warning. The warning names
the option, missing key, and destination variable, but never includes the secret value.
For framework options exposing a secret as a JSON object, mapped entries are removed from that object; unmapped entries remain in the original output.
Values and defaults¶
For framework options, mappings use the values already prepared by the framework, with
their existing encoding. For user-defined options, strings pass through unchanged;
booleans and numbers are JSON-encoded (for example, false becomes the string
"false"). Configuration validation and secret resolution still apply.
Defaults are mapped too. A log-level default of info emits LOG_LEVEL=info
without the operator setting the option. Resetting an option uses its default rather
than making it unset.
If an option has no value, its mapping adds no environment variable and leaves any existing
destination variable unchanged. Empty strings, false, and zero count as values and
replace existing destination values. Options without mappings keep their existing behavior
when unset.
Precedence and collisions¶
Environment variables are applied in this order, from lowest to highest priority:
Priority |
Source |
|---|---|
1 |
Charm configuration and framework-generated settings. |
2 |
Built-in relations and Prometheus metrics. |
3 |
Custom relations, in registration order. |
4 |
Explicit |
The charm logs a warning when a relation replaces a configuration or framework variable, or when a mapping replaces an existing variable. Warnings name the destination variable without logging its value. Mapping warnings also name the source option.
Each mapping reads its own option’s value, so two options can swap environment variable names. Mappings can also replace framework variables. Charm authors must ensure that the workload still works with the chosen names.
Validation¶
The paas-config.yaml file is validated when the charm initializes to handle a hook.
If validation fails, the hook fails and Juju reports an error. The charm author must
correct the file and repack the charm. Existing applications need the corrected charm
revision; see the Juju refresh command
for updating a deployed application.
Common validation errors include:
Invalid YAML syntax
Unknown fields
Missing required fields in nested configuration sections
Invalid field values
Unknown source options or mapping fields that do not match an option’s declared type
Duplicate mapping destinations, even when a source is unset
Ambiguous source option names such as
foo-barandfoo_bar, which the library treats identically
Functionality provided¶
The file paas-config.yaml allows you to:
Configure the application server port
Configure the workload metrics endpoint
Define custom Prometheus scrape targets for metrics collection
Enable structured framework logs in JSON format
Rename environment variables generated from config options and secrets
For the detailed configuration schema and detailed examples, see: