APISIX Vault Integration#
APISIX integrates with HashiCorp Vault as a pluggable external secret manager, keeping sensitive values — TLS certificates, private keys, API keys, plugin credentials — out of etcd plain text. APISIX supports only Vault KV engine version V1 . Alongside Vault, APISIX also supports environment variables, AWS Secrets Manager, and GCP Secrets Manager through the same abstraction .
How It Works#
Secrets stored in Vault are referenced anywhere in plugin or SSL configurations via a URI of the form:
$secret://vault/<confid>/<secret_name>/<key>
vault— the manager name, maps toapisix/secret/vault.lua<confid>— the ID of the APISIX Secret resource (registered via Admin API)<secret_name>— path within Vault's KV store (relative to the configuredprefix)<key>— the field within the Vault secret JSON object
At runtime, fetch_by_uri() parses the URI via parse_secret_uri(), looks up the named Secret resource from etcd (/secrets/{manager}/{confid}), then calls the manager's get() function. The resolution is cached in an LRU cache with a 300-second TTL and 512-entry cap .
The URI prefix $secret:// is validated by check_secret_uri() . The schema enforces this pattern on SSL cert, key, certs, and keys fields as an alternative to direct PEM values .
Vault HTTP Client (apisix/secret/vault.lua)#
The full implementation lives in apisix/secret/vault.lua. Key behaviors:
- Schema — requires
uri,prefix, andtoken;namespaceis optional for Vault Enterprise / HCP Vault . - Request construction — the HTTP path is
{uri}/v1/{prefix}/{secret_name}, usingGETwith anX-Vault-Tokenheader . - Namespace header — if
namespaceis set,X-Vault-Namespaceis added per Vault Enterprise namespace rules . - Token from env — the token value can itself be an
$ENV://reference;env.fetch_by_uri()is attempted first . - Key splitting — the
keyargument must be in the formmain_key/sub_key. The function fetchesmain_keyfrom Vault and extractssub_keyfrom the response'sdataobject . - Default timeout — 5 seconds .
Registering a Vault Secret Resource#
Register a Vault connection via the Admin API (PUT /apisix/admin/secrets/vault/{id}) :
curl http://127.0.0.1:9180/apisix/admin/secrets/vault/1 \
-H "X-API-KEY: $admin_key" -X PUT -d '{
"uri": "https://127.0.0.1:8200",
"prefix": "apisix",
"token": "root"
}'
For standalone mode, add to apisix.yaml :
secrets:
- id: vault/1
prefix: apisix
token: root
uri: 127.0.0.1:8200
The Admin API resource handler is apisix/admin/secrets.lua. On PUT, it dynamically loads apisix.secret.vault, validates the request body against the Vault schema, and rejects unknown managers . POST is not supported .
Using Vault Secrets in SSL Objects#
cert and key fields on an SSL object accept either inline PEM or a $secret:// URI . During the TLS certificate phase, _M.set() detects secret URIs and fetches the actual PEM values before calling ngx_ssl.set_cert() / ngx_ssl.set_priv_key() .
Example — store a TLS cert in Vault then reference it from an SSL object:
# Write to Vault
vault kv put apisix/my-cert cert=@server.pem key=@server.key
# Create SSL object referencing Vault
curl http://127.0.0.1:9180/apisix/admin/ssls/1 \
-H "X-API-KEY: $admin_key" -X PUT -d '{
"sni": "example.com",
"cert": "$secret://vault/1/my-cert/cert",
"key": "$secret://vault/1/my-cert/key"
}'
(Pattern adapted from How to Use Vault to Manage Certificates in APISIX)
The same pattern applies to plugin fields — for example, key-auth's key field: "$secret://vault/1/jack/auth-key" .
Key Files#
| File | Role |
|---|---|
apisix/secret/vault.lua | Vault HTTP client, get() entry point |
apisix/secret.lua | Secret URI parser, fetch_by_uri(), LRU cache, init_worker() |
apisix/admin/secrets.lua | Admin API resource handler for /apisix/admin/secrets/{type}/{id} |
apisix/schema_def.lua | secret_uri_schema and its use in SSL cert/key fields |
docs/en/latest/terminology/secret.md | Canonical reference documentation |