# k8s/talos-iam/vault-values.yaml
# HashiCorp Vault — secrets backend for the homelab.
# Stores OIDC client secrets, TLS certs, and any other sensitive values.
# Accessed via the `talos` CLI (talos-cli/) which wraps `vault kv get/put`.
#
# Storage backend: MinIO S3 (minio.storage.svc.cluster.local) — no extra PVC.
# Auto-unseal: postStart hook reads unseal keys from vault-unseal-keys Secret
# (written by setup_vault.sh after operator init; operator must run that script
# once after first install to initialize and store the keys).

# ── Global ────────────────────────────────────────────────────────────────────
# tlsDisable: true — TLS terminated at the nginx ingress (vault.riotpiao.com)
# or at port-forward. In-cluster traffic to Vault is plain HTTP; this is acceptable
# because all clients are on the pod network (not crossing node boundaries).
global:
  enabled: true
  tlsDisable: true

# ── Agent Injector ────────────────────────────────────────────────────────────
# The injector mutates pods to sidecar Vault Agent for automatic secret injection.
# Not used here — secrets are fetched explicitly via the talos CLI.
# Enabling it would add a webhook that intercepts all pod creates cluster-wide,
# which is unnecessary overhead for a homelab with manual secret management.
injector:
  enabled: false

server:
  replicas: 1

  annotations:
    secret.reloader.stakater.com/reload: "vault-unseal-keys"

  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

  # ── Scheduling ─────────────────────────────────────────────────────────────
  # Tolerate cp-1 so Vault can run there if worker-1 is down.
  # Prefer worker-1 under normal conditions (keeps Vault off the same node as etcd).
  tolerations:
    - key: node-role.kubernetes.io/control-plane
      operator: Exists
      effect: NoSchedule

  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          preference:
            matchExpressions:
              - key: node-role.kubernetes.io/worker
                operator: Exists

  # ── Environment variables ───────────────────────────────────────────────────
  # extraEnvironmentVars: non-secret config passed directly.
  extraEnvironmentVars:
    VAULT_LOG_LEVEL: info

  # extraSecretEnvironmentVars: pulls values from K8s Secrets into env vars.
  # vault-minio-creds is created by the helmfile presync hook from MINIO_ROOT_USER/PASSWORD.
  # vault-unseal-keys is a placeholder created at first deploy; setup_vault.sh
  # overwrites it with real unseal keys after `vault operator init`.
  # Vault reads the keys from env on every pod start and the postStart hook unseals.
  extraSecretEnvironmentVars:
    - envName: AWS_ACCESS_KEY_ID
      secretName: vault-minio-creds
      secretKey: access_key
    - envName: AWS_SECRET_ACCESS_KEY
      secretName: vault-minio-creds
      secretKey: secret_key
    - envName: VAULT_UNSEAL_KEY_1
      secretName: vault-unseal-keys
      secretKey: key1
    - envName: VAULT_UNSEAL_KEY_2
      secretName: vault-unseal-keys
      secretKey: key2
    - envName: VAULT_UNSEAL_KEY_3
      secretName: vault-unseal-keys
      secretKey: key3

  # ── Auto-unseal ─────────────────────────────────────────────────────────────
  # Vault starts sealed after every pod restart and can't serve requests until
  # unsealed. postStart runs immediately after the container starts, sleeps 5s
  # to let the Vault process bind its port, then feeds the unseal keys one by one.
  # `|| true` prevents the hook from failing if a key was already used (idempotent).
  # 3-of-5 Shamir unseal is the default — we stored all 3 used keys in the Secret.
  postStart:
    - /bin/sh
    - -c
    - |
      sleep 5
      vault operator unseal "$VAULT_UNSEAL_KEY_1" || true
      vault operator unseal "$VAULT_UNSEAL_KEY_2" || true
      vault operator unseal "$VAULT_UNSEAL_KEY_3" || true

  # ── Vault config (HCL) ──────────────────────────────────────────────────────
  standalone:
    enabled: true
    config: |
      ui = false   # UI served via Vault's own HTTP; enabled below via ui: enabled: true

      listener "tcp" {
        address     = "0.0.0.0:8200"
        tls_disable = "true"

        # No auth in front of Vault's metrics endpoint — acceptable since all
        # Prometheus scrape traffic stays on the pod network (not exposed via ingress).
        telemetry {
          unauthenticated_metrics_access = "true"
        }
      }

      telemetry {
        prometheus_retention_time = "30s"
        disable_hostname          = true
      }

      # S3 storage backend pointing at the in-cluster MinIO service.
      # AWS_ env vars (from vault-minio-creds Secret) supply the credentials.
      # s3_force_path_style: MinIO uses path-style URLs (not virtual-hosted).
      # disable_ssl: MinIO in this cluster has no TLS.
      storage "s3" {
        endpoint            = "http://minio-cluster-hl.storage.svc.cluster.local:9000"
        bucket              = "vault"
        region              = "us-east-1"
        s3_force_path_style = "true"
        disable_ssl         = "true"
        max_parallel        = 128
      }

      # api_addr: the address other Vault nodes (or HA standbys) use to reach
      # this node. Single-node standalone, but Vault requires it to be set.
      api_addr = "http://vault.iam.svc.cluster.local:8200"
      cluster_addr = "https://vault-0.vault-internal.iam.svc.cluster.local:8201"

  # ── Service ─────────────────────────────────────────────────────────────────
  # NodePort 32171 — fallback for direct node access during bootstrap before
  # the ingress is up. Normal access is via nginx ingress (vault.riotpiao.com).
  service:
    type: NodePort
    port: 8200
    nodePort: 32171

  # ── Persistence ─────────────────────────────────────────────────────────────
  # No PVC — all Vault state (secrets, policies, tokens) is stored in MinIO S3.
  # This means Vault survives node loss as long as MinIO is healthy.
  dataStorage:
    enabled: false

  auditStorage:
    enabled: false

# ── UI ────────────────────────────────────────────────────────────────────────
# Vault's web UI is used for the OIDC browser login flow (Vault as an OIDC
# provider, if configured) and for manual operator inspection.
# Accessible at http://vault.riotpiao.com or via port-forward.
ui:
  enabled: true

# ── Metrics ───────────────────────────────────────────────────────────────────
# vault_core_unsealed is the availability signal (0 after a restart until the
# postStart hook above finishes unsealing). Pairs with the telemetry{} stanzas
# in standalone.config above, which actually turn the /v1/sys/metrics endpoint on.
serverTelemetry:
  serviceMonitor:
    enabled: true
    selectors: {}
    interval: 30s
    scrapeTimeout: 10s

