Skip to content

Variables Reference

For a complete list of the automatically injected run metadata, see Special Environment Variables.

Environment Variables

System Environment Variable Filtering

Dagu filters the process environment before it builds the step execution environment.

System environment variables are still available for expansion (${VAR}) while Dagu parses the DAG, but only a filtered subset is forwarded to step processes and sub-DAG executions.

The built-in forwarded variables are platform-dependent:

  • Unix and macOS exact names: PATH, HOME, USER, SHELL, TMPDIR, TERM, EDITOR, VISUAL, LANG, LC_ALL, LC_CTYPE, TZ, LD_LIBRARY_PATH, XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_CACHE_HOME, DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH, DOCKER_API_VERSION
  • Windows exact names: USERPROFILE, SYSTEMROOT, WINDIR, SYSTEMDRIVE, COMSPEC, PATHEXT, TEMP, TMP, PATH, PSMODULEPATH, HOME, DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH, DOCKER_API_VERSION
  • Allowed prefixes on all platforms: DAGU_, DAG_, LC_, KUBERNETES_

DAG_ includes the runtime variables Dagu sets for each step. KUBERNETES_ allows in-cluster API discovery variables such as KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT.

You can extend the forwarded set in server configuration with top-level env_passthrough and env_passthrough_prefixes. The matching env vars are only forwarded if they already exist in Dagu's own process environment.

yaml
# config.yaml
env_passthrough:
  - SSL_CERT_FILE
  - HTTP_PROXY
  - HTTPS_PROXY
  - NO_PROXY

env_passthrough_prefixes:
  - AWS_
  - CUSTOM_CA_

The same settings are available through:

  • DAGU_ENV_PASSTHROUGH=SSL_CERT_FILE,HTTP_PROXY,HTTPS_PROXY,NO_PROXY
  • DAGU_ENV_PASSTHROUGH_PREFIXES=AWS_,CUSTOM_CA_

On Unix, exact-name and prefix matching are case-sensitive. On Windows, they are case-insensitive.

If a variable is not in the forwarded set, it can still be referenced during DAG parsing, but it will not appear in the step process environment unless you copy it into env:, dotenv, or secrets:. Use secrets: for credentials and other sensitive values.

Defining Environment Variables

Set environment variables available to all steps:

yaml
env:
  - LOG_LEVEL: debug
  - DATA_DIR: /tmp/data
  - API_URL: https://api.example.com
  - AWS_REGION: ${AWS_REGION}   # Explicitly reference a non-sensitive system variable

Important: Sensitive system environment variables should normally be declared through secrets: rather than copied into env:. Explicit env: references are better suited to non-sensitive values.

Variable Expansion

Reference other variables:

yaml
env:
  - BASE_DIR: ${HOME}/data
  - INPUT_DIR: ${BASE_DIR}/input
  - OUTPUT_DIR: ${BASE_DIR}/output
  - CONFIG_FILE: ${INPUT_DIR}/config.yaml

Unknown Variable Handling

When a variable is referenced but not defined in Dagu's context, the behavior depends on the execution context:

Shell expansion enabled (default for local shell execution): Unknown variables become empty strings. This is standard POSIX shell behavior.

Non-shell executors (docker, http, ssh, jq, mail, etc.): OS-only variables not defined in the DAG scope are preserved as-is, letting the target environment resolve them. DAG-scoped variables (env, params, secrets, step outputs) are still expanded normally.

Template steps: The script body is not expanded by Dagu at all, so ${VAR} remains literal there. Pass values through config.data when you want Dagu to expand them before template rendering.

yaml
# Example: Non-shell executor (SSH)
env:
  - DEPLOY_BRANCH: main

steps:
  - type: ssh
    config:
      user: deploy
      host: remote.example.com
    command: |
      cd $HOME/app                    # $HOME preserved — remote shell resolves it
      git checkout ${DEPLOY_BRANCH}   # Expanded by Dagu — defined in DAG env

In this example, $HOME is not defined in the DAG scope, so it passes through unchanged to the remote shell. ${DEPLOY_BRANCH} is defined in the DAG env:, so Dagu expands it before sending.

Literal Dollar Signs

In non-shell contexts (docker, http, ssh, jq, mail, etc.), you can emit a literal $ by escaping it with a backslash:

yaml
env:
  - PRICE: '\$9.99'   # Becomes $9.99 at runtime

Notes:

  • \$ is only unescaped when Dagu is the final evaluator (non-shell executors and config fields).
  • Shell-executed commands keep native shell semantics. Use shell escaping there.
  • To get a literal $$ in non-shell contexts, escape both dollars: \$\$.
  • In YAML, single quotes preserve backslashes; with double quotes, escape the backslash (e.g., "\\$9.99").
  • template step script bodies are excluded because Dagu does not process $ there.

Loading from .env Files

Load variables from dotenv files:

yaml
# Single file
dotenv: .env

# Multiple files (loaded in order)
dotenv:
  - .env
  - .env.local
  - configs/.env.${ENVIRONMENT}

Example .env file:

bash
DATABASE_URL=postgres://localhost/mydb
API_KEY=secret123
DEBUG=true

Parameters

Positional Parameters

Define default positional parameters:

yaml
params: first second third

steps:
  - command: echo "Args: $1 $2 $3"

Run with custom values:

bash
dagu start workflow.yaml -- one two three

Named Parameters

Define named parameters with defaults:

yaml
params:
  - ENVIRONMENT: dev
  - PORT: 8080
  - DEBUG: false

steps:
  - command: ./server --env=${ENVIRONMENT} --port=${PORT} --debug=${DEBUG}

Override at runtime:

bash
dagu start workflow.yaml -- ENVIRONMENT=prod PORT=80 DEBUG=true

Accessing Parameters as JSON

Every step receives the full parameter map encoded as JSON via DAG_PARAMS_JSON. This value reflects the merged defaults plus any runtime overrides. Resolved DAG params are serialized as strings, and when a run is started with raw JSON parameters, the original payload is preserved. Raw JSON may be an object or an array, but named params should use an object. The variable is not set when the DAG has no parameters and none were supplied.

yaml
steps:
  - id: print_params
    command: echo "Raw payload: ${DAG_PARAMS_JSON}"
  - id: batch_size
    type: jq
    config:
      raw: true
    script: ${DAG_PARAMS_JSON}
    command: '"Batch size: \(.batchSize // "n/a")"'

Use this when downstream scripts prefer structured data or when you need access to parameters that were provided as nested JSON.

Mixed Parameters

Combine positional and named parameters:

yaml
params:
  - ENVIRONMENT: dev
  - VERSION: latest

steps:
  - command: echo "Deploying $1 to ${ENVIRONMENT} version ${VERSION}"

Run with:

bash
dagu start workflow.yaml -- myapp ENVIRONMENT=prod VERSION=1.2.3

Command Substitution

Execute commands and use their output in env: blocks using backticks. This runs the command at DAG load time and stores the result:

yaml
env:
  - TODAY: "`date +%Y-%m-%d`"
  - HOSTNAME: "`hostname -f`"
  - GIT_COMMIT: "`git rev-parse HEAD`"

steps:
  - command: echo "Deploy on ${TODAY} from ${HOSTNAME}"

Note: Command substitution is always supported in env: blocks. For DAG-level params:, use eval: on an inline rich param definition when you want $VAR expansion or backtick command substitution. Literal default values and runtime overrides from the CLI, API, and sub-DAG calls remain literal.

Output Variables

Capturing Output

Capture command output to use in later steps:

yaml
steps:
  - command: cat VERSION
    output: VERSION
  - command: docker build -t myapp:${VERSION} .

Output Size Limits

Control maximum output size:

yaml
# Global limit for all steps
max_output_size: 5242880  # 5MB

steps:
  - command: cat large-file.json
    output: FILE_CONTENT  # Fails if > 5MB

Redirecting Output

Redirect to files instead of capturing:

yaml
steps:
  - command: python report.py
    stdout: /tmp/report.txt
    stderr: /tmp/errors.log

JSON Path References

Access nested values in JSON output:

yaml
steps:
  - command: |
      echo '{"db": {"host": "localhost", "port": 5432}}'
    output: CONFIG
    
  - command: psql -h ${CONFIG.db.host} -p ${CONFIG.db.port}

Sub-workflow Output

Access outputs from nested workflows:

yaml
steps:
  - call: etl-workflow
    params: "DATE=${TODAY}"
    output: ETL_RESULT
    
  - command: |
      echo "Records processed: ${ETL_RESULT.outputs.record_count}"
      echo "Status: ${ETL_RESULT.outputs.status}"

Step ID References

Reference step properties using IDs:

yaml
steps:
  - id: risky
    command: 'sh -c "if [ $((RANDOM % 2)) -eq 0 ]; then echo Success; else echo Failed && exit 1; fi"'
    continue_on: failed

  - command: |
      if [ "${risky.exit_code}" = "0" ]; then
        echo "Success! Output was:"
        cat ${risky.stdout}  # Read content from file path
      else
        echo "Failed with code ${risky.exit_code}"
        cat ${risky.stderr}  # Read content from file path
      fi

Available properties:

  • ${id.exit_code} - Exit code of the step (as a string, e.g., "0" or "1")
  • ${id.stdout} - Path to stdout log file
  • ${id.stderr} - Path to stderr log file
  • ${id.output} - Captured output value (requires output: on the referenced step)

Important: ${id.stdout} and ${id.stderr} return file paths, not the actual output content.

  • To read content: use cat ${id.stdout}
  • To capture output for later steps: use the output: field instead
  • Substring slicing like ${id.stdout:0:5} operates on the file path string, not file content

${id.output} returns the actual captured text value. If the referenced step does not have output: configured, the reference is not expanded and passes through as a literal. Substring slicing works: ${id.output:0:5} extracts the first 5 characters of the captured value.

Variable Precedence

Dagu resolves variables in two places: when interpolating ${VAR} in DAG fields, and when constructing the step process environment.

Interpolation precedence (highest to lowest)

  1. Step-level environment

    yaml
    steps:
      - env:
          - VAR: step-value
  2. Output variables from earlier steps

    yaml
    steps:
      - command: echo 42
        output: VAR
  3. Secrets

    yaml
    secrets:
      - name: VAR
        provider: env
        key: VAR
  4. DAG-level environment (including dotenv)

    yaml
    env:
      - VAR: env-value
    dotenv: .env
  5. Parameters (defaults + CLI overrides)

    yaml
    params:
      - VAR: dag-default
  6. Process environment fallback For shell commands, system environment variables are used if the key is not set by any of the sources above, and are still subject to filtering at execution time. For non-shell executors (docker, http, ssh, jq, mail, etc.), OS environment is not used as a fallback during variable interpolation — only DAG-scoped sources (levels 1–5) are checked. OS-only variables pass through unchanged, letting the target environment resolve them. template step script bodies are a special case: Dagu does not interpolate them at all, while config.data values still use DAG-scoped sources.

Step process environment precedence (lowest to highest)

  1. Filtered system environment
  2. DAG runtime environment (params + env + .env + run metadata) If a key appears in both params and env, the env value wins.
  3. Secrets
  4. Step-level environment
  5. Output variables from earlier steps

See Also

Released under the MIT License.