HashiCorp Vault for Dummies: Setup your 1st Vault with TLS (WSL)

Intro

Vault by HashiCorp is a powerful tool for managing secrets, credentials, and encrypted data. In this guide, you’ll learn how to set up a local Vault server using Raft storage and TLS in a WSL (Windows Subsystem for Linux) environment. Whether you’re just starting with secrets management, prepping for the Vault Associate exam, or want to simulate a Vault cluster for testing, this guide will walk you through it step-by-step.

💡WSL Background and Assumptions

  • WSL1 lacks native systemd support, so boot-time services must be invoked via the wsl.conf command workaround.
  • The Vault server will run as a background process, initiated via a custom startup script.
  • Using custom static IPs, allows support of multiple Vault nodes (WSL instances) within the same machine.
  • 🔥More WSL Vault blogs coming soon (Transit unseal, VSO…)

Types of Vault Clusters

  • Single-node deployments
  • High Availability (HA) clusters:
    • Multi-Node with Integrated Storage
    • Multi-Node with External storage Backend

Lab Configuration

This setup covers the Vault Associate exam basics—check the official Docs to dive deeper.

Configuration Value Description
Node Type Single Node Indicates the Vault server is running in single node mode.
Storage Type Raft (Integrated) Indicates the Raft storage backend is being used.
storage path /opt/vault/data Path to store Vault data.
storage node_id node1 Unique ID for the Vault node in the Raft cluster.
cluster address (wsl) https://192.168.56.1:8201 Address for internal Vault communication.
api address (wsl) https://192.168.56.1:8200 Address for the Vault API.
ui true Enable the Vault web UI.
listener address (wsl) 192.168.56.1:8200 Address and port for the listener.
listener cluster_address (wsl) https://192.168.56.1:8201 Address for the listener’s cluster communication.
listener tls_cert_file /opt/vault/tls/vault-cert.pem Path to the TLS certificate file.
listener tls_key_file /opt/vault/tls/vault-key.pem Path to the TLS key file.
disable mlock true Disable memory locking (not recommended for prod).
audit logging enabled Enables audit logging to track all requests and responses.

⚠️Audit log Warning: Careful with Disk Usage

Vault will stop functioning if it can’t write to the audit log. This is by design, as it treats failure to audit as a potential security incident. You can always comment the audit section further down in the config step.

Solution(logrotate)

You set up logrotate for Vault Logs through a config file (/etc/logrotate.d/vault)

sudo vi /etc/logrotate.d/vault
#####
/var/log/vault.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    copytruncate
}

🔍 What this does:

  • Rotates the log daily
  • Keeps 7 compressed logs
  • Does nothing if the log file is missing or empty
  • copytruncate so Vault keeps writing without interruption

Getting Started

1️⃣ Install Vault

📥 Download & Install Vault Binary (Linux)

wget -O vault.zip https://releases.hashicorp.com/vault/1.18.3/vault_1.18.3_linux_amd64.zip
unzip vault*.zip && rm -f vault*.zip
chmod +x vault
sudo mv vault /usr/bin/vault

### ✅ Check Installation
$ vault --version
  Vault v1.18.3


📦 Install via ubuntu Package Managers

# Option 1 (simple)
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install vault
# Option 2 (signed keyring method)
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
UBUNTU_CODENAME=$(grep -oP '^VERSION_CODENAME=\K\w+' /etc/os-release)
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $UBUNTU_CODENAME main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vault

⚙️ Enable Autocomplete

vault -autocomplete-install
complete -C /usr/bin/vault vault


👤 Create Vault User

sudo groupadd --system vault
sudo useradd --system --home /srv/vault --shell /bin/false --gid vault vault

2️⃣ Configure Vault TLS (with Raft)

📁 Create TLS Directory

sudo mkdir -p /opt/vault/tls


🔐 Generate Self-Signed Certs (For Testing Only)

openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
  -subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=192.168.56.1:8200" \
  -keyout /opt/vault/tls/vault-key.pem \
  -out /opt/vault/tls/vault-cert.pem


🔒 Set Permissions

sudo chown -R vault:vault /opt/vault/
sudo chmod 640 /opt/vault/tls/vault-key.pem
sudo chmod 644 /opt/vault/tls/vault-cert.pem

➕ Add Certificate to Trusted Store

Ubuntu:

sudo cp /opt/vault/tls/vault-cert.pem /usr/local/share/ca-certificates/vault-cert.crt
sudo update-ca-certificates


(Optional) Set TLS Environment Variable

export VAULT_CACERT=/opt/vault/tls/vault-cert.pem

3️⃣ Vault Configuration File (TLS + Raft)

Create Config File

📁 Create Config Directory

sudo mkdir -p /etc/vault.d

📝 Create a file called /etc/vault.d/vault.hcl
Replace <192.168.56.1> with your own IP which allows for multi node cluster communication.

# Full configuration options can be found 
# Here https://developer.hashicorp.com/vault/docs/configuration

storage "raft" {
  path    = "/opt/vault/data"
  node_id = "node1"
}
# Cluster
cluster_addr  = "https://192.168.56.1:8201"
api_addr      = "https://192.168.56.1:8200"

# HTTPS listener
listener "tcp" {
  address     = "192.168.56.1:8200"
  cluster_address = "192.168.56.1:8201"
  tls_cert_file = "/opt/vault/tls/vault-cert.pem"
  tls_key_file  = "/opt/vault/tls/vault-key.pem"
}

#Other
ui            = true
disable_mlock = true
# log_level   = "warn"

# Audit logging -- feel free to disable ➡️ (comment)
audit {
  file_path = "/var/log/vault.log"
}

#telemetry {
#  prometheus_retention_time = "24h"
#}

# license_path = "/opt/vault/vault.hclic" # optional

✅ Validate & Set Permissions

vault operator diagnose -config=/etc/vault.d/vault.hcl
sudo chown -R vault:vault /etc/vault.d
sudo chmod 640 /etc/vault.d/vault.hcl

* Audit logging (if enabled)

# Audit logging
sudo touch /var/log/vault.log
sudo chgrp vault /var/log/vault.log
sudo chmod g+w /var/log/vault.log

4️⃣ Create Systemd Service for Vault (WSL2)

🧾 Create Service File /etc/systemd/system/vault.service

[Unit]
Description=HashiCorp Vault - A tool for managing secrets
Documentation=https://www.vaultproject.io/docs/
After=network-online.target
Wants=network-online.target

[Service]
User=vault
Group=vault
ExecStart=/usr/bin/vault server -config=/etc/vault.d/vault.hcl
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
LimitNOFILE=65536
ProtectSystem=full
ProtectHome=read-only
PrivateTmp=yes
NoNewPrivileges=yes

[Install]
WantedBy=multi-user.target

🔄 Reload and Start Vault

sudo systemctl daemon-reload
sudo systemctl enable vault
sudo systemctl start vault
sudo systemctl status vault

🌍 Set Vault Environment Variable

Replace <192.168.56.1> with your vault API endpoint (i.e WSL IP)

export VAULT_ADDR='https://192.168.56.1:8200'
echo "export VAULT_ADDR='https://192.168.56.1:8200'" >> ~/.bashrc

🔍 Check Vault Status

vault status
### check via API
curl -k https://192.168.56.1:8200/v1/sys/seal-status

5️⃣ Initialize & Unseal Vault

vault operator init -key-shares=3 -key-threshold=2 > key.txt
### output 
Unseal Key 1: xxxxxxxxxxxxxxxx
Unseal Key 2: xxxxxxxxxxxxxxxx
Unseal Key 3: xxxxxxxxxxxxxxxx
Initial Root Token: hvs.xxxxxxxxxxxxxxxx
Note: 🔒 Store your key.txt file securely. Without enough unseal keys, you’ll lose access to your Vault.

🔓 Unseal Vault

vault operator unseal
# Enter at least 2 of the 3 unseal keys
Unseal Key (will be hidden): **************************
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    3
Threshold       2
Unseal Progress 0/2
Unseal Nonce    n/a
Version         1.15.0
Storage Type    file
Cluster Name    vault-cluster-1234
Cluster ID      01234567-89ab-cdef-0123-456789abcdef
HA Enabled      false

✅ You’re All Set!

You’ve successfully installed and configured HashiCorp Vault with TLS and Raft storage on WSL. From here, you can:
Enable secrets engines, Create policies, Use Vault CLI and API to manage secrets securely. Start with the below CLI cheat sheet

🚀 Vault CLI cheat sheet
Command Description
vault status Check Vault’s current status.
vault version Display the Vault version.
vault login <method> Log in to Vault (e.g., using a token).
vault logout Log out from the current session.
vault operator init Initialize Vault for the first time.
vault operator unseal Unseal Vault using the required keys.
vault operator raft list-peers List Raft cluster members.
vault operator step-down Force the current leader to step down.
vault auth enable <method> Enable an auth method (e.g., approle).
vault auth list List enabled auth methods.
vault auth disable <path> Disable a specific auth method.
vault secrets enable <engine> Enable a secrets engine (e.g., kv).
vault secrets enable -path=<path> -version=2 kv Enable kv2.
vault secrets list List enabled secrets engines.
vault secrets disable <path> Disable a specific secrets engine.
vault policy write <name> <file> Create or update a policy from a file.
vault policy list List all policies.
vault policy delete <name> Delete a specific policy.
vault kv put <path> <key=value> Write a secret to the KV store.
vault kv get <path> Retrieve a secret.
vault kv delete <path> Delete a secret.
vault kv list <path> List secrets at a path.
vault token lookup <token> Look up details for a specific token.
vault token revoke <token> Revoke a specific token.
vault write <path> Generate dynamic secrets (e.g., DB creds).
vault read <path> Read dynamic secrets.
vault write transit/encrypt/<key> plaintext=<data> Encrypt data using a key.
vault write transit/decrypt/<key> ciphertext=<data> Decrypt ciphertext.
vault write transit/keys/<key-name>/rotate Rotate transit encryption key.
vault write transit/keys/<key-name>/config min_decryption_version=2 Set the minimum decryption version of the transit key.
vault read transit/keys/hcvop Read a transit key.
vault token create -period=24h -policy=auto-unseal-policy -wrap-ttl=120s -field=wrapping_token > wrapping-token.txt Create a new token.

II. WSL1 workaround for Vault Startup

1. Create the Vault Startup Script

Path: ~/.config/vault/start_service.sh

#!/bin/bash

# Replace this with your WSL node's static IP (e.g. 192.168.56.1)
export VAULT_ADDR='https://192.168.56.1:8200'

# Start Vault as a background process
vault server -config=/etc/vault.d/vault.hcl >> /var/log/vault.log 2>&1 &

chmod +x ~/.config/vault/start_service.sh

2. Configure wsl.conf to Run the Script on Launch

Path: /etc/wsl.conf [Replace <your_user> with your actual WSL username.]

[boot]
command="sudo bash /home/<your_user>/.config/vault/start_service.sh"

[user]
default=<your_user>
[network]
hostname = <Your_WSLhost>


🔽Conclusion

And that’s a wrap on setting up your first Vault with TLS on WSL! It might feel like a lot at first, but once you get through it, you’ll see it’s not as scary as it looks. This setup is solid enough to prep for the Vault Associate exam and get you hands-on with how Vault works in the real world.
Remember to secure your logs, and rotate them, because even local environments deserve production-grade habits.
Stay tuned for the next post in the Vault for Dummies series (Auto-unseal)! 🔐

🙋🏻‍♀️If you like this content please subscribe to our blog newsletter ❤️.

👋🏻Want to chat about your challenges?
We’d love to hear from you! 

Share this…

Don't miss a Bit!

Join countless others!
Sign up and get awesome cloud content straight to your inbox. 🚀

Start your Cloud journey with us today .