File names for keys. File contents for values.
For security, simplicity, and consistency, all configuration is in files – not environmental variables.
- Security – Environmental variables set on a Docker image or container are injectable outside the container. When forking a process, the environmental variables are often exposed to the new process. This means environmental variables are insecure for secrets like passwords or encryption keys.
- Simplicity – ConfigDir is simple to parse. This makes it easy for any language to parse. It is particularly useful for shell interpreters like bash.
- Consistency – Rather than have two or more ways to configure an application securely (files for secrets, environmental variables for everything else), all configuration is done as files.
- Kubernetes Integration – Easy to generate from ConfigMaps or Secrets
- Variable Interpolation – Configuration values can reference other
configuration values. Kubernetes only interpolates variables for
command
,args
, orenv
fields so Kubernetes variable interpolation can not be used when volume mounting ConfigMaps or Secrets as files.
Configuration is mounted as a directory of files in /configdir
(by default). The configuration directory can be overridden with the
environmental variable CONFIGDIR
.
Each key is create as a file named /configdir/{key}
. The configuration,
when parsed, will be a dictionary where the keys of the dictionary are
the child file names.
Nested keys are allowed: /configdir/{key}/{sub-key}
. If the parent key
is a directory, the value will be a dictionary where the keys of the
dictionary are the child file names. There is no limit to directory nesting
depth.
Each filename consists of up to two parts: the name
and an optional
extension
. Only the name
portion is used for the configuration key.
name
must consist solely of lowercase ascii letters, uppercase ascii letters, digits, and underscore and must not begin with a digit ([a-zA-Z_][a-zA-Z0-9_]*
).extension
must be omitted or be one of the File Types below.
Trailing and leading whitespace is removed from file contents (except for
.bin
files).
Files can contain template place holders for other config keys. Placeholders
are enclosed with squiggly braces ({{PLACEHOLDER}}
).
- Placeholders can refer to nested keys using dot (
.
) notation:{{PARENT_KEY.NESTED_KEY}}
- Placeholders can refer to nested list items using at (
@
) notation:{{PARENT_KEY@1}}
- Placeholders may only reference number or string values.
- A File with no extension has a value that is UTF-8 encoded and can contain interpolated variables.
.json
will automatically be decoded as JSON then each value will be interpolated..yaml
will automatically be decoded as YAML then each value will be interpolated..bin
will not be UTF-8 decoded, will not be interpolated, and will be loaded as binary..uri
will be decoded as a UTF-8 string then interpolated and each interpolated value will be URL encoded.
File Path | Contents |
---|---|
/configdir/REDIS_URI.uri |
redis://:{{REDIS_PASSWORD}}@{{REDIS_HOST}}:{{REDIS_PORT}}/{{REDIS_SENTINEL_MASTER}}/0 |
/configdir/REDIS_PASSWORD |
$3cr3t |
/configdir/REDIS_SENTINEL_MASTER |
mymaster |
/configdir/REDIS_HOST |
redis-sentinel |
/configdir/REDIS_PORT |
6319 |
/configdir/CELERY_BROKER_URL.uri |
sentinel://{{REDIS_HOST}}:{{REDIS_PORT}} |
/configdir/CELERY_BROKER_TRANSPORT_OPTIONS/master_name |
{{REDIS_SENTINEL_MASTER}} |
/configdir/CELERY_BROKER_TRANSPORT_OPTIONS/visibility_timeout |
3600 |
/configdir/POSTGRES_DB_URI.uri |
postgresql://root:postgres@postgres:5432/database |
/configdir/SMTP/username |
sender |
/configdir/SMTP/password |
$3cr3t |
/configdir/SMTP/port |
542 |
/configdir/SMTP/host |
mail.mailgun.com |
/configdir/SMTP/certificate.bin |
<binary> |
/configdir/KEYS.json |
{"keys": {"id": 1, "private_key": "<pem>"}} |
/configdir/PUBLIC_KEY.bin |
<binary> |
/configdir/BLOBSTORE_URI.uri |
http://{{BLOBSTORE_KEY}}:{{BLOBSTORE_SECRET}}@blobstore/ |
/configdir/BLOBSTORE_KEY |
aderattsrngmvoc1gogj54 |
/configdir/BLOBSTORE_SECRET |
C/Ahz+pAA/NMWirgEy4Pg== |
{
"PUBLIC_KEY": "<binary>",
"KEYS": {
"keys": {
"id": 1,
"private_key": "<pem>"
}
},
"CELERY_BROKER_TRANSPORT_OPTIONS": {
"master_name": "mymaster",
"visibility_timeout": "3600"
},
"CELERY_BROKER_URL": "sentinel://redis-sentinel:6319",
"POSTGRES_DB_URI": "postgresql://root:postgres@postgres:5432/database",
"REDIS_HOST": "redis-sentinel",
"REDIS_PASSWORD": "$3cr3t",
"REDIS_PORT": "6319",
"REDIS_SENTINEL_MASTER": "mymaster",
"REDIS_URI": "redis://:%243cr3t@redis-sentinel:6319/mymaster/0",
"SMTP": {
"certificate": "<binary>",
"host": "mail.mailgun.com",
"password": "$3cr3t",
"port": "542"
},
"BLOBSTORE_URI": "http://aderattsrngmvoc1gogj54:C%2FAhz%2BpAA%2FNMWirgEy4Pg%3D%3D@blobstore/",
"BLOBSTORE_KEY": "aderattsrngmvoc1gogj54",
"BLOBSTORE_SECRET": "C/Ahz+pAA/NMWirgEy4Pg=="
}
from configdir import configdir
config = configdir()
print(config["REDIS_URI"])
- envdir – Launches a sub-process with configuration directory contents as environmental variables. There is also a Python port.
- confdir – Python based.