
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 thewsl.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
🔓 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 ❤️.