Secret Providers
Haloy integrates with external secret providers to securely resolve credentials during configuration resolution. Define reusable sources under secret_providers, then reference individual values with from.secret.
Secret Reference Format
Secret references use this format:
<provider>:<source>:<key>
<provider>:<source>:<key>
<provider>: The provider name, currentlyonepasswordorsops<source>: The source key defined undersecret_providers.<provider><key>: The field or nested key to resolve from that source
Examples:
onepassword:production-db:passwordsops:development:client.idsops:development:users.0.name
This replaces the earlier provider:source.key proposal. Update existing configurations to the new provider:source:key syntax.
1Password Integration
Configure 1Password to pull item fields during config resolution.
Prerequisites
- 1Password CLI (
op) installed and authenticated - The referenced vault items must exist with fields matching the keys you use in
from.secret
How Haloy Maps to 1Password
A 1Password secret reference has two parts: the reusable source you define under secret_providers.onepassword, and the field key you reference from from.secret.
| Haloy setting | 1Password meaning | Where to find or set it |
|---|---|---|
account | The 1Password account to use. This is optional unless you have multiple 1Password accounts configured. | In the 1Password app, select the account or collection at the top of the sidebar. In the CLI, run op account list and use the URL or USER ID value. |
vault | The vault that contains the item. Vaults organize items and control who can access them. The value can be the vault name or vault UUID. Vault names with spaces are supported when quoted in YAML, for example "Production Secrets". | In the 1Password app sidebar, choose an existing vault or create one with the plus button next to the account name. In the CLI, run op vault list --account "<account>" --format json to find the vault name and UUID. |
item | The title of the 1Password item that stores the secret fields. | Open the vault, create or select an item such as Database Credentials, API Tokens, or Build Secrets, then use that item title in haloy.yaml. |
| Secret key | The field label inside the item. This is the third segment of from.secret, for example password in onepassword:production-db:password. | Edit the item in 1Password and add or rename fields so their labels match the keys you reference. Field labels are case-sensitive and should be unique within the item. |
For example, this reference:
onepassword:production-db:password
onepassword:production-db:password
means:
- Use the
production-dbsource undersecret_providers.onepassword - Read the 1Password item configured by that source
- Return the item field whose label is
password
Set Up a 1Password Item
- Open and unlock the 1Password app.
- Choose the account you want to use from the top of the sidebar if you have more than one account.
- Choose or create a vault for deployment secrets, for example
Production Secrets. - Create an item in that vault, for example
Database Credentials. A Login, Password, API Credential, Secure Note, or other item type can work as long as it has fields with labels Haloy can read. - Add fields for each value Haloy needs, such as
username,password,stripe-key, orsendgrid-key. - Save the item, then use the vault name or UUID, item title, and field labels in
haloy.yaml.
You can verify what the 1Password CLI can see before deploying:
op account list
op vault list --account "my.1password.com" --format json
op item get "Database Credentials" --vault "Production Secrets" --account "my.1password.com" --format json
op item get "Database Credentials" --vault "Production Secrets" --account "my.1password.com" --fields label=username,label=password
op account list
op vault list --account "my.1password.com" --format json
op item get "Database Credentials" --vault "Production Secrets" --account "my.1password.com" --format json
op item get "Database Credentials" --vault "Production Secrets" --account "my.1password.com" --fields label=username,label=password
If you only have one 1Password account, or you already set OP_ACCOUNT, you can omit account in haloy.yaml and leave off the --account flag in manual CLI checks.
Configuration
name: "my-app"
secret_providers:
onepassword:
production-db:
account: "my.1password.com"
vault: "Production Secrets"
item: "Database Credentials"
api-keys:
vault: "API Services"
item: "Third-party APIs"
env:
- name: "DB_PASSWORD"
from:
secret: "onepassword:production-db:password"
- name: "DB_USERNAME"
from:
secret: "onepassword:production-db:username"
- name: "STRIPE_API_KEY"
from:
secret: "onepassword:api-keys:stripe-key"
- name: "SENDGRID_API_KEY"
from:
secret: "onepassword:api-keys:sendgrid-key"
name: "my-app"
secret_providers:
onepassword:
production-db:
account: "my.1password.com"
vault: "Production Secrets"
item: "Database Credentials"
api-keys:
vault: "API Services"
item: "Third-party APIs"
env:
- name: "DB_PASSWORD"
from:
secret: "onepassword:production-db:password"
- name: "DB_USERNAME"
from:
secret: "onepassword:production-db:username"
- name: "STRIPE_API_KEY"
from:
secret: "onepassword:api-keys:stripe-key"
- name: "SENDGRID_API_KEY"
from:
secret: "onepassword:api-keys:sendgrid-key"
1Password Item Structure
Your 1Password item fields should match the keys you reference. For the configuration above:
- The
Database Credentialsitem in theProduction Secretsvault needsusernameandpasswordfields - The
Third-party APIsitem in theAPI Servicesvault needsstripe-keyandsendgrid-keyfields
SOPS Integration
Haloy can resolve secrets from SOPS-encrypted YAML, JSON, and dotenv files. The file is decrypted locally during config resolution, and the requested values are injected into the resolved target config.
Prerequisites
- SOPS CLI (
sops) installed and available in your PATH - Your SOPS file must be decryptable with the keys available on your machine (e.g. an age key in
~/.config/sops/age/keys.txt, or cloud KMS credentials configured)
Configuration
SOPS sources are defined under secret_providers.sops. File paths are resolved relative to your haloy.yaml.
name: "my-app"
secret_providers:
sops:
development:
file: "./secrets.dev.yaml"
deploy-tokens:
file: "./deploy.tokens.env"
format: "dotenv"
env:
- name: "CLIENT_ID"
from:
secret: "sops:development:client.id"
- name: "CLIENT_SECRET"
from:
secret: "sops:development:client.secret"
- name: "HALOY_API_TOKEN"
from:
secret: "sops:deploy-tokens:HALOY_API_TOKEN"
name: "my-app"
secret_providers:
sops:
development:
file: "./secrets.dev.yaml"
deploy-tokens:
file: "./deploy.tokens.env"
format: "dotenv"
env:
- name: "CLIENT_ID"
from:
secret: "sops:development:client.id"
- name: "CLIENT_SECRET"
from:
secret: "sops:development:client.secret"
- name: "HALOY_API_TOKEN"
from:
secret: "sops:deploy-tokens:HALOY_API_TOKEN"
Key Resolution
- YAML and JSON files support nested lookup with dot notation, for example
sops:development:client.id - Arrays use numeric segments, for example
sops:development:users.0.name - Dotenv files use direct keys, for example
sops:deploy-tokens:HALOY_API_TOKEN - If
formatis omitted, Haloy infers it from the file extension
Validation and Limitations
- Binary SOPS files are not supported for key-based lookup
- Structured keys containing
.are rejected to avoid ambiguous lookups - If
formatis omitted, the file extension must be enough to infer it - Validation, read, decrypt, and parse failures include source context to make troubleshooting easier
Registry Authentication with Secrets
Use 1Password to store registry credentials:
name: "my-app"
image:
repository: "ghcr.io/your-org/private-app"
tag: "latest"
registry:
username:
from:
secret: "onepassword:registry-credentials:username"
password:
from:
secret: "onepassword:registry-credentials:password"
secret_providers:
onepassword:
registry-credentials:
vault: "Infrastructure"
item: "GitHub Container Registry"
name: "my-app"
image:
repository: "ghcr.io/your-org/private-app"
tag: "latest"
registry:
username:
from:
secret: "onepassword:registry-credentials:username"
password:
from:
secret: "onepassword:registry-credentials:password"
secret_providers:
onepassword:
registry-credentials:
vault: "Infrastructure"
item: "GitHub Container Registry"
API Token with Secrets
Store your Haloy API token in a SOPS-encrypted dotenv file:
name: "my-app"
server: "api.haloy.dev"
api_token:
from:
secret: "sops:deploy-tokens:HALOY_API_TOKEN"
secret_providers:
sops:
deploy-tokens:
file: "./deploy.tokens.env"
format: "dotenv"
name: "my-app"
server: "api.haloy.dev"
api_token:
from:
secret: "sops:deploy-tokens:HALOY_API_TOKEN"
secret_providers:
sops:
deploy-tokens:
file: "./deploy.tokens.env"
format: "dotenv"
Build Arguments with Secrets
Pass secrets to Docker build as build arguments:
name: "my-app"
image:
repository: "my-app"
tag: "latest"
build_config:
context: "."
args:
- name: "NPM_TOKEN"
from:
secret: "onepassword:build-secrets:npm-token"
- name: "GITHUB_TOKEN"
from:
secret: "onepassword:build-secrets:github-token"
secret_providers:
onepassword:
build-secrets:
vault: "Development"
item: "Build Tokens"
name: "my-app"
image:
repository: "my-app"
tag: "latest"
build_config:
context: "."
args:
- name: "NPM_TOKEN"
from:
secret: "onepassword:build-secrets:npm-token"
- name: "GITHUB_TOKEN"
from:
secret: "onepassword:build-secrets:github-token"
secret_providers:
onepassword:
build-secrets:
vault: "Development"
item: "Build Tokens"
Multi-Target with Different Secrets
Use different SOPS files for different deployment targets:
name: "my-app"
secret_providers:
sops:
production:
file: "./secrets.production.yaml"
staging:
file: "./secrets.staging.yaml"
targets:
production:
server: "prod.myapp.com"
env:
- name: "DB_PASSWORD"
from:
secret: "sops:production:database.password"
staging:
server: "staging.myapp.com"
env:
- name: "DB_PASSWORD"
from:
secret: "sops:staging:database.password"
name: "my-app"
secret_providers:
sops:
production:
file: "./secrets.production.yaml"
staging:
file: "./secrets.staging.yaml"
targets:
production:
server: "prod.myapp.com"
env:
- name: "DB_PASSWORD"
from:
secret: "sops:production:database.password"
staging:
server: "staging.myapp.com"
env:
- name: "DB_PASSWORD"
from:
secret: "sops:staging:database.password"
Validation
Validate your configuration and verify secrets are resolved correctly:
# Validate config (doesn't show secret values)
haloy validate-config
# Show resolved config with secrets (use with caution!)
haloy validate-config --show-resolved-config
# Validate config (doesn't show secret values)
haloy validate-config
# Show resolved config with secrets (use with caution!)
haloy validate-config --show-resolved-config
Warning: --show-resolved-config displays all secrets in plain text. Only use in secure environments.
Troubleshooting
1Password CLI Not Authenticated
# Check authentication status
op account list
# Sign in if needed
op signin
# Check authentication status
op account list
# Sign in if needed
op signin
SOPS File Issues
- Confirm the
filepath is correct relative to your Haloy config file - Set
formatexplicitly if the extension is uncommon or ambiguous - Re-run
haloy validate-config --show-resolved-configonly in a secure environment to verify resolved keys
Secret Not Found
For 1Password, verify the item exists and contains the expected field:
# Verify the item exists
op item get "Database Credentials" --vault "Production"
# List item fields
op item get "Database Credentials" --vault "Production" --fields label
# Verify the item exists
op item get "Database Credentials" --vault "Production"
# List item fields
op item get "Database Credentials" --vault "Production" --fields label
Permission Denied
Ensure your 1Password account has access to the specified vault and item.
Next Steps
Stay updated on Haloy
Get notified about new docs, deployment patterns, and Haloy updates.