Skip to main content

Workflows secrets: 1Password

Wire 1Password-backed secrets into Loom workflows using op:// references. Loom resolves entries through the 1Password Go SDK at execution time — no op CLI installation required.

Prerequisites

  • A 1Password service account with access to the target vault(s). Create one at 1Password service accounts.
  • OP_SERVICE_ACCOUNT_TOKEN exported in the shell or CI runner environment.
  • At least one item stored in an accessible vault.

If you have not set up 1Password with Loom yet, follow Getting started with secrets — Option A: 1Password.

Example job

This deployment example uses placeholder URLs. Replace them with your service endpoints before running it. The walkthrough below uses a local file check.

deploy:
stage: ci
target: linux
secrets:
DEPLOY_TOKEN:
ref: op://Engineering/services/loom/deploy/token
file: true
required: true
API_PASSWORD:
ref: op://Engineering/services/loom/api/password
file: false
script:
- echo "Deploying with credentials..."
- 'curl -H "Authorization: Bearer $(cat "$DEPLOY_TOKEN")" https://api.example.com/deploy'

DEPLOY_TOKEN is file-injected (default) — the variable holds a temp-file path, so the script reads the value with cat. API_PASSWORD uses direct injection (file: false) and is available as a raw environment variable.

URI anatomy

op://<vault>/<item-path>/<field>
└──┬──┘ └────┬────┘ └──┬──┘
vault name item title/ field to
or UUID path segment resolve
SegmentDescriptionExample
<vault>1Password vault name or UUID. The service account must have access to this vault.Engineering
<item-path>Item title or path segment as stored in 1Password. Use / separators for nested organization.services/loom/deploy
<field>Field name to resolve from the item.token, password, username

Full example: op://Engineering/services/loom/deploy/token resolves the token field from the item at services/loom/deploy in the Engineering vault.

Runtime configuration

1Password resolution requires a single environment variable:

VariablePurposeRequired
OP_SERVICE_ACCOUNT_TOKENService account token (starts with ops_...) used to authenticate with the 1Password APIYes
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."

Verify connectivity by listing accessible vaults:

loom secrets op vault list

If the token is missing, expired, or lacks access to the target vault, resolution fails with SECRETS_PROVIDER_UNAVAILABLE.

Script behavior by injection mode

file: true (default) — the variable holds a file path:

TOKEN=$(cat "$DEPLOY_TOKEN")
curl -H "Authorization: Bearer ${TOKEN}" https://api.example.com/deploy

file: false — the variable holds the raw value:

echo "machine api.example.com password ${API_PASSWORD}" >> ~/.netrc

Prefer file: true unless your tool requires a direct environment value. Loom sets the job variable to a temporary file path and restricts the file to 0600 permissions. This reduces exposure through environment inspection and commands that use only the path. The protection depends on those permissions and Loom's temporary-file cleanup: a tool that reads the contents into a shell trace, process argument, log, or artifact can still expose the value.

For Docker jobs, file-injected secrets are bind-mounted read-only into the container. Scripts inside the container use the same cat "$VAR" pattern.

Complete walkthrough

From service account setup to a successful workflow run:

1. Export the service account token:

export OP_SERVICE_ACCOUNT_TOKEN="ops_..."

2. Verify vault access:

loom secrets op vault list

Expected output:

name=Engineering id=vlt_abc123

3. Store a secret (or use an existing item):

export DEPLOY_TOKEN_VALUE="tok_example_abc123"

loom secrets op item create \
--vault Engineering \
--item-path services/loom/deploy \
--field token \
--value-from-env DEPLOY_TOKEN_VALUE

4. Save this as .loom/workflow.yml:

version: v1
stages: [ci]

check-secret:
stage: ci
target: linux
secrets:
DEPLOY_TOKEN:
ref: op://Engineering/services/loom/deploy/token
script:
- test -r "$DEPLOY_TOKEN" && test -s "$DEPLOY_TOKEN"
- echo "Secret file is readable and non-empty"

5. Validate and run:

loom check validates structure; the run resolves the secret. The script should print Secret file is readable and non-empty and the run should exit with status 0.

loom check
loom run --local --workflow .loom/workflow.yml

Safety checklist

  • Keep the service account token outside workflow YAML and variables blocks — supply it through the runtime environment only.
  • Use least-privilege token scoping — grant access only to the vaults and items your workflows require.
  • Rotate service account tokens on a defined schedule.
  • Prefer file: true for lower leakage risk.
  • Avoid CI_DEBUG_TRACE=true when any secret uses file: false.
  • Validate with loom check before running.

Troubleshooting

SymptomLikely causeFix
SECRETS_PROVIDER_UNAVAILABLEMissing, expired, or invalid OP_SERVICE_ACCOUNT_TOKEN, or token lacks access to the target vaultVerify the token is exported and valid; check vault access with loom secrets op vault list
SECRETS_REF_NOT_FOUNDVault, item, or field does not exist in 1PasswordList items with loom secrets op item list --vault <vault> and confirm the path and field
SECRETS_REF_INVALIDMalformed op:// URI (missing vault, item, or field segment)Check URI format: op://<vault>/<item-path>/<field>
SECRETS_REQUIRED_MISSINGRequired secret could not be resolved and required is true (default)Fix the provider config, or set required: false if the secret is optional
Script gets a file path instead of a valuefile: true (default) but script expects raw valueUse cat "$VAR" in the script, or set file: false on the secret