Skip to content

Interpolation

Plenum supports boot-time interpolation in all x-plenum-* extension string values using the ${{ namespace.key }} syntax. This lets you inject environment variables, file contents, and other values into your configuration.

All interpolation uses the same ${{ }} template syntax:

ExpressionDescription
${{ env.VAR }}Value of environment variable VAR
${{ file.NAME.content }}Contents of a file declared in x-plenum-files
${{ file.NAME.path }}Resolved absolute path to the file

Whitespace inside the braces is optional — ${{env.VAR}} and ${{ env.VAR }} are equivalent.

Reference environment variables with ${{ env.VAR }}:

x-plenum-upstream:
kind: "HTTP"
address: "${{ env.BACKEND_HOST }}"
port: 8080

If the variable is not set, Plenum fails at startup with an error. To provide defaults, set them when running the container:

Terminal window
docker run -e BACKEND_HOST=api.example.com ...

Or in Docker Compose:

environment:
- BACKEND_HOST=${BACKEND_HOST:-localhost}

Inject file contents or paths into config values using ${{ file.NAME.accessor }}. First, declare your files in x-plenum-files at the spec root:

x-plenum-files:
jwt-secret: /run/secrets/jwt-secret
ca-bundle: /etc/ssl/custom-ca.pem

Then reference them by name:

x-plenum-interceptor:
- module: "./interceptors/auth.js"
hook: on_request_headers
function: checkJwt
options:
secret: "${{ file.jwt-secret.content }}"

Files are read at startup. Relative paths resolve against --config-path. Missing files cause a startup error.

Each file entry is a descriptor with two accessors:

AccessorDescription
${{ file.NAME.content }}File contents
${{ file.NAME.path }}Resolved absolute path to the file

An accessor is always required — bare ${{ file.NAME }} is an error.

The .path accessor is useful for fields that expect a filesystem path rather than inline content — for example, TLS certificate and key paths:

x-plenum-files:
gateway-cert: /certs/gateway.crt
gateway-key: /certs/gateway.key
x-plenum-config:
tls:
cert: "${{ file.gateway-cert.path }}"
key: "${{ file.gateway-key.path }}"
overlay: 1.1.0
info:
title: File declarations
version: 1.0.0
actions:
- target: $
update:
x-plenum-files:
jwt-secret: /run/secrets/jwt-secret

Interpolation applies to all string values in any x-plenum-* extension — universally, with no exceptions:

  • Upstream addresses, ports, TLS cert/key/CA paths
  • Interceptor module paths and options
  • Plugin options and permissions
  • CORS origins and headers
  • Static response bodies
  • Backend config values

The ${{ }} syntax is also used for runtime context resolution in certain fields (e.g. hash-key in load balancing, queries in x-plenum-backend). These use different namespaces:

NamespaceResolved atExample
envBoot time${{ env.API_KEY }}
fileBoot time${{ file.secret.content }}, ${{ file.cert.path }}
headerRequest time${{ header.x-user-id }}
queryRequest time${{ query.page }}
pathRequest time${{ path.id }}
bodyRequest time${{ body.name }}
cookieRequest time${{ cookie.session }}
client-ipRequest time${{ client-ip }}

Boot-time tokens (env, file) are resolved once at startup. Runtime tokens pass through and are resolved per-request.

query.* tokens resolve from parsed query parameters (queryParams), so values are typed — an integer query param resolves as a number, not a string. Use query.* tokens in x-plenum-backend.params to safely pass query parameter values to database queries:

x-plenum-backend:
query: "SELECT * FROM users LIMIT $1"
params:
- "${{query.limit}}"

The gateway resolves each entry in params before calling the plugin. The resolved values are passed as a native parameter array — never interpolated into the query string.