Tailscale: Vault Contract

Level 2 (Topic) — Vault hostname evolution, MagicDNS convergence, cluster DNS architecture.

Concept

The Vault runtime has evolved through several networking models, each with different Tailscale integration. The current architecture converges on a native Tailscale-hostname contract consumed by cluster pods via Operator egress proxies.

Hostname Evolution

PhaseHostnameTailscale-owned?Status
Originallushycorp-vm.ts.tazlab.netYesSuperseded by lushycorp-vault
Custom aliaslushycorp-api.ts.tazlab.netNo (runtime-defined TLS)Debt (TD-020), retired from active architecture
Currentlushycorp-vault.magellanic-gondola.ts.netYes (MagicDNS)Operational

Current Runtime Identity (Phase 1 of 09 completed 2026-04-29)

  • Tailnet registration: lushycorp-vault (device name)
  • MagicDNS FQDN: lushycorp-vault.magellanic-gondola.ts.net
  • Vault API: https://lushycorp-vault.magellanic-gondola.ts.net:8200
  • Tailscale tags: tag:tazlab-vault, tag:vault-api
  • Tailnet IP: not stable across destroy/recreate (Phase 1 validated with 100.82.13.87)

Connectivity to Vault

Operator path

Inside TazPod, hostnet+TUN mode runs Tailscale in kernel mode; Vault is reachable by MagicDNS FQDN without any transport shim. --accept-dns=true is required so the Go runtime resolves MagicDNS names via 100.100.100.100.

Cluster pod path — ExternalName egress proxy (current, via 15-tailscale-operator-hardening)

The Tailscale Kubernetes Operator provides egress proxies for specific tailnet targets via ExternalName Services annotated with tailscale.com/tailnet-fqdn.

pod → CoreDNS (10.96.0.10)
  → forward ts.net → nameserver Service (ClusterIP 10.108.193.103)
    → nameserver pod (DNSConfig CRD, auto-registers ExternalName IPs)
      → egress proxy pod (connected to tailnet)
        → target tailnet node (lushycorp-vault)

Key points:

  • The ExternalName Service declares lushycorp-vault.magellanic-gondola.ts.net as the target
  • The Operator creates a dedicated egress proxy pod in the tailscale namespace
  • The DNSConfig nameserver auto-resolves the MagicDNS name to the proxy pod’s IP
  • User-managed CoreDNS (10.96.0.10) forwards ts.net to the nameserver via “Disable & Replace” (Talos native CoreDNS controller overwrites ConfigMap changes — cluster.coreDNS.disabled: true required)
  • This replaced the earlier relay DaemonSet approach (2026-05-08, decommissioned by 2026-05-09)

Custom alias path (legacy/debt)

The old alias lushycorp-api.ts.tazlab.net was defined in the Vault runtime TLS configuration, not in Tailscale DNS. It is not lifecycle-stable across destroy/recreate runs and requires bespoke DNS glue. Retired from active architecture.

Migration Direction

Phase 1 — Vault Runtime Convergence ✅ (completed 2026-04-29)

  • Tailscale machine name changed to lushycorp-vault
  • TLS cert SANs match lushycorp-vault.magellanic-gondola.ts.net
  • PKI fetch-back from VM to operator (~/secrets/lushycorp-vault/pki/)
  • Destroy/create validated end-to-end

Phase 2 — Cluster Consumption Convergence 🔄 (in progress)

  • 10-operator-dns-resolution — ✅ Operator deployed, CoreDNS forwarding active (2026-05-08)
  • 15-tailscale-operator-hardening — ✅ ExternalName egress + CoreDNS Disable&Replace (2026-05-09)
  • P2.1 — Create eso-reader Vault policy and scoped token
  • P2.2 — Deploy tazlab-secrets-vault ClusterSecretStore via Flux (GitOps)
  • P2.3 — ESO smoke test (read test secret, verify scoped token denies out-of-scope)

Phase 3 — Consumer Cutover (project 10-tazlab-k8s-vault-migration)

  • Migrate static secrets from Infisical to Vault in bounded waves
  • Retire tazlab-secrets (Infisical) ClusterSecretStore
  • Decommission Infisical (project 20-infisical-decommission)

See Also