Quick Commands

# edit + deploy
git status
git add -A
git commit -m "docs: update"
git push

# rebuild static blog output (local)
cd site
npm ci --no-audit --no-fund
npm run build

# VPS: pull only
# (on server)
git pull --ff-only

Big picture (external gateway → test/prod proxy → apps)

[ Internet / external main gateway ]
                |
                v
        +--------------------+
        |  proxy.test/prod   |  (your NGINX/sidecar, keeps CA chain in sync from Vault)
        +--------------------+
           |            |
           v            v
     [App A]        [App B] ... (each app has its own agent)
         |               |
     (secrets)       (leaf certs/secrets)

Vault runs separately and is reachable as vault.test.local (test) and vault.prod.local (prod).
All agents (proxy + apps) talk to Vault over mTLS.


1) One-time base initialization (per environment)

Do this once per env (test / prod) before connecting proxies and apps.

  1. Offline Root CA erzeugen
    • Script: 01_make_offline_root_ca.sh --env test
    • Purpose: create the offline root CA key/cert.
  2. Create the Vault intermediate & sign it with the offline root
    • Script: 02_intermediate_in_vault_sign_with_root.sh --env test --config ./config/apps.yaml
    • Purpose: enable PKI mount in Vault, sign the intermediate, set CA URLs.
  3. Issue the Vault server certificate
    • Script:

      03_issue_vault_server_cert.sh --env test --config ./config/apps.yaml \
        --cn vault.test.local \
        --dns "vault.test.local,localhost,host.containers.internal" \
        --ips "127.0.0.1,::1,<public-ip>"
      
      
    • Important: --cn must match what clients verify (SNI).
      If your agents connect via IP, keep address=https://<public-ip>:22300 and set tls_server_name="vault.test.local" (hostname check against the cert).

  4. Switch Vault to HTTPS
    • Script: 04_enable_https_in_compose.sh --env test --port 22300 --cn vault.test.local
    • Result: Vault config uses tls_cert_file=.../fullchain.crt, tls_key_file=.../server.key.

(Optional) 5. Admin mTLS client cert

  • Script: 05_issue_admin_client_cert.sh --env test
  • For the vault CLI: set VAULT_CLIENT_CERT / VAULT_CLIENT_KEY.

2) Connect proxy test/prod to Vault (CA chain only)

For your proxy.test/prod NGINX instances so they keep the CA chain updated.

  • Script: setup-vault-agent-proxy-config2.sh --env test --config ./config/apps.yaml
  • Liefert:
    • mTLS-Client (agent.crt/key + ca.pem)
    • Agent config that renders only the chain (no leaf certs)
    • Post-hook scripts/vault-agent-post.sh can trigger nginx -s reload on updates (via label tls=true).

When?

  • Once during proxy setup.
  • After that, rotation runs automatically (agent renews auth and re-renders the chain).

3) Onboard a new app (secrets and/or leaf certs)

Two typical paths:

A) Container app with a sidecar agent (e.g. Nextcloud + DB password)

  1. Create AppRole + KV/policies
    • Script: bootstrap_secret_agent.sh --env test --config ./config/apps.yaml nctest
    • Result:
      • Policies (KV-read, optional PKI-Issue)
      • AppRole (RoleID/SecretID) → stored at /home/<appuser>/vault/creds/ (0400)
  2. Start the sidecar agent in Compose
    • In your docker-compose.yml (like vault-agent-nctest)
    • The agent reads role_id/secret_id, logs in, and renders secrets into /vault/secrets/... (tmpfs volume).

When?

  • Every time you set up a new container app.
  • SecretID rotation: either re-run bootstrap_secret_agent.sh with a new SecretID option or run vault write auth/approle/role/<role>/secret-id.

B) Host app (Unix service) needs a leaf certificate (mTLS)

  1. mTLS client for the agent
    • Script: setup-vault-agent-mtls-client-config2.sh --env test --config ./config/apps.yaml
    • Result: ~/vault/mtls/{agent.key,agent.crt,ca.crt}
  2. App agent that renders leaf certificates
    • Script: setup-vault-agent-app-config2.sh --env test --config ./config/apps.yaml
    • Result: a systemd user unit ~/.vault-agent-<app>/... that fetches and rotates the leaf (<app>.key + fullchain.pem).

When?

  • Once during onboarding.
  • Rotation runs automatically via the agent (renew + re-render).

4) Which scripts for which event?

Event Goal Scripts / action Order Key checks
Fresh Vault setup (per env) PKI + HTTPS ready 01 → 02 → 03 → 04 (→ 05 optional) 1→2→3→4 vault status, agent login works, CN/SAN correct
Connect proxy.test/prod CA chain stays current setup-vault-agent-proxy-config2.sh 1 Agent logs “rendered chain…”, NGINX reload ok
New container app Secrets + optional PKI bootstrap_secret_agent.sh → Compose sidecar 1→2 Agent logs “authentication successful”, secret files present
New host app (mTLS leaf) Leaf cert + rotation setup-vault-agent-mtls-client-config2.sh → setup-vault-agent-app-config2.sh 1→2 Leaf files exist, systemd unit active, app starts
SecretID rotation Refresh AppRole SecretID bootstrap_secret_agent.sh (new option) or vault write auth/approle/.../secret-id – New secret_id in app path, reload agent
Vault server cert expiring New server cert 03_issue_vault_server_cert.sh (same CN/SAN) → reload/restart Vault 1→(2) Clients connect, tls_server_name matches
Intermediate/root rotation New CA hierarchy 02 (new intermediate) + redeploy chains 1 Proxies/apps receive new chain (agents handle it)
DNS broken in container Fix connectivity In agent config: use address=https://<ip>:22300 and keep tls_server_name=vault.test.local – No “no such host” in logs
“no known role ID” Fix AppRole login Check /vault/creds/role_id and secret_id (0400, readable, correct) – Agent shows “authentication successful”
x509 CN mismatch Fix TLS hostname Re-issue cert or adjust tls_server_name (must match CN/SAN) – No “certificate is valid for … not …”

5) Which auth is used where?

  • Container sidecar (secrets): AppRole (RoleID/SecretID from bootstrap_secret_agent.sh).
  • Proxy agent (CA chain only): mTLS client cert (from setup-vault-agent-mtls-client-config2.sh).
  • Host app agent (leaf): mTLS client cert plus PKI role to issue a leaf cert.

Yes: you can replace AppRole with mTLS if you want client-cert distribution everywhere. In containers AppRole is often more convenient (no long-lived private key files). Mixed mode is fine.


6) Minimal commands (copy/paste, test environment)

Base setup (one-time):

./01_make_offline_root_ca.sh --env test
./02_intermediate_in_vault_sign_with_root.sh --env test --config ./config/apps.yaml
./03_issue_vault_server_cert.sh --env test --config ./config/apps.yaml \
  --cn vault.test.local \
  --dns "vault.test.local,localhost,host.containers.internal" \
  --ips "127.0.0.1,::1,<public-ip>"
./04_enable_https_in_compose.sh --env test --port 22300 --cn vault.test.local

Attach proxy test to Vault (CA chain only):

./setup-vault-agent-proxy-config2.sh --env test --config ./config/apps.yaml
# check: systemctl --user status vault-agent-<proxy>-ca.service (if a unit was created)

New container app (e.g. nctest):

./bootstrap_secret_agent.sh --env test --config ./config/apps.yaml nctest
# then start your docker/podman compose with the vault-agent-nctest sidecar

New host app (leaf cert):

./setup-vault-agent-mtls-client-config2.sh --env test --config ./config/apps.yaml
./setup-vault-agent-app-config2.sh --env test --config ./config/apps.yaml


7) Logging notes (short)

  • Container best practice: log to stdout/stderr; avoid writing log files under /var/log/... inside containers (permission problems). For MariaDB: disable file logging in .cnf or route to stderr; debug via podman logs.
  • Agents: everything is visible in the logs; key lines:
    • authentication successful
    • rendered "<template>" => "<destination>"
    • renewed auth token

If you want, I can turn this into a one-page checklist—but for now you have the key events and the matching scripts in one place.