Map file reference

What can envilder.json contain, and how does Envilder read it? It is one JSON object that maps environment variable names to secret identifiers, with an optional $config block for the provider, profile and vault URL. CLI flags override $config field by field, and an invalid name or provider stops the run before any secret is read.

Prerequisites

This page describes the map file as read by the envilder CLI (0.16) and the GitHub Action. The runtime SDKs read the same file. If you have not resolved a secret yet, start with the getting started guide.

Structure

A map file is one JSON object. Keys that start with $ are reserved; every other key declares an environment variable, and its value is the identifier of the secret that fills it.

envilder.jsonjson
{
  "$schema": "https://envilder.com/schema/map-file.v1.json",
  "$config": {
    "provider": "aws",
    "profile": "dev-account"
  },
  "DB_PASSWORD": "/my-app/dev/db-password",
  "STRIPE_API_KEY": "/my-app/dev/stripe/api-key"
}
KeyMeaning
$schemaOptional URL of the JSON Schema. Editors use it for autocompletion and validation; envilder ignores it.
$configOptional object that selects the provider and its settings. See the fields below.
$…Any other key starting with $ is skipped by envilder. The schema rejects it, so do not use it for metadata.
DB_PASSWORDVariable name (key) and secret identifier (string value). The value is opaque: its format depends on the provider.

$config fields

Every field is optional. A file without $config uses AWS SSM with the default AWS credential chain.

FieldValuesDefaultBehaviour
provideraws | azureawsSecret backend. Matched case-insensitively. Any value other than aws or azure stops the run.
profileAWS CLI profile nameAWS default chainNamed profile from ~/.aws/config or ~/.aws/credentials. AWS only: with azure it is ignored and a warning is printed.
vaultUrlhttps://<vault>.vault.azure.net-Key Vault URL, for example https://my-vault.vault.azure.net. Required for azure. Ignored by aws.

The runtime SDKs read the same fields but can reject combinations the CLI only warns about, such as profile with azure. Each SDK page lists its own errors.

Secret identifiers by provider

AWS SSM Parameter Store

The value is the parameter name exactly as stored in SSM, usually a hierarchical path. Envilder calls GetParameter with decryption, so String and SecureString parameters both work. The region comes from AWS_REGION, then AWS_DEFAULT_REGION, then the profile, with us-east-1 as the last fallback.

envilder.jsonjson
{
  "$config": { "provider": "aws", "profile": "prod-account" },
  "DB_PASSWORD": "/my-app/prod/db-password",
  "LEGACY_TOKEN": "legacy-token"
}

Azure Key Vault

The value is the secret name. Envilder turns slashes into hyphens before calling Key Vault, so the same path style can be shared with an AWS file:

envilder.jsonjson
{
  "$config": {
    "provider": "azure",
    "vaultUrl": "https://my-vault.vault.azure.net"
  },
  "DB_PASSWORD": "my-app-prod-db-password",
  "STRIPE_API_KEY": "/my-app/prod/stripe-api-key"
}
  • Leading slashes are removed and the other slashes become hyphens: "/my-app/prod/stripe-api-key" reads my-app-prod-stripe-api-key. The CLI, the GitHub Action and every SDK apply the same rule.
  • Everything else is sent as written. A name Key Vault rejects (for example one with _ or .) fails with Key Vault's own error.
  • In the CLI and the GitHub Action, two different values that resolve to the same name in one file are an error.
  • Envilder always reads the latest version of the secret.

Precedence between $config and flags

Each setting is resolved on its own, from the first source that defines it:

1. CLI flags (--provider, --vault-url, --profile) or GitHub Action inputs
2. $config in the map file
3. Defaults: provider aws, default AWS credential chain

A flag replaces only the field it names; the other $config fields still apply. The same rules hold for pull, push and exec. When --map is omitted, envilder uses envilder.json in the current directory; pull and push also default --envfile to .env.

envilder exec -- npm start
envilder exec --profile=staging-account -- npm start
envilder exec --provider=azure \
  --vault-url=https://other-vault.vault.azure.net -- npm start

The GitHub Action accepts provider and vault-url inputs but has no profile input: in CI, credentials come from the workflow (for example OIDC), not from a named profile.

Validation rules

envilder checks the file before it contacts any provider, so an invalid file never resolves part of its secrets:

  • The file must be valid JSON. Comments and trailing commas are not allowed.
  • Variable names must match ^[A-Za-z0-9_./-]+$: letters, digits, underscore, dot, hyphen and slash. Spaces, =, #, accented letters and line breaks are rejected, because they would inject or lose a line in a .env file.
  • A name with / (Database/Password) works everywhere: the SDKs and exec pass it as written, and the .NET SDK maps it to a configuration section. When writing a .env file the CLI keeps it and warns, because python-dotenv loads that line but dotenv for Node.js, Docker Compose and bash do not; use exec or a __ name (Database__Password) if your app reads the file with one of those.
  • An empty name is rejected.
  • __proto__ cannot be used as a variable name: the schema rejects it and envilder never resolves it, because .env parsers cannot read it back.
  • The name rule applies to every key, even when the value is not a string. A key with a non-string value (number, object, null) is then skipped, not resolved.
  • With exec on Windows, two names that differ only by case are rejected, because Windows treats them as one variable.
  • The schema recommends POSIX names (^[a-zA-Z_][a-zA-Z0-9_]*$). Dotted and hyphenated names are accepted, but some shells and tools cannot read them as variables.

Secret contents (the resolved values)

Envilder never rewrites a secret value: what the provider returns is what your application gets. The limits come from where the value is stored:

StageLimit
ProviderAWS SSM: 4 KB (standard) or 8 KB (advanced tier). Azure Key Vault: 25 KB.
.env file (CLI, GitHub Action)Every value dotenv can represent. See the exception below.
Process environmentThe operating system cannot store NUL (U+0000) in a variable, and Windows limits a variable to 32,767 characters.

The SDKs' resolve-only APIs (resolve, ResolveFile, IConfiguration) keep values in memory and are subject to the provider limits only.

The CLI writes each value so that dotenv reads back exactly the original string. The quoting is chosen automatically and checked by parsing the result before the file is written. The check uses dotenv’s grammar extended to keys with /, so for those keys it proves the value round-trips, not that Node.js dotenv loads them (it skips such lines):

.envdotenv
PLAIN=plain
QUOTES=she said "hi"
HASH='alpha#beta'
PADDED='  padded  '
MULTILINE="first\nsecond"

#, leading and trailing whitespace, quotes, backslashes, a literal \n, real LF/CRLF line breaks and Unicode all round-trip. When the file already exists, each assignment is replaced in place (a multiline one entirely), and comments, ordering and line endings are preserved.

⚠️
The one value a .env file cannot hold: a value containing all three quote characters (', " and `) together with a line break, leading or trailing whitespace, or a #. The CLI stops with an error that names the variable and leaves the .env file unchanged. Store such a value encoded (for example base64) or read it with an SDK.
💲
Variable expansion: Envilder writes references such as $HOME literally and dotenv does not expand them, but other loaders do. Docker Compose, for instance, expands an unquoted KEY=$HOME when it reads the file. Keep this in mind when a secret contains $.

Multi-environment example

Keep one file per environment with the same keys, so the application code never changes. Only the paths and the profile differ:

envilder.dev.jsonjson
{
  "$schema": "https://envilder.com/schema/map-file.v1.json",
  "$config": { "provider": "aws", "profile": "dev-account" },
  "DB_PASSWORD": "/my-app/dev/db-password",
  "STRIPE_API_KEY": "/my-app/dev/stripe/api-key"
}
envilder.prod.jsonjson
{
  "$schema": "https://envilder.com/schema/map-file.v1.json",
  "$config": { "provider": "aws", "profile": "prod-account" },
  "DB_PASSWORD": "/my-app/prod/db-password",
  "STRIPE_API_KEY": "/my-app/prod/stripe/api-key"
}

Choose the file with --map. Locally, run the app with the development file; for a production artifact, write a .env from the production file:

envilder exec --map=envilder.dev.json -- npm run dev
envilder --map=envilder.prod.json --envfile=.env.prod

In a workflow, point the action at the file for that environment:

- uses: macalbert/envilder/github-action@v0
  with:
    map-file: envilder.prod.json
    env-file: .env

Names that match envilder.json or envilder.*.json are recognized by SchemaStore, so most editors validate them even without the $schema line.

Common errors

MessageFix
Invalid environment variable name "MY VAR": names may only contain letters, digits, underscore, dot, hyphen and slash, so that they can be read back from a .env fileRename the key so it only uses letters, digits, underscore, dot, hyphen and slash.
Invalid JSON in parameter map file: envilder.jsonFix the JSON syntax: a trailing comma, a comment or a missing quote is the usual cause.
Unsupported provider: gcp. Supported providers: aws, azureUse aws or azure in $config.provider or --provider.
vaultUrl is required when using Azure provider. Set it in $config.vaultUrl in your map file or via --vault-url flag.Set $config.vaultUrl, or pass --vault-url, when the provider is azure.
--profile is only supported with the aws provider and will be ignored (current provider: azure).A warning, not an error. Remove profile from $config, or drop --profile, when using azure.
Map file declares variables that differ only by case (API_KEY, api_key); Windows treats them as the same variable.Rename one of the keys; exec on Windows refuses names that differ only by case.