Skip to content
Learni
View all tutorials
DevOps

How to Configure HashiCorp Vault in Server Mode in 2026

Lire en français

Introduction

HashiCorp Vault is the go-to tool for centralized secret management in 2026. It stores, encrypts, and controls access to credentials like API keys, certificates, or database passwords. Unlike scattered .env files, Vault provides full auditing, automatic rotation, and high availability.

This intermediate tutorial walks you through installing Vault in server mode (not dev), with persistent file storage, a secure TCP listener, HCL policies, the KV v2 engine, and userpass authentication. By the end, you'll manage secrets via CLI and API. Ideal for DevOps or pre-prod environments. Works on Linux/Mac, scalable to Kubernetes. Estimated time: 20 minutes. Why it matters: 70% of breaches come from mismanaged secrets (Verizon DBIR 2025 report).

Prerequisites

  • Linux or macOS system (Vault not natively supported on Windows without WSL)
  • User with sudo rights for /opt/vault
  • 2 GB free RAM
  • Basic CLI and encryption knowledge (AES-256)
  • Optional: curl for API tests

Download and Install Vault

install-vault.sh
#!/bin/bash

# Download the latest stable version (1.17.x in 2026)
VAULT_VERSION=1.17.0
wget https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip

# Unzip and install
unzip vault_${VAULT_VERSION}_linux_amd64.zip
sudo mv vault /usr/local/bin/
sudo chmod +x /usr/local/bin/vault

# Verify the installation
vault --version

# Create data directories
sudo mkdir -p /opt/vault/data /opt/vault/logs /opt/vault/config
sudo chown -R $(whoami):$(whoami) /opt/vault

This script downloads Vault from official HashiCorp releases, installs it in the system PATH, and sets up directories for storage, logs, and config. Run chmod +x install-vault.sh && ./install-vault.sh. Avoid snapshot versions for production; always verify GPG signatures for integrity.

HCL Configuration File

/opt/vault/config/vault.hcl
storage "file" {
  path = "/opt/vault/data"
}

listener "tcp" {
  address     = "127.0.0.1:8200"
  tls_disable = false
  tls_cert_file = "/opt/vault/config/vault.crt"
  tls_key_file  = "/opt/vault/config/vault.key"
}

ui = true

log_level = "info"

# Auto-unseal with Transit (optional, manual here for simplicity)
# seal "transit" { ... }

disable_mlock = true

api_addr = "https://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"

This HCL config sets up persistent file storage, a local TCP listener with TLS enabled (generate certs afterward), the web UI, and API/cluster addresses. disable_mlock avoids errors on some OSes. Copy this file; TLS is critical to prevent MITM attacks.

Generate Self-Signed TLS Certificates

gen-certs.sh
#!/bin/bash

cd /opt/vault/config

# Generate private key and self-signed certificate (for local testing)
openssl req -newkey rsa:2048 -nodes -keyout vault.key -x509 -days 365 -out vault.crt -subj "/CN=vault.local"

# Secure permissions
chmod 600 vault.key
chmod 644 vault.crt

# Verify
openssl x509 -in vault.crt -text -noout | grep -A1 "Subject:"

Generate basic TLS certs for the listener (use Let's Encrypt in production). Run chmod +x gen-certs.sh && ./gen-certs.sh. This secures API/CLI communications from startup, avoiding 'connection refused' errors without HTTPS.

Start the Vault Server

start-vault.sh
#!/bin/bash

# Start Vault in foreground (use systemd in production)
nohup vault server -config=/opt/vault/config/vault.hcl > /opt/vault/logs/vault.log 2>&1 &

# Wait for startup
sleep 5

# Check status
curl -k https://127.0.0.1:8200/v1/sys/health | jq .

This script launches Vault with the HCL config in the background, redirects logs, and tests health via API (ignores certs with -k for testing). Status '200' means sealed but initialized false. In production, use a systemd service for auto-restart.

Initialize and Unseal Vault

init-unseal.sh
#!/bin/bash

export VAULT_ADDR='https://127.0.0.1:8200'

# Initialize (one time only)
vault operator init > /opt/vault/init-keys.txt

# Retrieve keys (example: replace with your real ones)
UNSEAL_KEY1=$(grep 'Unseal Key 1:' /opt/vault/init-keys.txt | cut -d' ' -f4)
UNSEAL_KEY2=$(grep 'Unseal Key 2:' /opt/vault/init-keys.txt | cut -d' ' -f4)
UNSEAL_KEY3=$(grep 'Unseal Key 3:' /opt/vault/init-keys.txt | cut -d' ' -f4)

# Unseal (3/5 Shamir's)
vault operator unseal $UNSEAL_KEY1
vault operator unseal $UNSEAL_KEY2
vault operator unseal $UNSEAL_KEY3

# Login as root (keep secret!)
ROOT_TOKEN=$(grep 'Initial Root Token:' /opt/vault/init-keys.txt | cut -d' ' -f4)
vault login $ROOT_TOKEN

# Status
vault status

Initialize Vault to generate the root token and unseal keys (Shamir's secret sharing). Replace the extracted keys with yours from init-keys.txt. After 3 unseal operations, Vault is active. Back up init-keys.txt offline; loss means data loss.

Enable KV v2 and Create a Policy

/tmp/policy-kv.hcl
path "secret/data/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

path "secret/metadata/*" {
  capabilities = ["list"]
}

This HCL policy grants read/write access to the KV v2 engine at 'secret/'. Run vault policy write kv-rw /tmp/policy-kv.hcl then vault write auth/userpass/users/testuser password=testpass policies=kv-rw to apply it. Separates data/metadata for fine-grained audits.

Store and Retrieve Secrets via CLI and API

manage-secret.sh
#!/bin/bash

export VAULT_ADDR='https://127.0.0.1:8200'

# Enable KV v2
vault secrets enable -path=secret kv-v2

# Create userpass auth
vault auth enable userpass
vault write auth/userpass/users/appuser password=AppPass123! policies=kv-rw

# Login and store secret
vault login -method=userpass username=appuser password=AppPass123!
vault kv put secret/myapp db_password=supersecret123 api_key=sk-abc123

# Retrieve
vault kv get secret/myapp

# Via API curl (with token)
TOKEN=$(vault print token)
curl -s -k -H "X-Vault-Token: $TOKEN" -X GET https://127.0.0.1:8200/v1/secret/data/myapp | jq .data.data

Enable KV v2 for automatic versioning, set up userpass auth, store a secret, and retrieve it via CLI/API. Tokens are ephemeral; use AppRole in production. KV v2 stores metadata separately for rotation without downtime.

Best Practices

  • Always enable audit logs: vault audit enable file file_path=/opt/vault/audit.log for traceability.
  • Use auto-unseal with AWS KMS or Transit to avoid manual unseal on boot.
  • Least-privilege policies: Granularize by path/capability, avoid root tokens.
  • High availability: Switch to Consul/Raft storage for clustering.
  • Rotate tokens and use TTL: vault token create -ttl=1h.

Common Errors to Avoid

  • Forgetting to unseal: Vault stays sealed, API returns 5xx; check vault status.
  • Misconfigured TLS: 'Certificate signed by unknown authority' errors; use -k for tests or trusted CA.
  • VAULT_ADDR without https: CLI refuses secure connections in 2026.
  • Lost init keys: No recovery; mandatory encrypted offline backup.

Next Steps

Master Vault in production with our Learni DevOps training. Resources: Official Vault Docs, Kubernetes Vault Injector Tutorial, advanced HCL community on GitHub.

How to Configure HashiCorp Vault Server Mode 2026 | Learni