Skip to content

Configuration Reference

This is the complete reference for EMB configuration files.

EMB uses two types of configuration files:

  • .emb.yml - Project-level configuration at the monorepo root
  • Embfile.yml - Component-level configuration in each component folder

Required. Basic project information.

project:
name: my-project # Required: Project identifier
rootDir: . # Optional: Root directory (default: .)

Optional. List of plugins to load.

plugins:
- name: autodocker # Auto-discover components with Dockerfiles
- name: dotenv # Load .env files
config:
- .env
- .env.local
- name: embfiles # Load component Embfile.yml files
- name: op # Fetch secrets and files from 1Password

Built-in plugins:

  • autodocker - Auto-discovers components by looking for Dockerfiles
  • dotenv - Loads environment variables from .env files
  • embfiles - Loads component configuration from Embfile.yml files
  • op - Fetches secrets and files from 1Password, enabling ${op:...} expansion and the op/file resource type (see Secrets Management)
  • vault - Fetches secrets from HashiCorp Vault (see Secrets Management)

Plugin configuration:

Plugins extend the configuration in the order they are listed. Each entry takes an optional config value whose shape depends on the plugin. Unknown keys are rejected, so a typo fails the whole config load.

autodocker:

PropertyTypeDescription
globstringGlob pattern used to find Dockerfiles (default: */Dockerfile)
ignorestring or arrayPatterns to ignore when searching for Dockerfiles
plugins:
- name: autodocker
config:
glob: services/*/Dockerfile
ignore:
- services/legacy/**

embfiles:

PropertyTypeDescription
globstring or arrayGlob pattern(s) used to find Embfiles (default: */Embfile.{yaml,yml})
plugins:
- name: embfiles
config:
glob: services/*/Embfile.yml

dotenv takes an array of .env file paths rather than an object, as shown in the example above.

When a variable is defined in several of those files, the file listed last wins, as with docker-compose’s env_file:

plugins:
- name: dotenv
config:
- .env.commons # MY_SETTING=from_commons
- .env # MY_SETTING=from_env -> this one wins

Variables already present in the shell environment are never overwritten, whichever file defines them.

The vault plugin’s configuration is documented in Secrets Management.

Plugin config values are template-expanded before the plugin is constructed, so ${vars:...} and ${env:...} placeholders work there:

vars:
dockerfileGlob: services/*/Dockerfile
plugins:
- name: autodocker
config:
glob: ${vars:dockerfileGlob}

Because plugins are constructed before the configuration’s own environment is installed, ${env:...} in a plugin config resolves against the shell environment only. Variables declared in this file’s env block, or loaded by the dotenv plugin, are not yet available and silently fall back to the placeholder default. Use vars for values defined inside the configuration file.

Optional. Environment variables available to all processes.

env:
DOCKER_TAG: ${env:DOCKER_TAG:-latest}
NODE_ENV: development

Supports variable expansion with ${env:VAR_NAME:-default} syntax.

Optional. Variables for string expansion (not passed to subprocesses).

vars:
version: "1.0.0"
registry: "docker.io/myorg"

Optional. Default settings for builds and execution.

defaults:
docker:
tag: ${env:DOCKER_TAG} # Default image tag
target: development # Default build target
platform: linux/amd64 # Target platform (e.g., linux/amd64, linux/arm64)
buildArgs: # Default build arguments
NODE_ENV: development
labels: # Default labels
maintainer: team@example.com
publish: # Default publishing settings
registry: ghcr.io/myorg # Registry to push images to
tag: ${env:VERSION} # Tag override for publishing
kubernetes:
namespace: staging # Default namespace for K8s operations
selectorLabel: app.kubernetes.io/component # Label for pod selection
build:
concurrency: auto # Build this many resources in parallel (default: 1)

Kubernetes defaults:

OptionDescriptionDefault
namespaceDefault Kubernetes namespacedefault
selectorLabelLabel name used to find component podsapp.kubernetes.io/component

Build defaults:

OptionDescriptionDefault
concurrencyHow many resources to build in parallel. A positive integer, or "auto" for min(CPU count, 4).1 (serial)

defaults.build.concurrency sets the project-wide default; emb resources build --jobs and emb up --jobs override it per run. Dependency order is always respected — see Parallel builds.

defaults:
build:
concurrency: 4 # a positive integer
# concurrency: auto # or min(CPU count, 4)

defaults.build rejects unknown keys, so a typo (concurrancy, jobs, parallelism) fails validation rather than being silently ignored.

Optional. Inline component definitions (usually loaded via plugins).

components:
api:
rootDir: services/api
resources:
image:
type: docker/image
tasks:
test:
script: npm test

Optional. Project-level tasks.

tasks:
lint:
script: npm run lint
deploy:
pre: [lint, test]
script: ./scripts/deploy.sh

Optional. Project-level flavor configurations.

flavors:
production:
patches:
- op: replace
path: /env/NODE_ENV
value: production

Optional. Path to component root (auto-detected).

rootDir: services/api

Optional. Human-readable description.

description: REST API service

Optional. Resources this component provides.

resources:
image:
type: docker/image
publish: true # Mark as publishable (opt-in)
dependencies:
- base:image
params:
target: development
buildArgs:
NODE_ENV: development
labels:
version: "1.0.0"
context: .
dockerfile: Dockerfile

Common resource properties:

PropertyTypeDescription
typestringResource type (required): docker/image, file, op/file
publishbooleanMark resource as publishable for emb resources publish
dependenciesarrayList of resource IDs this depends on
paramsobjectType-specific parameters
rebuildTriggerobjectOverrides when a rebuild happens. Read by docker/image resources. See Rebuild triggers.

Resource types:

Builds a Docker image.

ParameterTypeDescription
imagestringImage name (without project prefix or tag). Defaults to component name.
tagstringImage tag. Defaults to defaults.docker.tag or latest.
targetstringBuild stage to target
platformstringTarget platform (e.g., linux/amd64, linux/arm64)
buildArgsobjectBuild arguments
labelsobjectImage labels
contextstringBuild context path
dockerfilestringDockerfile path
publish.registrystringRegistry to push to (overrides defaults.docker.publish.registry)
publish.tagstringTag for publishing (overrides defaults.docker.publish.tag)

By default a docker/image resource rebuilds when any git-tracked file under its build context has a newer mtime than the sentinel from the last successful build. That’s the right default for CI and production. In dev, where source is often bind-mounted into containers, it’s wasteful — the running container already sees the new code.

The rebuildTrigger field on the resource (or a flavor-level default under flavors.<flavor>.defaults.rebuildPolicy['docker/image']) lets you pick how the rebuild decision is made.

StrategyRebuilds whenTypical use
auto (default)any git-tracked file in the docker context has changedCI, production
alwaysevery invocationimages that fetch external content at build time
watch-pathsone of the listed paths has changeddev with bind-mounted source
resources:
image:
type: docker/image
rebuildTrigger:
strategy: watch-paths
paths:
- Dockerfile
- package.json
- /shared/base.Dockerfile # /-prefix escapes to monorepo root

Paths in watch-paths are resolved against the resource’s docker context (the same base used for dockerfile / context). A leading / escapes to the monorepo root, which is useful for shared files like root-level lockfiles or base Dockerfiles.

rebuildTrigger follows this precedence, highest wins:

  1. resources.<name>.rebuildTrigger on the resource itself.
  2. flavors.<flavor>.defaults.rebuildPolicy['docker/image'] on the active flavor — see Flavors → Rebuild policies.
  3. Built-in { strategy: auto }.

Non-auto rebuilds (and any --force run) print the resolved strategy, source, reason, and watched files in the build output, so you can see exactly why a rebuild did or didn’t happen.

Regardless of the strategy, two invariants hold:

  • If a dependency was rebuilt, this resource rebuilds too (dep cascade).
  • --force always rebuilds.

Generates a file.

ParameterTypeDescription
pathstringOutput file path (defaults to resource name)
contentstringContent to write to the file (supports template expansion with secrets)
scriptstringScript to generate the file

Example with content and secrets:

resources:
.env:
type: file
params:
content: |
DATABASE_URL=${op:Private/db-credentials#connection_string}
API_KEY=${op:Private/api-keys#production}

Example with script:

resources:
config.json:
type: file
params:
path: config.json
script: |
echo '{"key": "value"}' > config.json

Note: If both content and script are provided, content takes precedence.

Materializes a 1Password attachment (document or file field) as a file on disk. Requires a configured 1Password provider.

ParameterTypeDescription
referencestringRequired. Full 1Password secret reference, e.g. op://vault/item/file
pathstringDestination path relative to the component (defaults to the resource name)
resources:
service-account.json:
type: op/file
params:
reference: op://Production/gcp-service-account/credentials.json
path: .secrets/service-account.json

Optional. Component tasks.

tasks:
test:
description: Run tests
script: npm test
executors:
- container # Run in container (default)
vars:
NODE_ENV: test

Task properties:

PropertyTypeDescription
descriptionstringTask description
scriptstringShell script to execute. Required unless pre is set
prearrayTasks to run before this one. Required if script is omitted
dependenciesarrayResource refs (name or component:name) that must be built before this task runs
executorsarrayWhere to run: local, container, or kubernetes
interactivebooleanRequires TTY (default: false)
varsobjectTask-specific variables
confirmobjectRequire user confirmation

Every task must define script, pre, or both. A task with neither (for example one carrying only a description) fails validation of the entire configuration file, not just that task.

Optional. Component-level flavors.

flavors:
production:
patches:
- op: replace
path: /resources/image/params/target
value: production

Optional. Kubernetes-specific configuration for the component.

kubernetes:
selector: app=api,tier=backend # Custom label selector for finding pods
container: main # Container name for multi-container pods
OptionDescription
selectorLabel selector to find pods (overrides default {selectorLabel}={component})
containerContainer name for multi-container pods

EMB supports variable expansion in configuration values:

env:
# Use environment variable with default
TAG: ${env:DOCKER_TAG:-latest}
# Use another config variable
IMAGE: ${vars:registry}/app:${env:TAG}
# Use a secret from Vault
DATABASE_URL: ${vault:secret/myapp/database#url}

Syntax:

  • ${env:VAR_NAME} - Environment variable (required)
  • ${env:VAR_NAME:-default} - Environment variable with default
  • ${vars:VAR_NAME} - Config variable
  • ${vault:path#key} - Secret from Vault (requires vault plugin)

Flavors use JSON Patch (RFC 6902) operations:

patches:
# Add a new property
- op: add
path: /resources/image/params/labels/version
value: "2.0.0"
# Replace existing value
- op: replace
path: /resources/image/params/target
value: production
# Remove a property
- op: remove
path: /resources/image/params/buildArgs/DEBUG
# Move a property
- op: move
from: /old/path
path: /new/path
# Copy a property
- op: copy
from: /source/path
path: /dest/path
.emb.yml
project:
name: my-app
plugins:
- name: autodocker
- name: dotenv
config: [.env]
- name: embfiles
env:
DOCKER_TAG: ${env:DOCKER_TAG:-latest}
REGISTRY: docker.io/myorg
defaults:
docker:
tag: ${env:DOCKER_TAG}
tasks:
deploy:
pre: [build]
script: ./deploy.sh
flavors:
production:
patches:
- op: replace
path: /env/DOCKER_TAG
value: ${env:VERSION:-latest}
api/Embfile.yml
description: REST API service
resources:
image:
type: docker/image
params:
target: development
tasks:
test:
description: Run API tests
script: npm test
migrate:
description: Run database migrations
executors: [local]
script: npm run migrate
flavors:
production:
patches:
- op: replace
path: /resources/image/params/target
value: production