KeePass in workflows
Wire keepass:// secrets into Loom workflow jobs. This page covers declaration syntax, injection modes, optional secrets, multi-secret patterns, Docker job behavior, and validation.
Declaring a KeePass secret
Add a secrets block to any job. Each key becomes an environment variable available to the job's script.
version: v1
stages: [ci]
deploy:
stage: ci
target: linux
secrets:
DATABASE_PASSWORD:
ref: keepass://local/main#services/loom/deploy:password
script:
- ./scripts/deploy.sh
Spec fields
| Field | Required | Default | Description |
|---|---|---|---|
ref | Yes | — | KeePass URI in the format keepass://<alias>#<entry-path>:<field> |
file | No | true | When true, Loom writes the value to a 0600 temp file and sets the env var to the file path. When false, the raw value is placed directly in the env var. |
required | No | true | When true, the job fails if the secret cannot be resolved. When false, the env var is omitted and the job continues. |
Scoping rules
- Secrets are job-scoped only. Declaring secrets under
defaultis invalid and rejected by the schema validator. - A key cannot appear in both
variablesandsecretson the same job — the validator rejects the overlap.
Injection modes
File injection (default, recommended)
secrets:
DATABASE_PASSWORD:
ref: keepass://local/main#services/loom/deploy:password
file: true
The job environment variable contains a file path. Read the value in scripts:
DB_PASS=$(cat "$DATABASE_PASSWORD")
curl -u "admin:${DB_PASS}" https://db.example.com/health
File injection is the default (file: true). Prefer it because:
- Secret bytes never appear in the process environment table (not visible to
psor/proc/*/environ). - Shell tracing (
set -x) prints the file path, not the value. - Tools that accept credential files (e.g.
--password-file) work directly with the path.
Direct injection (use only when required)
secrets:
API_TOKEN:
ref: keepass://local/main#services/loom/deploy:token
file: false
The job environment variable contains the raw secret value. Use only when a tool requires an environment variable value and cannot read from a file.
echo "machine api.example.com password ${API_TOKEN}" >> ~/.netrc
CI_DEBUG_TRACE=true combined with any file: false secret triggers a hard failure (SECRETS_UNSAFE_DEBUG_TRACE) before job execution. Either disable debug trace or switch the secret to file: true.
Optional secrets
Mark a secret required: false when the workflow should continue even if the secret is unavailable:
secrets:
OPTIONAL_WEBHOOK:
ref: keepass://local/main#services/loom/notifications:webhook
required: false
If resolution fails, the environment variable is omitted entirely — it is not set to an empty string. Scripts can check for its presence:
if [ -n "${OPTIONAL_WEBHOOK+x}" ]; then
curl -X POST "$(cat "$OPTIONAL_WEBHOOK")" -d '{"status": "deployed"}'
fi
Multiple secrets in a single job
Jobs can declare any number of secrets. Each resolves independently.
deploy:
stage: ci
target: linux
secrets:
DATABASE_PASSWORD:
ref: keepass://local/main#services/loom/deploy:password
API_TOKEN:
ref: keepass://local/main#services/loom/deploy:token
file: false
DEPLOY_KEY:
ref: keepass://team#infra/deploy:ssh-key
script:
- ./scripts/deploy.sh
Secrets can reference different aliases (local, team) in the same job. Each alias resolves through its own set of LOOM_KEEPASS_DB_<KEY>_* environment variables.
Docker jobs
For Docker-based jobs (target: docker or jobs with an image field), file-injected secrets are automatically bind-mounted read-only into the container. Loom rewrites the environment variable to the container-local path.
deploy:
stage: ci
target: docker
image: alpine:3.19
secrets:
DATABASE_PASSWORD:
ref: keepass://local/main#services/loom/deploy:password
script:
- DB_PASS=$(cat "$DATABASE_PASSWORD")
- echo "Connected with credentials"
Scripts inside the container use the same cat "$VAR_NAME" pattern — no path translation needed.
URI authoring guidelines
| Guideline | Example | Rationale |
|---|---|---|
| Use environment-specific aliases | local, team, prod | Makes workflow YAML portable across environments |
| Use predictable entry paths | services/loom/<component> | Easier to audit and discover with item list |
| Use explicit field names | password, token, username | Self-documenting; avoids reliance on default fields |
| Specify enough path segments | services/loom/deploy not just deploy | Prevents ambiguous matches (see entry path matching) |
Validation
Always validate before running to catch URI format errors and missing configuration early:
loom check
loom check validates:
- URI syntax for all
keepass://references. - No overlap between
secretsandvariableskeys. - No secrets declared under
default.
To run the workflow after validation:
loom run --local --workflow .loom/workflow.yml
Troubleshooting
| Error code | Cause | Fix |
|---|---|---|
SECRETS_PROVIDER_UNAVAILABLE | Alias mapping or credential environment is misconfigured | Verify LOOM_KEEPASS_DB_<KEY>_* env vars — see Install and setup |
SECRETS_REF_NOT_FOUND | Entry path or field does not exist in the .kdbx file | Run loom secrets keepass item list to check available entries |
SECRETS_REF_INVALID | Malformed URI or ambiguous entry path | Check URI format against URI format |
SECRETS_REQUIRED_MISSING | A required: true secret could not be resolved | Fix the provider config or set required: false for optional secrets |
SECRETS_UNSAFE_DEBUG_TRACE | CI_DEBUG_TRACE=true with a file: false secret | Remove debug trace or switch the secret to file: true |
Related pages
- KeePass provider overview — URI format, resolution model, and full error reference.
- KeePass install and setup — First-time environment configuration.
- CLI reference — Manage vaults and entries from the command line.
- Secrets overview — Cross-provider secrets system documentation.
- Secrets security — Threat model and operational guardrails.