zoobzio January 23, 2026 Edit this page

HashiCorp Vault

The vault package provides a fig.SecretProvider backed by HashiCorp Vault's KV v2 secrets engine.

Installation

go get github.com/zoobzio/fig/vault

Quick Start

import (
    "log"

    "github.com/zoobzio/fig"
    "github.com/zoobzio/fig/vault"
)

type Config struct {
    DBPassword string `secret:"database/credentials:password"`
    APIKey     string `secret:"services/api:key"`
}

func main() {
    provider, err := vault.New()
    if err != nil {
        log.Fatal(err)
    }

    var cfg Config
    if err := fig.Load(&cfg, provider); err != nil {
        log.Fatal(err)
    }
}

Configuration

Environment Variables

The provider uses Vault's standard environment variables:

VariableDescriptionRequired
VAULT_ADDRVault server addressYes
VAULT_TOKENAuthentication tokenNo (can be empty for unauthenticated access)
VAULT_CACERTCA certificate path for TLSNo (uses system CAs)

Mount Path

By default, the provider uses the secret mount. Configure a different mount:

provider, err := vault.New(vault.WithMount("kv"))

Key Format

Keys follow the format path/to/secret:field:

// Vault path: secret/data/database/credentials
// Field: password
Password string `secret:"database/credentials:password"`

If no field is specified, value is used:

// Vault path: secret/data/api-key
// Field: value
APIKey string `secret:"api-key"`

Example Vault Data

vault kv put secret/database/credentials \
    username=admin \
    password=supersecret

vault kv put secret/api-key \
    value=sk_live_12345

Corresponding config:

type Config struct {
    DBUser     string `secret:"database/credentials:username"`
    DBPassword string `secret:"database/credentials:password"`
    APIKey     string `secret:"api-key"`  // uses "value" field
}

API Reference

New

func New(opts ...Option) (*Provider, error)

Creates a provider using environment variable configuration.

Returns: (*Provider, error) — error if VAULT_ADDR is not set.

Options

WithMount

func WithMount(mount string) Option

Sets the KV secrets engine mount path. Default: "secret".

WithAddress

func WithAddress(addr string) Option

Sets the Vault server address. Overrides VAULT_ADDR.

WithToken

func WithToken(token string) Option

Sets the Vault token. Overrides VAULT_TOKEN.

WithHTTPClient

func WithHTTPClient(client *http.Client) Option

Sets a custom HTTP client. Useful for testing or custom TLS configuration.

Authentication

The provider uses token-based authentication. Set the token via environment variable or option.

Environment Variable

export VAULT_ADDR="https://vault.example.com:8200"
export VAULT_TOKEN="hvs.your-token-here"

Token File

token, _ := os.ReadFile("/var/run/secrets/vault-token")
provider, _ := vault.New(vault.WithToken(string(token)))

Kubernetes

In Kubernetes, mount the token as a secret and read it at startup:

# Pod spec
volumes:
  - name: vault-token
    secret:
      secretName: vault-token
containers:
  - volumeMounts:
      - name: vault-token
        mountPath: /var/run/secrets/vault-token
        subPath: token
        readOnly: true
token, _ := os.ReadFile("/var/run/secrets/vault-token")
provider, _ := vault.New(vault.WithToken(string(token)))

For Vault Agent sidecar patterns, the agent writes a token file that your application reads.

Error Handling

The provider returns fig.ErrSecretNotFound when:

  • The secret path doesn't exist
  • The secret data is empty
  • The requested field doesn't exist

Other errors (network, authentication) are returned as-is and cause fig.Load to fail.

Next Steps