Why?
Centralized secrets management vault to store API keys, passwords, certificates, and tokens in one secure location. This eleminates secret sprawl and provides encryption. This can also eliminate clear text passwords in automation and deployment scripts. Every operation is also logged so if a breach does happen you can trace it back to the source.
Installation
It is best practice to install the vault on a VM or dedicated machine which is isolated from any production environment or public network. You should have it be accessible through a VPN or zero trust network.
I will be installing it on an isolated Ubuntu server VM in my Proxmox datacenter.
My goal is to improve the security and manageability of my homelab: segmented, reproducible, and automation‑ready. Consul + Vault + Tailscale is a powerful trio for secure, zero‑trust‑style automation, and you can deploy them cleanly across a hybrid environment without overcomplicating the topology.
Below is a practical, homelab‑friendly guide that assumes:
- You have multiple nodes (Proxmox VMs, cloud VMs, containers, etc.)
- Everything is reachable over Tailscale for management
- You want Consul as the storage backend for Vault
- You want to use Ansible to automate secrets distribution and operations
Let’s build this in a way that mirrors real enterprise patterns but stays lightweight.
Architecture Overview
Vault
- Stores secrets, issues dynamic credentials, signs SSH certs, etc.
- Runs on 1–3 nodes (start with 1 for homelab)
- Uses Consul as its storage backend
Consul
- Provides service discovery + KV store
- Acts as Vault’s highly available storage backend
- Runs on 1–3 nodes (start with 1)
Tailscale
- Provides secure overlay network
- Allows Vault/Consul nodes to communicate without exposing ports publicly
- Lets Ansible reach Vault securely from anywhere
Network Layout (Recommended)
| Component | Network | Notes |
|---|---|---|
| Vault | Tailscale network (100.x.x.x) | Management + API access |
| Consul | Tailscale network | Cluster gossip + Vault backend |
| Ansible controller | Tailscale network | Uses Vault for secrets |
| Proxmox hosts | Tailscale network | Optional: use Vault for SSH certs |
You do not need to expose Vault or Consul to your LAN or WAN. Tailscale is your secure transport.
Step 1 — Prepare Your Nodes
On each VM/container that will run Vault or Consul:
sudo apt update && sudo apt install -y unzip curl gnupg lsb-release
Make sure nodes can ping each other via Tailscale:
ping 100.x.x.x
Step 2 — Install Consul
Add HashiCorp repo
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install consul
Create Consul config
/etc/consul.d/consul.hcl
datacenter = "homelab"
data_dir = "/opt/consul"
bind_addr = "100.tail.scale.ip"
client_addr = "0.0.0.0"
server = true
bootstrap_expect = 1
ui = true
retry_join = [100.tail.scale.ip]
IF you would like to enable TLS, add this stanzas:
ports {
https = 8501
http = -1
}
tls {
defaults {
verify_incoming = false
verify_outgoing = false
verify_server_hostname = false
}
https {
cert_file = “/path/to/fullchain.pem”
key_file = “/path/to/private.key”
}
}
Enable and start:
sudo systemctl enable consul
sudo systemctl start consul
Check status:
consul members
You should see the node bound to its Tailscale IP.
Step 3 — Install Vault
sudo apt install vault
Create Vault config
/etc/vault.d/vault.hcl
ui = true
cluster_addr = "http://100.tail.scale.ip":8201"
api_addr = "http://100.tail.scale.ip":8200"
storage "consul" {
# if tls is enable point to your fqdn
address = "127.0.0.1:8500"
path = "vault/"
}
listener "tcp" {
address = "100.tail.scale.ip:8200"
# Change this to -1 or comment out to enable tls
tls_disable = 1
}
If you are enabling TLS, add this stanza:
# HTTPS listener
listener “tcp” {
address = “vault.domain.com”
tls_cert_file = “/path/to/fullchain.pem”
tls_key_file = “/path/to/privkey.pem”
}
Start Vault:
sudo systemctl enable vault
sudo systemctl start vault
If you are running vault without TLS for the initial setup you will need to tell vault to listen on your tailscale network.
export VAULT_ADDR=”http://100.123.63.44:8200″
Step 4 — Initialize & Unseal Vault
Initialize:
vault operator init
Save:
- Unseal keys
- Root token
Unseal:
vault operator unseal
vault operator unseal
vault operator unseal
Enable KV v2 (Key/Value v2 engine)
vault secrets enable -path=secret kv-v2
Login:
vault login <root-token>
Step 5 — Verify Vault + Consul Integration
Check Vault storage:
vault status
Check Consul KV:
consul kv get vault/core/leader
If you see a leader entry, Vault is successfully using Consul.
Step 6 — Secure Vault Access Over Tailscale
Allow only Tailscale subnet to reach Vault
Vault is already bound to tailscale0, so it’s isolated.
If you want to restrict further:
sudo ufw allow in on tailscale0 to any port 8200
sudo ufw deny 8200
Optional Enhancements (Highly Recommended)
Enable Vault SSH CA
Issue short‑lived SSH certs for Proxmox, Linux VMs, and containers.
Enable auto‑unseal
Use:
- Tailscale SSH
- Transit auto‑unseal (if you run a second Vault)
- Cloud KMS (AWS/GCP/Azure)
Leave a Reply