In this hands-on tutorial, you’ll set up a single HashiCorp Vault node on an AWS EC2 instance using integrated Raft storage, AWS KMS auto-unseal, and a basic TCP listener. We assume you’ve already provisioned your EC2 instance (e.g., via Packer ) and dropped the Vault binary and example configs into /tmp.
Table of Contents
Install the Vault Binary
Create a Vault System User and Directories
Define the Systemd Service
Vault Configuration (vault.hcl)
Start and Verify Vault
References
1. Install the Vault Binary
SSH into your EC2 instance and place the Vault executable in your PATH.
# 1. Change to /tmp and verify files
cd /tmp && ls
# 2. Unzip and move the Vault binary
sudo unzip vault.zip
sudo mv vault /usr/local/bin/vault
# 3. Validate the installation
vault --version
Ensure that /usr/local/bin is in your $PATH so you can run vault without providing the full path.
2. Create a Vault System User and Directories
Run Vault under a non-root user and prepare the configuration and data directories.
# Create a system user for Vault
sudo useradd --system --home /var/lib/vault --shell /sbin/nologin vault
# Create config & data directories
sudo mkdir -p /etc/vault.d /opt/vault/data1
# Give ownership to the vault user
sudo chown -R vault:vault /etc/vault.d /opt/vault
Directory Purpose Owner /etc/vault.dVault configuration files vault:vault /opt/vault/data1Raft storage data vault:vault /var/lib/vaultVault home (no shell) vault:vault
3. Define the Systemd Service
Create the Systemd unit at /etc/systemd/system/vault.service:
[Unit]
Description = "HashiCorp Vault - Secrets Management"
Documentation =https://www.vaultproject.io/docs/
Requires =network-online.target
After =network-online.target
ConditionFileNotEmpty =/etc/vault.d/vault.hcl
StartLimitIntervalSec =60
StartLimitBurst =3
[Service]
User =vault
Group =vault
ProtectSystem =full
ProtectHome =read-only
PrivateTmp =yes
PrivateDevices =yes
SecureBits =keep-caps
AmbientCapabilities =CAP_IPC_LOCK
Capabilities =CAP_IPC_LOCK+ep
CapabilityBoundingSet =CAP_SYSLOG CAP_IPC_LOCK
NoNewPrivileges =yes
ExecStart =/usr/local/bin/vault server -- config =/etc/vault.d/vault.hcl
ExecReload =/bin/kill --signal HUP $MAINPID
KillMode =process
KillSignal =SIGINT
Restart =on-failure
RestartSec =5s
TimeoutStopSec =30s
[Install]
WantedBy =multi-user.target
Reload and enable the Vault service:
sudo systemctl daemon-reload
sudo systemctl enable vault
4. Vault Configuration (vault.hcl)
Below is an example of /etc/vault.d/vault.hcl using Raft storage, AWS KMS auto-unseal, and a non-TLS TCP listener for demonstration:
storage "raft" {
path = "/opt/vault/data1"
node_id = "node-a-us-east-1"
retry_join {
auto_join = [
"provider=aws" ,
"region=us-east-1" ,
"tag_key=vault" ,
"tag_value=us-east-1"
]
}
}
seal "awskms" {
region = "us-east-1"
kms_key_id = "arn:aws:kms:us-east-1:003674902126:key/8bc6b2ab-840a-4eef-8f2d-5616a3e67900"
}
listener "tcp" {
address = "0.0.0.0:8200"
cluster_address = "0.0.0.0:8201"
tls_disable = 1
}
api_addr = "http://10.0.1.37:8200"
cluster_addr = "http://10.0.1.37:8201"
cluster_name = "vault-prod-us-east-1"
ui = true
log_level = "INFO"
For a production setup, always enable TLS by adding tls_cert_file and tls_key_file under the listener block.
5. Start and Verify Vault
Launch Vault and confirm its status:
# Start the service
sudo systemctl start vault
# Check seal & HA status
vault status
Expected output:
Key Value
--- -----
Seal Type awskms
Initialized false
Sealed false
Total Shares 0
Version 1.7.1
Storage Type raft
HA Enabled true
View runtime logs to troubleshoot:
# Service status
sudo systemctl status vault
# Live logs
sudo journalctl -u vault -f
You should see AWS KMS auto-unseal messages if IAM and KMS permissions are correct:
2021-05-12T13:41:19.601Z [INFO] core: [DEBUG] discover-aws: Creating session...
2021-05-12T13:41:19.639Z [INFO] core: [DEBUG] discover-aws: Filter instances with vault=us-east-1
...
6. References