Secrets
secrets: declares environment variables whose values are resolved when a DAG run starts.
Dagu supports two secret declaration styles:
- Registry refs for secrets managed from Dagu's Web UI.
- Direct provider refs for existing DAG-based secrets such as
env,file,kubernetes, andvault.
Both styles inject a target environment variable into the run. The value is resolved before steps start and is masked in Dagu-managed logs.
Registry Refs
Use ref when the secret value is managed in Dagu's secret registry:
secrets:
- name: DB_PASSWORD
ref: prod/db-passwordname is the environment variable exposed to steps. ref is the registry key. The DAG does not store the plaintext value or provider details.
Create or rotate the value in the Web UI under Secrets:
- Select Global or a named workspace.
- Create a Dagu-managed secret with ref
prod/db-password. - Use
ref: prod/db-passwordin DAGs.
labels:
- workspace=payments
secrets:
- name: DB_PASSWORD
ref: prod/db-password
steps:
- name: migrate
run: ./migrate.shRegistry refs are resolved by scope:
| Secret scope | Resolution behavior |
|---|---|
| Global | Workspace-less secret available to all DAGs unless a more specific scope has the same ref |
| Named workspace | Secret for DAGs with the matching workspace=<name> label |
A DAG in workspace=payments first checks the payments secret scope, then the Global scope. It never reads another named workspace. A DAG without a workspace label uses Global directly.
Do not include the scope or workspace name in ref; use ref: prod/db-password, not ref: payments/prod/db-password. If a more specific scoped secret exists but is disabled, Dagu fails the run instead of falling back to a global secret with the same ref.
Registry refs currently resolve Dagu-managed secrets. External registry providers such as Vault, cloud secret managers, and Kubernetes-backed registry records are request-based and are not creatable through the secret management API yet. Use Request access to contact the Dagu team. Existing direct provider refs still work as described below.
Direct Provider Refs
Use provider plus key when the DAG should fetch a secret directly from a provider at runtime:
secrets:
- name: DB_PASSWORD
provider: env
key: PROD_DB_PASSWORDThe current built-in direct provider registry contains:
| Provider | Source |
|---|---|
env | A variable from the context environment scope, an internal Dagu transport variable, or the Dagu process environment |
file | The complete contents of one local file |
kubernetes | One data key from a Kubernetes Secret resource |
vault | One field from a HashiCorp Vault secret response |
Existing DAGs that use provider and key continue to work. Direct provider refs do not require the Web UI secret registry.
secrets:
- name: API_TOKEN
provider: file
key: /run/secrets/api-token
- name: STRIPE_WEBHOOK_SECRET
provider: kubernetes
key: payments/stripe-webhook-secret
options:
namespace: prodSecret Reference Schema
Each item must use exactly one of these shapes:
# Registry ref
secrets:
- name: TARGET_ENV_NAME
ref: prod/example-secret# Direct provider ref
secrets:
- name: TARGET_ENV_NAME
provider: env
key: SOURCE_ENV_NAME
options:
option_name: option_value| Field | Required | Meaning |
|---|---|---|
name | Yes | Target environment variable injected into the run |
ref | Required for registry refs | Registry ref, for example prod/db-password |
provider | Required for direct provider refs | Resolver name. Built-in values are env, file, kubernetes, and vault |
key | Required for direct provider refs | Provider-specific lookup key |
options | Direct provider refs only | Provider-specific string map |
Validation rules:
namemust be a valid environment variable name.namemust be unique inside the DAG.namemust not start withDAGU_.refmust be lowercase slug segments separated by/, for exampleprod/db-password.refcannot be combined withprovider,key, oroptions.- Direct provider refs require both
providerandkey.
Provider existence and backing secret availability are checked when the run resolves secrets. An unknown provider such as unknown-provider fails the run with unknown secret provider.
Literal Keys And Options
secrets[].key and secrets[].options are not evaluated with Dagu's variable engine. They are passed to the direct provider as literal strings.
This does not resolve SECRET_FILE_PATH:
env:
- SECRET_FILE_PATH: /run/secrets/api-token
secrets:
- name: API_TOKEN
provider: file
key: ${SECRET_FILE_PATH} # literal path, not expandedTo read a value loaded from .env, use the env provider:
# .env
PROD_API_TOKEN=token-from-dotenvdotenv: .env
secrets:
- name: API_TOKEN
provider: env
key: PROD_API_TOKENdotenv: is related, but it is not a secret provider. Dotenv files load normal DAG environment variables. A dotenv value becomes a masked secret only when a secrets: entry reads it through provider: env.
Resolution Time
When a DAG run starts, Dagu:
- Loads dotenv files into the DAG environment.
- Resolves all entries in
secrets:. - Adds resolved secret values to the run environment with source
secret. - Starts steps only if secret resolution succeeds.
If any secret fails to resolve, run initialization fails and steps do not execute. dagu dry also resolves secrets. dagu validate checks YAML shape and DAG structure, but it does not contact providers and does not verify that a secret exists.
Variable Precedence
During step execution, the environment scope is layered so later layers override earlier layers:
- Step environment values, including evaluated
env:entries and container env entries for the step. - Output variables from dependency steps.
- Secrets.
- DAG-level environment values, including values loaded from dotenv files, runtime metadata, and params.
- Filtered process environment values.
This means a secret overrides DAG env: and dotenv values with the same name. This is allowed for backward compatibility with existing DAGs. A step-level env: value can still override the secret for that step.
env:
- DB_PASSWORD: visible-dag-env
secrets:
- name: DB_PASSWORD
provider: env
key: PROD_DB_PASSWORD
steps:
- name: uses-secret
run: ./migrate.sh
- name: overrides-for-one-step
env:
- DB_PASSWORD: local-test-password
run: ./test.shStorage For Dagu-Managed Secrets
Dagu-managed registry values are stored by Dagu in the internal secret store under the configured data directory:
<data_dir>/secretsThe file-backed implementation stores secret metadata and encrypted value versions. Plaintext values are write-only through the API and Web UI: after saving, Dagu does not return the value in API responses. Values are decrypted only when a run resolves the secret.
The encryption key is resolved from the same data directory. Back up the data directory securely if you rely on Dagu-managed secrets.
Masking
Dagu creates a masker from non-empty resolved secret values. The replacement string is *******.
The masker is applied to:
- Step stdout and stderr log writers.
- Step stdout and stderr redirect writers.
- Final
outputs.jsonvalues collected from string-formoutput: NAME,stdout.outputs, andoutputs.write. - Chat step messages immediately before they are sent to the LLM provider.
The matcher replaces exact secret values. It does not mask empty values. It also does not mask values loaded through env: or dotenv: unless those values are resolved through secrets:.
Masking is not a process sandbox. The step process receives the raw secret in its environment and can write it to files, databases, APIs, child processes, or output variables used by later steps.
Provider Pages
Complete Example
# /srv/app/.env
SLACK_BOT_TOKEN=xoxb-from-dotenvworking_dir: /srv/app
labels:
- workspace=payments
dotenv: .env
secrets:
# Dagu-managed registry secret in the payments workspace
- name: DB_PASSWORD
ref: prod/db-password
# Existing direct provider secrets
- name: SLACK_TOKEN
provider: env
key: SLACK_BOT_TOKEN
- name: API_KEY
provider: vault
key: kv/data/prod/api/key
- name: STRIPE_WEBHOOK_SECRET
provider: kubernetes
key: payments/stripe-webhook-secret
options:
namespace: prod
steps:
- name: deploy
run: ./deploy.sh
env:
- DATABASE_URL: postgres://app:${DB_PASSWORD}@db/prod
- AUTH_HEADER: "Bearer ${API_KEY}"