Skip to content

Last updated: 2026-02-11

HashiCorp Vault TLS/SSL Configuration Guide

This guide provides recommended TLS/SSL settings for HashiCorp Vault, a secrets management tool. Vault stores and controls access to sensitive data such as API keys, passwords, and certificates. TLS is critical for Vault because all secrets transit the network through its API.

Prerequisites

Certificate Setup

Vault needs a certificate that includes all hostnames and IP addresses clients will use to connect:

chmod 640 /etc/vault/ssl/privkey.pem
chown vault:vault /etc/vault/ssl/privkey.pem
chmod 644 /etc/vault/ssl/fullchain.pem

Listener Configuration

Vault's TLS settings are configured in the listener stanza of the Vault configuration file (/etc/vault.d/vault.hcl).

Basic TLS Setup

listener "tcp" {
    address     = "0.0.0.0:8200"
    tls_cert_file = "/etc/vault/ssl/fullchain.pem"
    tls_key_file  = "/etc/vault/ssl/privkey.pem"
}

Setting tls_disable = true disables TLS entirely. Never do this in production. Vault will refuse to start in production mode without TLS unless explicitly disabled, and all secrets would transit the network in plaintext.

Minimum TLS Version

listener "tcp" {
    address         = "0.0.0.0:8200"
    tls_cert_file   = "/etc/vault/ssl/fullchain.pem"
    tls_key_file    = "/etc/vault/ssl/privkey.pem"
    tls_min_version = "tls12"
}

Available values: tls10, tls11, tls12, tls13.

Cipher Suites

Vault uses Go's cipher suite names. Configure allowed cipher suites for TLS 1.2 (TLS 1.3 ciphers are not configurable in Go and are always secure):

listener "tcp" {
    address         = "0.0.0.0:8200"
    tls_cert_file   = "/etc/vault/ssl/fullchain.pem"
    tls_key_file    = "/etc/vault/ssl/privkey.pem"
    tls_min_version = "tls12"

    tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
}

Client Certificate Authentication

To require clients to present a TLS certificate (mutual TLS):

listener "tcp" {
    address                  = "0.0.0.0:8200"
    tls_cert_file            = "/etc/vault/ssl/fullchain.pem"
    tls_key_file             = "/etc/vault/ssl/privkey.pem"
    tls_min_version          = "tls12"
    tls_client_ca_file       = "/etc/vault/ssl/ca.pem"
    tls_require_and_verify_client_cert = true
}

Disable Client Cache Headers

For additional security, disable client-side caching of Vault responses:

listener "tcp" {
    address                            = "0.0.0.0:8200"
    tls_cert_file                      = "/etc/vault/ssl/fullchain.pem"
    tls_key_file                       = "/etc/vault/ssl/privkey.pem"
    tls_min_version                    = "tls12"
    tls_disable_client_certs           = false
    custom_response_headers {
        "default" = {
            "Strict-Transport-Security" = ["max-age=63072000; includeSubDomains; preload"]
        }
    }
}

Cluster TLS

In high-availability (HA) deployments, Vault nodes communicate with each other through the cluster port. Configure TLS for cluster communication:

listener "tcp" {
    address         = "0.0.0.0:8200"
    cluster_address = "0.0.0.0:8201"
    tls_cert_file   = "/etc/vault/ssl/fullchain.pem"
    tls_key_file    = "/etc/vault/ssl/privkey.pem"
    tls_min_version = "tls12"
}

Vault automatically uses TLS for cluster communication when the listener has TLS enabled. For separate cluster certificates:

cluster_addr = "https://vault-node1.example.com:8201"

Complete Configuration

storage "raft" {
    path = "/opt/vault/data"
    node_id = "vault-node1"
}

listener "tcp" {
    address         = "0.0.0.0:8200"
    cluster_address = "0.0.0.0:8201"
    tls_cert_file   = "/etc/vault/ssl/fullchain.pem"
    tls_key_file    = "/etc/vault/ssl/privkey.pem"
    tls_min_version = "tls12"

    tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"

    custom_response_headers {
        "default" = {
            "Strict-Transport-Security" = ["max-age=63072000; includeSubDomains; preload"]
        }
    }
}

api_addr     = "https://vault.example.com:8200"
cluster_addr = "https://vault-node1.example.com:8201"
ui           = true

Vault as a CA (PKI Secrets Engine)

Vault can also act as a certificate authority using the PKI secrets engine. This is useful for issuing TLS certificates to other services:

vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki

vault write pki/root/generate/internal \
    common_name="Internal CA" \
    ttl=87600h

vault write pki/config/urls \
    issuing_certificates="https://vault.example.com:8200/v1/pki/ca" \
    crl_distribution_points="https://vault.example.com:8200/v1/pki/crl"

Client Configuration

Environment Variables

export VAULT_ADDR="https://vault.example.com:8200"
export VAULT_CACERT="/path/to/ca.pem"

For mutual TLS:

export VAULT_CLIENT_CERT="/path/to/client-cert.pem"
export VAULT_CLIENT_KEY="/path/to/client-key.pem"

CLI Usage

vault status -ca-cert=/path/to/ca.pem -address=https://vault.example.com:8200

Skip Verification (Development Only)

export VAULT_SKIP_VERIFY=true

Never use VAULT_SKIP_VERIFY in production. This disables all certificate verification.

Verification

Start or restart Vault:

systemctl restart vault

Check Vault's status:

vault status

Test the TLS connection:

openssl s_client -connect vault.example.com:8200

Verify the certificate details:

curl --cacert /path/to/ca.pem https://vault.example.com:8200/v1/sys/health