1. Vault Agent Overview
Vault Agent is a daemon client that runs alongside the application, automatically handling authentication, token renewal, and secret retrieval. Agent solves the "Secret Zero" problem — applications do not need to know how to authenticate with Vault.
Main function
Auto-auth — automatically authenticate and renew tokens
Template rendering — render secrets into config files
Caching — cache responses to reduce load on Vault server
API Proxy — application calls Agent instead of calling Vault directly
Architecture
┌─────────────────────────────────────────────────┐
│ Application Host │
│ │
│ ┌──────────┐ ┌───────────────┐ │
│ │ App │ Read files │ Vault Agent │ │
│ │ │ ◀──────────── │ │ │
│ │ │ (rendered │ Auto-auth │ │
│ │ │ templates) │ Templates │ │
│ │ │ │ Caching │ │
│ └──────────┘ └───────┬───────┘ │
│ │ │
└──────────────────────────────────────┼─────────┘
│
Vault API (HTTPS)
│
▼
┌──────────────┐
│ Vault Server │
└──────────────┘
2. Auto-auth
Auto-auth automatically authenticates with Vault and renews tokens. Supports all auth methods:
# vault-agent.hcl
vault {
address = "https://vault.company.com:8200"
tls_skip_verify = false
}
auto_auth {
method "kubernetes" {
mount_path = "auth/kubernetes"
config = {
role = "webapp"
}
}
# Lưu token vào file
sink "file" {
config = {
path = "/tmp/vault-token"
mode = 0640
}
}
# Lưu token vào file khác (wrapped)
sink "file" {
wrap_ttl = "5m"
config = {
path = "/tmp/vault-token-wrapped"
}
}
}
Auto-auth with AppRole
auto_auth {
method "approle" {
mount_path = "auth/approle"
config = {
role_id_file_path = "/etc/vault/role-id"
secret_id_file_path = "/etc/vault/secret-id"
remove_secret_id_file_after_reading = true
}
}
sink "file" {
config = {
path = "/tmp/vault-token"
}
}
}
Auto-auth with AWS IAM
auto_auth {
method "aws" {
mount_path = "auth/aws"
config = {
type = "iam"
role = "webapp"
header_value = "vault.company.com"
}
}
sink "file" {
config = {
path = "/tmp/vault-token"
}
}
}
3. Template Rendering
Vault Agent uses Consul Template syntax to render secrets into config files. Templates automatically re-render when secrets change.
Template Configuration
# vault-agent.hcl (tiếp)
template {
source = "/etc/vault/templates/app.conf.tpl"
destination = "/etc/app/app.conf"
perms = 0640
command = "systemctl reload app" # Chạy sau khi render
error_on_missing_key = true
}
template {
source = "/etc/vault/templates/db.env.tpl"
destination = "/etc/app/db.env"
perms = 0600
}
# Inline template (không cần file tpl)
template {
contents = "{{ with secret \"secret/data/app/config\" }}DB_HOST={{ .Data.data.host }}{{ end }}"
destination = "/etc/app/db-host"
}
Template Syntax
# /etc/vault/templates/app.conf.tpl
# KV v2 secret
{{ with secret "secret/data/production/db" }}
DB_HOST={{ .Data.data.host }}
DB_PORT={{ .Data.data.port }}
DB_NAME={{ .Data.data.database }}
DB_USER={{ .Data.data.username }}
DB_PASS={{ .Data.data.password }}
{{ end }}
# Dynamic database credentials
{{ with secret "database/creds/app-role" }}
DB_DYNAMIC_USER={{ .Data.username }}
DB_DYNAMIC_PASS={{ .Data.password }}
# Lease: {{ .LeaseID }} ({{ .LeaseDuration }}s)
{{ end }}
# PKI certificate
{{ with secret "pki/issue/app-cert" "common_name=app.company.com" "ttl=24h" }}
{{ .Data.certificate }}
{{ .Data.private_key }}
{{ end }}
# Conditional
{{ with secret "secret/data/production/feature-flags" }}
{{ if .Data.data.enable_cache }}
CACHE_ENABLED=true
CACHE_TTL={{ .Data.data.cache_ttl }}
{{ else }}
CACHE_ENABLED=false
{{ end }}
{{ end }}
Environment Variable Template
# /etc/vault/templates/db.env.tpl
{{ with secret "secret/data/production/db" -}}
export DB_HOST="{{ .Data.data.host }}"
export DB_PORT="{{ .Data.data.port }}"
export DB_USER="{{ .Data.data.username }}"
export DB_PASS="{{ .Data.data.password }}"
{{- end }}
4. Agent Caching
# Caching configuration
cache {
use_auto_auth_token = true
persist {
type = "kubernetes"
path = "/vault/agent-cache"
}
}
listener "tcp" {
address = "127.0.0.1:8100"
tls_disable = true
}
Applications calls Agent (localhost:8100) instead of calling the Vault server directly. Agent cache responses and automatically handle authentication.
5. Vault Proxy
Vault Proxy (Vault 1.14+) is a simplified version of Vault Agent, focusing on API proxying and caching without template rendering.
# vault-proxy.hcl
vault {
address = "https://vault.company.com:8200"
}
auto_auth {
method "kubernetes" {
mount_path = "auth/kubernetes"
config = {
role = "webapp"
}
}
}
api_proxy {
use_auto_auth_token = "force"
}
cache {
use_auto_auth_token = true
persist {
type = "kubernetes"
path = "/vault/proxy-cache"
}
}
listener "tcp" {
address = "127.0.0.1:8100"
tls_disable = true
}
Static Secret Caching
# Cache static secrets (KV v2)
cache {
use_auto_auth_token = true
persist {
type = "kubernetes"
path = "/vault/proxy-cache"
}
# Static secret caching (mới)
static_secret_token_wait = "5s"
}
6. Agent vs Proxy — When to use which?
| Feature | Vault Agent | Vault Proxy |
|---|---|---|
| Auto-auth | ✅ | ✅ |
| Template rendering | ✅ | ❌ |
| API Proxy | ✅ | ✅ |
| Caching | ✅ | ✅ |
| Process Supervisor | ✅ | ❌ |
| Footprint | Larger | Smaller |
| Use case | Need to render files | Just need proxy API |
Agent: When application reads secrets from files (config files, env files)
Proxy: When application calls Vault API directly, caching and auto-auth are needed
7. Deployment Patterns
Systemd Service
# /etc/systemd/system/vault-agent.service
[Unit]
Description=Vault Agent
Requires=network-online.target
After=network-online.target
[Service]
User=vault
Group=vault
ExecStart=/usr/bin/vault agent -config=/etc/vault/agent.hcl
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGTERM
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Docker Sidecar
# docker-compose.yml
services:
vault-agent:
image: hashicorp/vault:1.21
command: vault agent -config=/vault/config/agent.hcl
volumes:
- ./agent.hcl:/vault/config/agent.hcl:ro
- ./templates:/vault/templates:ro
- shared-secrets:/vault/secrets
restart: unless-stopped
webapp:
image: myapp:latest
volumes:
- shared-secrets:/etc/app/secrets:ro
depends_on:
- vault-agent
volumes:
shared-secrets:
Kubernetes Init Container
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
initContainers:
- name: vault-agent-init
image: hashicorp/vault:1.21
command: ["vault", "agent", "-config=/vault/config/agent.hcl", "-exit-after-auth"]
volumeMounts:
- name: vault-config
mountPath: /vault/config
- name: vault-secrets
mountPath: /vault/secrets
containers:
- name: webapp
image: myapp:latest
volumeMounts:
- name: vault-secrets
mountPath: /etc/app/secrets
readOnly: true
volumes:
- name: vault-config
configMap:
name: vault-agent-config
- name: vault-secrets
emptyDir:
medium: Memory
8. Summary
Vault Agent — full-featured daemon: auto-auth, templates, caching, API proxy
Vault Proxy — lightweight proxy: auto-auth, caching, API proxy (no templates)
Auto-auth — automatically authenticates and renews tokens, resolves Secret Zero
Templates — render secrets into config files, auto re-render when secrets change
Deployment patterns — systemd, Docker sidecar, K8s init/sidecar container
The next article will dive into Vault on Kubernetes — Helm chart, Vault Secrets Operator, CSI Provider and Agent Injector.