LINUXOR.SK ... open source notes ...

HashiCorp Vault - secrets management for a service platform

category: solutionz · date: 2024-01-01 · updated: 2026-10-02 · author: LALA

Between 2021 and 2024 I designed, built and ran the secrets management of a multi-tenant network service platform. Customers of that platform hand over credentials: cloud account keys, VPN pre-shared keys, private keys of certificates, routing passwords. Before Vault, those values travelled through the same data model as everything else. Afterwards a customer portal wrote them into Vault, an orchestration platform read them out when it configured a device, and nothing in between ever held them.

This Solution is the whole of that system: three self-managed Vault clusters on Integrated Storage, one of which exists only to unseal the other two, behind HAProxy and Keepalived, on hardened Oracle Linux 8, with audit logs and snapshots shipped to object storage.

noteBuilt on Vault 1.11 and run on Vault 1.14, the last release under the MPL licence. Every configuration file is shown as it ran and then checked against Vault 2.1.1, the current release on 2026-10-02. The system is anonymized: names, domains, addresses, people and third-party products are replaced, and every secret is a placeholder.

The system in one picture

mermaid
flowchart LR
  subgraph consumers["API clients"]
    portal["service-portal<br/>writes secrets"]
    orch["orchestrator<br/>reads secrets"]
  end
  subgraph prod["PROD"]
    plb["HAProxy + Keepalived<br/>prod-vault:443"]
    pv["prod-vault<br/>5 nodes, Raft"]
    plb --> pv
  end
  subgraph nonprod["NONPROD"]
    nlb["HAProxy + Keepalived<br/>nonprod-vault:443"]
    nv["nonprod-vault<br/>5 nodes, Raft"]
    nlb --> nv
  end
  subgraph common["COMMON"]
    clb["HAProxy + Keepalived<br/>common-vault:443"]
    cv["common-vault<br/>3 nodes, Raft"]
    clb --> cv
  end
  portal --> plb
  orch --> plb
  portal -. test and dev .-> nlb
  orch -. test and dev .-> nlb
  pv -- "Transit auto-unseal" --> clb
  nv -- "Transit auto-unseal" --> clb
  s3[("S3 object storage<br/>snapshots, audit logs")]
  pv --> s3
  nv --> s3
  cv --> s3

The fictional environment

Every article and every configuration file uses the same names and addresses.

EnvironmentPurposeVault nodesService networkLoad-balancer networkAdmin networkClient endpoint
PRODProduction secrets510.10.1.32/2810.10.2.8/2910.10.3.16/29prod-vault.example.net, 10.10.2.14
NONPRODTest and development secrets510.20.1.32/2810.20.2.8/2910.20.3.16/29nonprod-vault.example.net, 10.20.2.14
COMMONTransit auto-unseal for the other two310.30.1.32/2810.30.2.8/2910.30.3.16/29common-vault.example.net, 10.30.2.14

Hosts are named <env>-vault-node1 to node5, <env>-vault-lb1 and lb2, and <env>-vault-bastion1, all under example.net. Shared services (DNS, NTP, package repository, monitoring, log collector, object storage) sit in 10.40.0.0/16, administrators and API clients arrive from 10.41.0.0/16 and above, and addresses that were public in reality are taken from the documentation ranges of RFC 5737.

Articles

Read in this order; it is the order in which the system was built.

#ArticleWhat it covers
1Use cases and requirementsWho stores what, who reads it, and what the system had to guarantee
2Secret modelThe KV layout, and the move from KV v1 paths to KV v2 objects
3High-level designThree clusters, Raft, two availability zones, and what fails when
4Network design and firewall flowsThree networks per environment and every permitted flow
5Virtual machines and OS buildSizing, the cloud template, disks, and the base build of a server
6Linux hardeningCIS benchmark, kernel, SSH, SELinux, and the documented deviations
7TLS, DNS and certificatesNames, subject alternative names, issuance and renewal
8Load balancerHAProxy in TCP mode, Keepalived, and how the active node is found
9Vault server configurationInstalling Vault and reading vault.hcl block by block
10Initialization and Transit auto-unsealBringing up COMMON first, then the clusters it unseals
11Authentication and policiesAppRole, userpass, and a writer that cannot read
12Audit logging and log shippingTwo audit devices, rsyslog, logrotate, and logs to object storage
13Raft snapshots, backup and restoreThe snapshot agent, the rsync detour, and restore
14Monitoring and day-2 operationsZabbix, security alerts, renewals, and moving to Vault 2.x

Configuration files

Each file is a document of its own: what it is, where it lives, the file with its comments, what differs per node or environment, and what has changed since.

Vault

Vault policies

Load balancer

Linux build and hardening

Logging

Software

ComponentVersion as builtRole
HashiCorp Vault, Community edition1.11.1 at the first build, 1.14.x from 2023Secrets management
vault_raft_snapshot_agent0.3.1Periodic Raft snapshots
Oracle Linux8Operating system of every server
HAProxy1.8, from the distributionTCP load balancer in front of each cluster
Keepalivedfrom the distributionVirtual address between two load-balancer nodes
Zabbix agent6.0Monitoring
Ansible with the RHEL8-CIS role2.9Hardening

What I would do differently

The articles say this where it belongs. The short list:

← solutionz