HashiCorp Vault — Auto-Unseal

2 minute read

Auto-unseal replaces manual Shamir key-based unsealing with a cloud KMS or HSM, allowing Vault to automatically unseal on restart.


Why Auto-Unseal?

Manual Unseal (Shamir) Auto-Unseal (KMS)
Requires operators on restart Automatic — no human needed
Distribute key shares securely KMS manages master key
Slow restart recovery Fast recovery (seconds)
Risky key management Cloud-grade key protection

How Auto-Unseal Works

Init (one-time):
  Vault generates master key
  → Encrypts master key with KMS
  → Stores encrypted key in storage

Startup:
  Vault reads encrypted master key from storage
  → Sends to KMS for decryption
  → Master key unlocked
  → Vault unsealed automatically

AWS KMS Auto-Unseal

# vault.hcl

seal "awskms" {
  region     = "us-east-1"
  kms_key_id = "alias/vault-unseal-key"
  # Or use the full ARN:
  # kms_key_id = "arn:aws:kms:us-east-1:123456789:key/abc-123"
}

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

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = false
  tls_cert_file = "/etc/vault/tls/cert.pem"
  tls_key_file  = "/etc/vault/tls/key.pem"
}

AWS IAM Policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:DescribeKey"
      ],
      "Resource": "arn:aws:kms:us-east-1:123456789:key/abc-123"
    }
  ]
}

Azure Key Vault Auto-Unseal

seal "azurekeyvault" {
  tenant_id     = "your-tenant-id"
  vault_name    = "vault-unseal-kv"
  key_name      = "vault-unseal-key"
  # Uses managed identity or environment credentials
}

GCP Cloud KMS Auto-Unseal

seal "gcpckms" {
  project     = "my-project"
  region      = "global"
  key_ring    = "vault-keyring"
  crypto_key  = "vault-unseal-key"
}

Transit Auto-Unseal

Use another Vault cluster to unseal (Vault-to-Vault):

seal "transit" {
  address         = "https://vault-primary.internal:8200"
  token           = "hvs.unseal-token"
  disable_renewal = false

  key_name        = "vault-unseal"
  mount_path      = "transit/"
}

Migrate from Shamir to Auto-Unseal

# 1. Update vault.hcl to add the seal stanza
# 2. Restart Vault with -migrate flag
vault server -config=vault.hcl -migrate

# 3. Provide Shamir unseal keys when prompted
# 4. Vault re-encrypts the master key with KMS
# 5. Future restarts will auto-unseal

Migrate from Auto-Unseal to Shamir

# Add disabled seal block pointing to old KMS
seal "awskms" {
  region     = "us-east-1"
  kms_key_id = "alias/vault-unseal-key"
  disabled   = true
}
vault server -config=vault.hcl -migrate
# Vault will migrate back to Shamir keys

Verify Auto-Unseal

# Check seal type
vault status -format=json | jq '.seal_type'
# "awskms" (or "azurekeyvault", "gcpckms", "transit")

# After restart, Vault should be unsealed automatically
systemctl restart vault
sleep 5
vault status
# Sealed: false ✅

Quick Reference

Seal Type Config Block Provider
AWS KMS seal "awskms" AWS
Azure Key Vault seal "azurekeyvault" Azure
GCP Cloud KMS seal "gcpckms" GCP
Transit (Vault) seal "transit" Another Vault
PKCS#11 HSM seal "pkcs11" Hardware HSM

Next: Performance Replication