Storing and Using Application Configuration
ConfigHub enables application configuration files to be represented in their native formats while supporting standard ConfigHub configuration functionality. Application configuration units can be operated upon by standard ConfigHub functions, filtered using ConfigHub's filter syntax, and managed as variants with upstream/downstream relationships. Values can be resolved across links via the Needs/Provides mechanism. Application configuration units can be rendered and deployed as Kubernetes ConfigMaps, mounted as ConfigMap volumes, or -- in the case of Env files -- injected as environment variables using envFrom.
Supported formats
ConfigHub supports the following ToolchainType values for application configuration:
| ToolchainType | Format | File suffix |
|---|---|---|
AppConfig/YAML |
YAML | .yaml |
AppConfig/JSON |
JSON | .json |
AppConfig/INI |
INI | .ini |
AppConfig/TOML |
TOML | .toml |
AppConfig/Properties |
Java Properties | .properties |
AppConfig/Env |
Environment variables | .env |
AppConfig/Text |
Text | .txt |
Required metadata fields
Each application configuration file must include ConfigHub metadata fields, represented consistently with its format. These fields are stripped when rendering a ConfigMap for use within a Kubernetes workload.
configHub.configName-- Uniquely identifies the configuration file. Required for most ConfigHub functionality. Treated similarly to Kubernetes resource names. Also used to generate the data key in the rendered ConfigMap, with the format's file suffix appended (e.g.,MyApplicationConfig.ini).configHub.configSchema-- Uniquely identifies the set of valid values. Required. Conceptually similar to a Kubernetes resource type (e.g.,apps/v1/Deployment). Can be used with thevet-jsonschemafunction to validate application configuration units.
For AppConfig/Text, these metadata fields are stored as standard YAML frontmatter at the beginning of the file, delimited by ---, with the fields nested under a configHub key (see the Text example below). For all other formats, the fields use the configHub. prefix in the format's native syntax.
Example configuration files
Below are examples showing the same application configuration in each supported format.
YAML (AppConfig/YAML)
configHub:
configName: MyApplicationConfig
configSchema: SimpleApp
app:
features:
- authentication
- logging
name: MyApplication
version: 1.0.0
database:
host: localhost
port: 5432
ssl:
enabled: true
JSON (AppConfig/JSON)
{
"configHub": {
"configName": "MyApplicationConfig",
"configSchema": "SimpleApp"
},
"app": {
"features": ["authentication", "logging"],
"name": "MyApplication",
"version": "1.0.0"
},
"database": {
"host": "localhost",
"port": 5432,
"ssl": {
"enabled": true
}
}
}
TOML (AppConfig/TOML)
[configHub]
configName = "MyApplicationConfig"
configSchema = "SimpleApp"
[app]
features = ["authentication", "logging"]
name = "MyApplication"
version = "1.0.0"
[database]
host = "localhost"
port = 5432
[database.ssl]
enabled = true
INI (AppConfig/INI)
[configHub]
configName = MyApplicationConfig
configSchema = SimpleApp
[app]
features.0 = authentication
features.1 = logging
name = MyApplication
version = 1.0.0
[database]
host = localhost
port = 5432
[database.ssl]
enabled = true
Properties (AppConfig/Properties)
configHub.configName=MyApplicationConfig
configHub.configSchema=SimpleApp
app.features.0=authentication
app.features.1=logging
app.name=MyApplication
app.version=1.0.0
database.host=localhost
database.port=5432
database.ssl.enabled=true
Env (AppConfig/Env)
configHub.configName=MyApplicationConfig
configHub.configSchema=SimpleApp
APP_FEATURES_0=authentication
APP_FEATURES_1=logging
APP_NAME=MyApplication
APP_VERSION=1.0.0
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_SSL_ENABLED=true
Text (AppConfig/Text)
Text files use standard YAML frontmatter (delimited by ---) to store ConfigHub metadata:
---
configHub:
configName: MyApplicationConfig
configSchema: SimpleApp
---
# My Application Config
Valid config options are:
* Database Host
* Database Port
* Database SSL Enabled
Deploying as a Kubernetes ConfigMap
Application configuration units can be rendered as Kubernetes ConfigMaps using the ConfigMapRenderer bridge. The bridge supports two modes, controlled by the RevisionHistoryLimit option:
Immutable mode (default, RevisionHistoryLimit >= 1): Each apply produces a new immutable ConfigMap with a unique name generated by appending a content hash to the unit slug (similar to ConfigMaps generated by Kustomize). The most recent ConfigMap has the annotation confighub.com/RenderRevision: Latest. By default, the bridge retains 10 revisions to remain available to old Pods during Kubernetes rolling updates. The workload must use confighubplaceholder in its ConfigMap references, and the Needs/Provides mechanism replaces them with the generated name.
Mutable mode (RevisionHistoryLimit=0): Produces a single mutable ConfigMap with a stable, predictable name equal to the unit slug (no hash suffix). The workload can reference the ConfigMap by name directly. The ConfigMap carries a confighub.com/Hash annotation containing the content hash. This annotation is registered as a provided value on the ConfigMap and as a needed value on workload podSpec template annotations, so it is automatically propagated via the Needs/Provides mechanism. When the ConfigMap content changes, the hash annotation on the workload's pod template changes, triggering a rolling update. Mutable mode is simpler to set up but does not preserve old ConfigMap versions during rollouts.
Step 1: Create the application configuration unit
Save your configuration file (using any of the supported formats above) and create a unit:
cub unit create --space my-space my-config app.env --toolchain AppConfig/Env
Step 2: Modify configuration values (optional)
You can use functions to modify values in the application configuration:
cub function do --space my-space --where "Slug = 'my-config'" --toolchain AppConfig/Env set-string-path SimpleApp "DATABASE_HOST" postgres.example.com
cub function do --space my-space --where "Slug = 'my-config'" --toolchain AppConfig/Env set-bool-path SimpleApp "DATABASE_SSL_ENABLED" false
cub function do --space my-space --where "Slug = 'my-config'" --toolchain AppConfig/Env set-int-path SimpleApp "DATABASE_PORT" 5433
Step 3: Create the server worker
The ConfigMapRenderer is a built-in server bridge that runs inside the ConfigHub server -- no external worker process is needed. Create a server worker if it doesn't already exist:
cub worker create --space default --allow-exists --is-server-worker server-worker
The --allow-exists flag makes the command idempotent. The worker can be placed in any space and referenced from other spaces using the space/worker syntax (e.g., default/server-worker).
Step 4: Create a Target for the ConfigMapRenderer
Create a Target with ProviderType ConfigMapRenderer and LiveStateType Kubernetes/YAML (no parameters are needed):
cub target create --space my-space my-target '' default/server-worker --provider ConfigMapRenderer --toolchain AppConfig/Env --livestate-type Kubernetes/YAML
To change the number of ConfigMap revisions retained, set the RevisionHistoryLimit bridge option:
cub target create --space my-space my-target '' default/server-worker --provider ConfigMapRenderer --toolchain AppConfig/Env --livestate-type Kubernetes/YAML --option RevisionHistoryLimit=5
To use mutable mode (a single mutable ConfigMap with a stable name), set RevisionHistoryLimit to 0:
cub target create --space my-space my-target '' default/server-worker --provider ConfigMapRenderer --toolchain AppConfig/Env --livestate-type Kubernetes/YAML --option RevisionHistoryLimit=0
For Env files that should be injected as environment variables using envFrom (where each key-value pair becomes a separate ConfigMap data entry), set the AsKeyValue bridge option:
cub target create --space my-space my-target-kv '' default/server-worker --provider ConfigMapRenderer --toolchain AppConfig/Env --livestate-type Kubernetes/YAML --option AsKeyValue=true
Step 5: Attach the Target and apply
cub unit set-target --space my-space my-config my-target
cub unit apply --wait --space my-space my-config
You can inspect the rendered ConfigMap in the unit's live state:
cub unit livestate --space my-space my-config
Step 6: Create a unit for the rendered ConfigMaps
Create a Kubernetes/YAML unit to receive the rendered ConfigMaps, and link it to the application configuration unit with UseLiveState true, UpdateType MergeUnits, and AutoUpdate true so that new ConfigMaps are propagated automatically.
Link the ConfigMap unit to a unit containing the target Kubernetes Namespace resource. The rendered ConfigMap contains a namespace placeholder that the Needs/Provides mechanism will replace with the actual namespace name:
cub unit create --space my-space my-configmap
cub link create --space my-space - my-configmap my-namespace
cub link create --space my-space --wait - my-configmap my-config --use-live-state --auto-update --update-type MergeUnits
Step 7: Link the workload to the ConfigMap unit
Link the unit containing your Kubernetes workload (e.g., a Deployment) to the ConfigMap unit:
cub link create --space my-space - my-deployment my-configmap
Immutable mode workload configuration
In immutable mode, the workload should use confighubplaceholder in its ConfigMap references. Needs/Provides will replace the placeholder with the generated ConfigMap name. You may optionally use --where-resource on the link to match only the most recently generated ConfigMap:
cub link create --space my-space - my-deployment my-configmap --where-resource "metadata.annotations.confighub~1com/RenderRevision = 'Latest'"
Note:
~1is the path escaping encoding for/(inspired by JSON Pointer) in the annotation keyconfighub.com/RenderRevision.
spec:
template:
spec:
containers:
- name: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/app.properties
subPath: app.properties
volumes:
- name: config-volume
configMap:
name: confighubplaceholder
When the workload unit is resolved, confighubplaceholder will be replaced with the name of the latest rendered ConfigMap.
Mutable mode workload configuration
In mutable mode, the ConfigMap has a stable name equal to the unit slug, so you can reference it directly. Add a confighub.com/Hash annotation with confighubplaceholder to the pod template; Needs/Provides will replace it with the content hash, triggering a rolling update whenever the ConfigMap changes:
spec:
template:
metadata:
annotations:
confighub.com/Hash: confighubplaceholder
spec:
containers:
- name: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/app.properties
subPath: app.properties
volumes:
- name: config-volume
configMap:
name: my-config
Environment variable injection using envFrom
For both modes, environment variable injection works the same way (use confighubplaceholder in immutable mode or the stable name in mutable mode):
spec:
template:
spec:
containers:
- name: nginx
envFrom:
- configMapRef:
name: confighubplaceholder
When a workload references multiple ConfigMaps, each ConfigMap's hash is propagated separately. Combining multiple hashes into a single annotation is not yet supported.