What I Want From My VPS and Vault

This post was the starting point. The current implementation now lives in:

This whole project is my attempt to turn a simple VPS into a mini security platform: my own PKI, my own secret management, and my own little “production” environment that behaves like a serious setup, not just a random box on the internet.

In one sentence, the goal is:

Use a single VPS (plus a few logical components) to run my own PKI with an offline root, Vault as intermediate CA for test/prod, and mTLS all the way from proxies down to apps.

More concretely, I want:

  • My own PKI hierarchy

  • An offline root CA whose private key never leaves /root and is only used to sign intermediate CAs.

  • One intermediate CA per environment (at least test and prod), managed by Vault through environment-specific PKI mounts.

  • Reproducible server certificates for Vault, proxies and apps, issued from Vault instead of random ad-hoc OpenSSL commands.

  • A layered VPS architecture instead of “one big box”

  • A public entry proxy that terminates incoming traffic for environment-specific hostnames.

  • Separate internal proxies for each environment, each running as its own Unix user.

  • Dedicated Vault instances per environment (Vault test, Vault prod) as the trust and secrets backbone.

  • Applications (Nextcloud etc.) that talk to Vault through sidecar agents, not with static secrets hardcoded somewhere.

  • mTLS everywhere it matters

  • Vault API only over HTTPS with proper CN/SAN.

  • Proxies authenticate to Vault with client certificates, not just tokens.

  • Apps use Vault Agents with mTLS to fetch short-lived certs and secrets.

  • Strong isolation instead of “one user does everything”

  • Clear separation between test and prod (separate PKI, separate Vault mounts).

  • Separation between Vault servers, proxies, and apps, each with their own Unix user and key directory.

  • Each logical component has its own key space under /home/<user>/..., so a compromise in one place doesn’t automatically leak keys from another.

  • Something that feels closer to “real infra” than a toy lab

  • Short-lived admin credentials and certificates.

  • Proper paths for TLS material (offline root, intermediate CA, Vault TLS, proxy CA chains).

  • A setup that I can later mirror into Kubernetes concepts (sidecars, annotations, secret volumes) if I want to go that way.

This blog is where I’ll document how I try to get from the messy reality on my VPS to this clean model: what actually works, what breaks, and how I glue Vault, PKI, proxies and apps together without losing my mind.

What Is Actually Running Now

The original direction mostly held up, but the implementation became more concrete:

  • the operational repo is now vault-ops,
  • active scripts live behind stable wrappers in infra/,
  • versioned implementations live in infra/versions/,
  • environment and app metadata are driven from infra/config/apps.example.yaml,
  • test and prod are split by PKI mount, Vault address, Unix owner, TLS directory, proxy user, and app paths,
  • Vault Agents now handle both app leaf issuance and proxy CA-chain refresh.

What started here as a design idea is now much closer to an actual operating model:

  • offline root CA stays outside Vault,
  • Vault hosts per-environment intermediates,
  • the Vault API is HTTPS + mTLS,
  • every app or proxy has its own Unix user and Vault identity,
  • cert rotation and trust distribution are handled by repeatable scripts instead of ad-hoc shell history.

For the up-to-date implementation details, start with the repo README: