Vault Agent can dynamically generate configuration files for other applications by rendering Go-style templates.

Let’s see it in action. Imagine you have an application that needs a database password, and you want to fetch that password from Vault and inject it into its configuration file without manual intervention.

Here’s a sample application configuration file, app.conf.tpl:

[database]
host = db.example.com
port = 5432
username = app_user

password = {{ .secret.db_password }}

And here’s how Vault Agent can render this template. First, we need to configure Vault Agent to:

  1. Authenticate to Vault.
  2. Lookup a secret.
  3. Render a template using that secret.

A minimal vault-agent-config.hcl might look like this:

pid_file = "/tmp/vault-agent.pid"
log_level = "info"

auto_auth {
  method "kubernetes" {
    config = {
      role = "my-app-role"
    }
  }
}

template {
  source = "app.conf.tpl"
  destination = "/etc/app/app.conf"
  perms = 0644
}

secret {
  # This tells Vault Agent to fetch the secret at path "secret/data/myapp/db"
  # and make it available in the template context as ".secret"
  path = "secret/data/myapp/db"
  change_notify {
    # This command will be run every time the secret is updated and re-rendered.
    # For simplicity, we'll just echo, but in reality, you might restart a service.
    command = "echo 'Secret updated, restarting app...'"
  }
}

When Vault Agent starts, it authenticates (using Kubernetes auth in this example), fetches the secret from secret/data/myapp/db, and then renders app.conf.tpl. If the secret at secret/data/myapp/db contains a key named db_password, its value will be substituted into the password field in /etc/app/app.conf.

The rendered /etc/app/app.conf would look like:

[database]
host = db.example.com
port = 5432
username = app_user
password = your_super_secret_password_from_vault

Vault Agent’s template rendering is powered by Go’s text/template and html/template packages. This means you have access to all standard Go template functions, plus some convenient additions for secrets. The {{ .secret }} variable in the template refers to the entire secret data fetched from the specified Vault path. If your secret is JSON, like:

{
  "db_password": "your_super_secret_password_from_vault",
  "api_key": "another_secret_value"
}

You can access individual fields using dot notation: {{ .secret.db_password }} or {{ .secret.api_key }}. You can also iterate over map keys using range and access nested structures.

The real power comes from the change_notify block. When Vault Agent detects a change in the secret it’s watching, it re-renders the template. The change_notify command is then executed. This allows for automatic configuration updates and application reloads without manual intervention. You could configure this to run a command that gracefully restarts your application, ensuring it picks up the new credentials or configuration.

A common misconception is that you can only inject simple string values. However, Vault Agent can render entire configuration files, including complex JSON, YAML, or custom formats. You can even have multiple template blocks, each rendering a different file from the same or different secrets. This makes Vault Agent a versatile tool for managing dynamic configurations across your infrastructure.

The next step is exploring how to manage multiple secrets and their rendering into complex application configurations using Vault Agent’s template and secret stanzas.

Want structured learning?

Take the full Vault course →