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>: The provider name, currently onepassword or sops
  • <source>: The source key defined under secret_providers.<provider>
  • <key>: The field or nested key to resolve from that source

Examples:

  • onepassword:production-db:password
  • sops:development:client.id
  • sops: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

Configuration

name: "my-app" secret_providers: onepassword: production-db: account: "my-account" vault: "Production" 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:

  • username
  • password
  • stripe-key
  • sendgrid-key

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"

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 format is 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 format is 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"

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"

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"

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"

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

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

SOPS File Issues

  • Confirm the file path is correct relative to your Haloy config file
  • Set format explicitly if the extension is uncommon or ambiguous
  • Re-run haloy validate-config --show-resolved-config only 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

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.