Environment System

Manages environment variables through configurable storage backends.

Overview

The environment system separates storage from access:

  • Storages - Where values are stored (OS, files, memory)
  • Variables - Named references to values in storages

Variables can be referenced by:

  • Public name - The variable field value (must be unique across the system)
  • Entry ID - Full namespace:name reference

If you don't want a variable to be publicly accessible by name, omit the variable field.

Entry Kinds

Kind Description
env.storage.memory In-memory key-value storage
env.storage.file File-based storage (.env format)
env.storage.os Read-only OS environment access
env.storage.static Read-only static key-value storage
env.storage.router Chains multiple storages
env.variable Named variable referencing a storage

Storage Backends

Memory Storage

Volatile in-memory storage.

- name: runtime_env
  kind: env.storage.memory

File Storage

Persistent storage using .env file format (KEY=VALUE with # comments).

- name: app_config
  kind: env.storage.file
  file_path: /etc/app/config.env
  auto_create: true
  file_mode: 0600
  dir_mode: 0700
Property Type Default Description
file_path string required Path to .env file
auto_create boolean false Create file if missing
file_mode integer 0644 File permissions
dir_mode integer 0755 Directory permissions

OS Storage

Read-only access to operating system environment variables.

- name: os_env
  kind: env.storage.os

Always read-only. Set operations return PERMISSION_DENIED.

Static Storage

Read-only storage with values defined directly in configuration. Values are baked into the entry and cannot be changed at runtime. Useful for public configuration constants that ship with a module or pack.

- name: defaults
  kind: env.storage.static
  values:
    PUBLIC_API_HOST: "https://api.example.com"
    PUBLIC_WS_HOST: "wss://api.example.com/ws"
    APP_ENV: "production"
Property Type Description
values map Key-value pairs (string to string)

Always read-only. Set operations return PERMISSION_DENIED.

Router Storage

Chains multiple storages. Reads search in order until found. Writes go to first storage only.

- name: config
  kind: env.storage.router
  storages:
    - app.config:memory    # Primary (writes here)
    - app.config:file      # Fallback
    - app.config:os        # Fallback
Property Type Description
storages array Ordered list of storage references

Variables

Variables provide named access to storage values.

- name: DATABASE_URL
  kind: env.variable
  variable: DATABASE_URL
  storage: app.config:file
  default: postgres://localhost/app
  readonly: false
Property Type Description
variable string Public variable name (optional, must be unique)
storage string Storage reference (namespace:name)
default string Default value if not found
readonly boolean Prevent modifications

Variable Naming

Variable names must contain only: a-z, A-Z, 0-9, _

Access Patterns

# Public variable - accessible by name "PORT"
- name: port_var
  kind: env.variable
  variable: PORT
  storage: app.config:os
  default: "8080"

# Private variable - accessible only by ID "app.config:internal_key"
- name: internal_key
  kind: env.variable
  storage: app.config:secrets

Placeholder Interpolation

Registered variables are pulled into entry configuration with ${env:NAME} placeholders, resolved centrally at decode time against this registry. Any string field in an entry's data may reference a variable this way.

Syntax Meaning
${env:NAME} Resolve NAME through the env registry; error if unset and no default
${env:NAME|default} Resolve NAME, falling back to default when unset
${NAME|default} Shorthand; NAME must be upper-snake (A-Z0-9_) and the |default is required — bare ${VAR} is left untouched so embedded shell/template spans are not mistaken for references
$${ Literal ${ (escape)

NAME is a registered variable's public name or its entry ID (registry-id form with dots/colons, e.g. app.env:tls_cert). It is not a raw OS environment variable: an OS value is reachable only when an env.storage.os-backed variable is registered under that name.

- name: api
  kind: http.service
  addr: ":443"
  tls:
    mode: manual
    cert: ${env:app.env:tls_cert}
    key:  ${env:app.env:tls_key}

A field whose entire value is a single placeholder takes the variable's typed value (coerced to bool/int/float when a typed default is given); a placeholder mixed with surrounding text interpolates into a string. A variable's own default is honored before the placeholder's inline |default. A reference that resolves to nothing and has no default fails decoding.

Resolution happens at decode time only: the stored registry entry keeps the raw placeholders, so resolved secrets never appear in registry.get results or persisted state. Entries referencing ${env:...} automatically order after the env storages and variables they depend on at boot.

Older configurations use a sibling <field>_env directive (for example cert_env: app.env:tls_cert) that resolves the same way. This form is deprecated — migrate it to the ${env:NAME} placeholder. A <field>_env key naming an unregistered variable is not treated as a directive and is left as-is; one naming a registered but empty variable keeps the inline <field> value. Only an explicit ${env:NAME} without a default hard-fails on a missing variable.

Errors

Condition Kind Retryable
Variable not found errors.NOT_FOUND no
Storage not found errors.NOT_FOUND no
Variable is read-only errors.PERMISSION_DENIED no
Storage is read-only errors.PERMISSION_DENIED no
Invalid variable name errors.INVALID no

Runtime Access

See Also