HashiCorp Vault: where my secrets actually live
Every homelab eventually hits the same awkward moment: you’re writing an automation script and you need a password. So you paste it directly into the script. Or into a .env file. Or — and we’ve all done this — into a comment in a config file you swore you’d clean up later.
That’s how secrets sprawl starts. A credential here, an API key there, a token buried in a shell script from eighteen months ago that you’re now scared to touch. It works, until it doesn’t — until you accidentally push that file to a public repo, or a service gets compromised, or you just can’t remember which of four passwords is the current one for the thing that broke at 11pm.
HashiCorp Vault is the answer to that problem. And it’s the solution running in this lab.
What Vault actually is
Vault is a secrets management server. In plain terms: it’s a locked box with a very good memory and a strict guest list.
You send secrets in — passwords, API keys, TLS certificates, tokens, whatever — and Vault stores them encrypted at rest. You retrieve them out with a token or credential that has exactly the permissions it needs, and nothing more. Every read and write is logged. If you want, secrets can be set to expire automatically. If you’re ambitious, Vault can even generate credentials on-demand and revoke them when a job finishes.
That last part — dynamic secrets — is where Vault gets genuinely impressive. Imagine your database never having long-lived credentials at all. Instead, a service asks Vault for access, Vault creates a fresh user with a short TTL, the service does its work, and when the TTL expires the credentials stop working. No rotation scripts. No “was it changed in January or March?” The compromise blast radius shrinks dramatically.
For a homelab, you may not need the full dynamism. But even the simpler use case — a single, audited, encrypted store for everything — is a massive upgrade over scattered .env files.
The problem it’s solving
Before Vault, secrets in a homelab typically live in one of a few places, none of them great:
- Hardcoded in scripts. Works until the script ends up somewhere public.
- A password manager. Good for humans, awkward for automation.
- Environment variables. Better, but still scattered across hosts and easy to leak in logs.
- Ansible vault / SOPS encrypted files. A real improvement, but per-file encryption isn’t the same as a unified API with audit trails and access policies.
The underlying problem isn’t just where credentials sit — it’s that there’s no single answer to “who has access to what, and when did they last use it?” Vault makes that question answerable.
What the commercial world uses
If you’ve worked in enterprise infrastructure, you’ve seen this problem solved at scale. The dominant commercial options are:
AWS Secrets Manager (and its cousin Parameter Store) handle the same use case inside the AWS ecosystem. Tight IAM integration, automatic rotation for supported services, pay-per-secret pricing. If your workload is already in AWS, it’s a natural fit. Outside AWS, it gets awkward fast.
Azure Key Vault is the equivalent for the Microsoft stack — and if you’re managing Azure AD credentials or App Service configs, it’s often the path of least resistance.
CyberArk and Delinea (formerly Thycotic/CyberArc Secret Server) are the heavy-weight enterprise options. CyberArk in particular is the gold standard for Privileged Access Management: session recording, break-glass workflows, certificate lifecycle, the works. It’s also priced for organizations, not individuals. Delinea’s Secret Server occupies similar territory with a somewhat more accessible mid-market posture.
⚠️ Unverified: Specific pricing for CyberArk, Delinea, or AWS Secrets Manager — these are general market characterizations from domain knowledge; verify current pricing against vendor sites.
The pattern across all of them is the same: centralize secrets, enforce policy, audit everything. Vault does all of that, open-source, self-hosted.
The self-hosted landscape
If you want to own your secrets infrastructure, a few options are worth knowing:
HashiCorp Vault is the most capable and the most complex. Open-source Community Edition covers everything a homelab or small organization needs. The Enterprise edition adds things like DR replication, HSM support, and namespace isolation — almost certainly out of scope for home use.
Infisical is a newer, more developer-friendly alternative. It has a polished UI, SDKs for common languages, and a SaaS option if you want managed hosting. If Vault’s operational complexity is intimidating, Infisical is worth a look.
SOPS (Secrets OPerationS, from Mozilla) takes a different approach: it encrypts secret files in place, using age, PGP, or cloud KMS keys. There’s no server to run — you encrypt a YAML file and commit it to git. Simpler, but no API, no dynamic secrets, no audit trail beyond git history. Great for small setups or as a complement to Vault for IaC files.
Bitwarden / Vaultwarden is primarily a password manager, but it has a “Secrets Manager” product for API keys and tokens. If you’re already running Vaultwarden (the open-source Bitwarden server) for passwords, it’s worth checking whether it covers your automation needs before reaching for Vault.
The honest answer: if you’re just starting out, SOPS or Vaultwarden might be all you need. Vault earns its complexity when you have multiple services, multiple users, and automation that needs to pull credentials programmatically without human involvement.
How it fits this lab
This lab runs Vault as a containerized service on a dedicated VM. The deployment is lightweight — a couple of CPU cores and a few gigabytes of RAM is plenty. Vault’s storage backend is file-based, which is simpler than a database and sufficient for the load a homelab puts on it.
The key-value store holds credentials for the services and automation that need them: firewall API keys, backup credentials, authentication tokens for various services, Terraform provider credentials. Anything that used to live in a .env file or a hardcoded script now lives in Vault, and scripts retrieve it at runtime via the Vault CLI or API.
The unsealing problem
One operational detail Vault is honest about: when Vault starts (or restarts after a reboot), it starts in a sealed state. Sealed means it has the encrypted data but refuses to serve any of it — it needs a quorum of unseal keys to re-derive the master key before it’ll open up.
By default, Vault uses Shamir’s Secret Sharing for this: you generate N keys at initialization and need M of them (where M < N) to unseal. It’s designed to prevent a single person or single piece of stolen data from unlocking everything. But it also means every reboot requires manual intervention — and if you’re not home when something restarts, every service that depends on Vault goes down with it.
The solution is auto-unseal, and Vault supports several mechanisms: cloud KMS (AWS KMS, Azure Key Vault, GCP Cloud KMS), an HSM, or Vault’s own Transit secrets engine running on a separate instance.
This lab uses the Transit engine approach: a second, minimal Vault instance is configured as the seal provider. When the main Vault starts, it reaches out to the secondary, authenticates, and uses the Transit engine to decrypt its own master key — no human involvement. The secondary instance runs on hardware that starts before the main VM, so the timing works out reliably.
The elegance of this approach is that it requires no cloud dependency and no hardware security module. The tradeoff is that the secondary instance introduces its own availability concern: if it’s down when the main Vault tries to start, auto-unseal fails. The secondary therefore lives on the most reliable, always-first-up host available. For most homelab setups, that means bare-metal NAS hardware or a low-power always-on device — something that boots independently of your hypervisor.
⚠️ Unverified: Specific behavior of HSM-based auto-unseal vs Transit auto-unseal in Vault Community Edition — characterizations are from general Vault documentation and experience; verify against current HashiCorp docs.
This two-tier approach is a pattern worth knowing: it solves a genuinely annoying problem (manual unsealing) without paying for cloud KMS or enterprise hardware, and it’s well within reach of anyone comfortable running a couple of Docker containers.
TLS and access
Vault runs internally over plain HTTP, with TLS terminated at a reverse proxy that handles certificates. External access goes through HTTPS. Cloudflare tunnels provide remote access without exposing Vault’s port directly to the internet — an important detail, since Vault’s API being reachable from the open internet would be a significant exposure even with token auth in place.
Authentication in this lab uses token-based auth for automation and the root token for administrative tasks (stored in a password manager, used as infrequently as possible). A healthier long-term posture — which is on the roadmap — is AppRole auth for services that pull credentials programmatically, so each service has scoped credentials rather than sharing a single token.
Should you bother?
Here’s the honest version:
Yes, if:
- You’re running automation that needs credentials — Ansible, Terraform, n8n, Python scripts, anything that touches an API.
- You have more than a handful of services and the “where did I put that API key?” question is getting old.
- You want audit trails: who (or what) accessed which secret, and when.
- You’re learning infrastructure skills that transfer directly to enterprise environments where CyberArk or Secrets Manager will appear.
Not yet, if:
- You have two or three services and manage everything manually.
- You’re still getting the basics running — DNS, reverse proxy, a VM or two. Vault is a dependency that other things depend on, not a starting point.
- The operational overhead (backups, unsealing, token rotation) sounds like more friction than the problem it solves.
There’s no shame in using a good password manager and SOPS for a simple setup. The right tool is the one you’ll actually use and maintain.
The thing it changes
The shift Vault creates is subtle but real. When credentials live in a centralized, API-accessible store, automation becomes simpler — scripts don’t need embedded secrets, they just need permission to ask. When something breaks, the audit log tells you what was accessed. When you rotate a credential, you update it in one place and everything that uses it pulls the new value.
It also changes how you think about service design. Once you’ve used dynamic credentials — even just for one service — you start to see the security improvement in everything else and reach for it more readily.
For Sun, it’s been running since early 2026, and the main feedback is that the initial setup investment pays off quickly. The “where is that password” question has essentially gone away, replaced by vault kv get and scripts that handle the rest.
That’s not magic. It’s just good infrastructure hygiene, applied consistently.
Next up: how Authentik handles SSO across the whole lab — one login for everything, no vendor lock-in.
Comments
No comments yet — be the first.