Install HashiCorp Vault on Ubuntu
This guide explains how to install and configure HashiCorp Vault on an Ubuntu 24.04 LTS server. Vault centralizes the management of secrets (API keys, passwords, TLS certificates) securely.
Modern applications rely on secrets: API keys, database passwords, TLS certificates, encryption keys. Storing them in code or in plain text is a risk. Vault provides secure storage, dynamic credential generation, encryption as a service, and fine-grained access control.
Order a Server
To host your Vault instance, HostMyServers offers several suitable options:
- Performance VPS - Ideal for small teams
- NVMe VPS - Excellent value for money
- Eco Dedicated Servers - For moderate load deployments
- Performance Dedicated Servers - Maximum performance
Prerequisites
- SSH access as root or user with sudo
- Ubuntu 24.04 LTS 64-bit system
- A DNS A record pointing to the server IP (for Let's Encrypt)
- Ports 8200 (Vault HTTPS) and 80 (Certbot, temporary) accessible
Required Configuration
| Component | Minimum | Recommended |
|---|---|---|
| RAM | 512 MB | 1-2 GB |
| CPU | 1 core | 2 cores |
| Storage | 5 GB | 10 GB |
| Network | 100 Mbps | 1 Gbps |
Vault listens on port 8200 over HTTPS. The web UI and API use this port.
Connect to the Server
Connect via SSH to your Ubuntu server (default port 22, or custom port / PEM key depending on your setup):
ssh user@server_ip_address
System Update
Update the package list before installing Vault:
sudo apt update
sudo apt upgrade -y
Install Vault from HashiCorp Repository
HashiCorp provides an official APT repository to install the latest stable version of Vault.
Install required packages
sudo apt install -y gnupg curl lsb-release
Add HashiCorp GPG key
This key verifies that packages actually come from HashiCorp:
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
Add HashiCorp repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
Install Vault
sudo apt update
sudo apt install -y vault
Verify installation
vault --version
You should see a line like: Vault v1.20.x (...).
Enable autocompletion (optional)
vault -autocomplete-install
exec $SHELL
Firewall Configuration
Open the ports needed for Vault and for Let's Encrypt certificate issuance:
sudo ufw allow 8200/tcp
sudo ufw allow 80/tcp
sudo ufw reload
Port 80 is used temporarily by Certbot for HTTP validation. You can close it after obtaining certificates if you don't need it otherwise.
TLS Certificates with Let's Encrypt
For production, Vault must be served over HTTPS. We use Certbot to obtain free Let's Encrypt certificates.
Install Certbot
sudo apt install -y certbot
Obtain a certificate for your domain
Replace vault.yourdomain.com with your subdomain and your-email@example.com with your email:
sudo certbot certonly --standalone -d vault.yourdomain.com --non-interactive --agree-tos --email your-email@example.com
Certificates are created in /etc/letsencrypt/live/vault.yourdomain.com/.
Prepare TLS directory for Vault
The Vault package usually creates a system user vault. If needed, create it: sudo adduser --system --group vault. Then create the certificate directory and copy the files:
sudo mkdir -p /opt/vault/tls
sudo mkdir -p /opt/vault/data
sudo cp /etc/letsencrypt/live/vault.yourdomain.com/fullchain.pem /opt/vault/tls/cert.pem
sudo cp /etc/letsencrypt/live/vault.yourdomain.com/privkey.pem /opt/vault/tls/key.pem
sudo chown -R vault:vault /opt/vault
sudo chmod 600 /opt/vault/tls/cert.pem /opt/vault/tls/key.pem
Adapt vault.yourdomain.com to your actual domain in all commands and files below.
Certificate renewal script
So that Vault always uses up-to-date certificates after a Let's Encrypt renewal:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/vault.sh << 'EOF'
#!/bin/bash
cp /etc/letsencrypt/live/vault.yourdomain.com/fullchain.pem /opt/vault/tls/cert.pem
cp /etc/letsencrypt/live/vault.yourdomain.com/privkey.pem /opt/vault/tls/key.pem
chown -R vault:vault /opt/vault/tls
chmod 600 /opt/vault/tls/*
systemctl reload vault
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/vault.sh
Remember to replace vault.yourdomain.com in this script with your domain.
Close port 80 after obtaining certificates (optional)
If you no longer need port 80:
sudo ufw delete allow 80/tcp
sudo ufw reload
Configure Vault for Production
The configuration file controls storage, network listeners, and security settings.
Backup default configuration
sudo cp /etc/vault.d/vault.hcl /etc/vault.d/vault.hcl.backup
Create production configuration
Replace vault.yourdomain.com with your domain:
sudo tee /etc/vault.d/vault.hcl << 'EOF'
# Vault production configuration
ui = true
disable_mlock = true
storage "file" {
path = "/opt/vault/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/cert.pem"
tls_key_file = "/opt/vault/tls/key.pem"
tls_min_version = "tls12"
tls_cipher_suites = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
tls_require_and_verify_client_cert = "false"
tls_disable_client_certs = "true"
}
api_addr = "https://vault.yourdomain.com:8200"
cluster_addr = "https://vault.yourdomain.com:8201"
EOF
| Parameter | Description |
|---|---|
ui | Enable web UI |
storage "file" | Local storage backend (encrypted data) |
listener "tcp" | HTTPS listener on port 8200 |
api_addr | Public API URL (for clients) |
Start Vault
sudo systemctl enable vault
sudo systemctl restart vault
sudo systemctl status vault
Status should show active (running).
Environment Variables for CLI
So the Vault client knows where to connect:
echo 'export VAULT_ADDR="https://vault.yourdomain.com:8200"' >> ~/.bashrc
source ~/.bashrc
Verify:
echo $VAULT_ADDR
vault status
Before initialization you should see e.g.: Initialized: false, Sealed: true.
Initialize and Unseal
Vault starts in a sealed state: data is present but cannot be decrypted. Initialization creates unseal keys and the root token.
Understanding the process
When you initialize, Vault creates:
- Master key: encrypts all secrets
- Unseal keys: 5 keys from Shamir's algorithm; 3 of 5 are required to unseal Vault
- Root token: initial admin token
Unseal keys and root token are shown only once. Store them in separate, secure locations. Without them, data remains inaccessible.
Initialize Vault
vault operator init
Note the 5 unseal keys and the Initial Root Token. Do not share them or commit them to a repository.
Unseal Vault
You must provide 3 different keys (one per run):
vault operator unseal
Paste the first key when prompted. Then run twice more with two other keys:
vault operator unseal
vault operator unseal
When unsealing succeeds, vault status shows: Sealed: false.
Log in with root token
vault login
Enter the Initial Root Token when prompted.
Access the Web UI
- Open a browser and go to:
https://vault.yourdomain.com:8200 - Choose Token as the method
- Enter your root token and submit
You reach the Vault dashboard: status, secrets engines (KV, etc.) and access policies.
Vault only listens over HTTPS on port 8200. Use https:// in the URL and accept the certificate if needed (Let's Encrypt is recognized by browsers).
Useful Commands
| Command | Description |
|---|---|
vault status | Vault status (initialized, sealed, etc.) |
vault operator unseal | Provide an unseal key |
vault login | Log in with a token |
sudo systemctl status vault | systemd service status |
sudo systemctl restart vault | Restart Vault |
File Structure
| Path | Description |
|---|---|
/etc/vault.d/vault.hcl | Configuration file |
/opt/vault/data/ | Vault data (encrypted) |
/opt/vault/tls/ | TLS certificate and key |
Troubleshooting
Service won't start
- Check logs:
sudo journalctl -u vault.service -n 50 - Ensure paths in
vault.hclexist and uservaulthas rights on/opt/vault - Check syntax:
vault server -config=/etc/vault.d/vault.hcl(debug mode, then stop)
TLS or certificate error
- Ensure
cert.pemandkey.pemare in/opt/vault/tls/and readable by uservault - Test renewal:
sudo certbot renew --dry-run
Vault stays sealed after reboot
After each server reboot, Vault is sealed again. You must provide 3 keys again with vault operator unseal. To automate unsealing (less secure), you can use auto-unseal (e.g. with a cloud KMS); see Vault documentation.