foundation/documentation/sessions/SESSION_2026-06-30_001.md
Andreas Niemann 1d2462ddaf docs(session): SESSION_2026-06-30_001 — state + Wave 2 handoff
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:48:35 +02:00

3.8 KiB
Raw Blame History

Session 2026-06-30 #001 — Foundation bootstrap: contracts → live VM + DNS + offsite backup

What was done

  • T00 contracts CONTRACT_001004 (+ amendment for hosts.git, vm.sshPort, cloudflare.zoneId).
  • T01 preflight/ + VERSIONS (images carry :PIN_DIGEST placeholders — see gotchas).
  • T02 Bun-workspace + typed config.ts + vendored @olsitec/pulumi-{docker,vault}.
  • ADR-006 precursor: shared Docker-over-SSH provider + foundation-net (lib/context.ts, components/network.ts, phase-slotted index.ts). Composition = per-component factories, gates via dependsOn.
  • Phase-0 VM: vendored @olsitec/pulumi-hetzner; provision/ stack. Live: cx33 Helsinki, 204.168.234.72, Docker 29.6.1, SSH port 222, key ~/.ssh/foundation-test_ed25519, firewall 222/80/443/2222.
  • Offsite backup: offsite-backup/ stack — bucket olsitec-foundation + scoped service account on minio.wob.olsitec.de:19000 (home Synology). Verified scoped (cross-bucket denied).
  • Steps 1+2: real olsitec.net config + DNS forge/vault/s3/git.olsitec.net → 204.168.234.72 (verified authoritative; explicit A shadows the *.olsitec.net wildcard). foundation-net live on VM.

Current state

  • Repo: ~/work/olsitec-foundation/foundation. Latest commit 185be52. Working tree clean.
  • Master passphrase (the one external secret): pass olsitec-foundation/PULUMI_CONFIG_PASSPHRASE.
  • Deploy the foundation: cd bootstrap && ./run.sh up (sets passphrase + SSH_PRIVATE_KEY_PATH).
  • Stacks (all local file backends): bootstrap stack foundation (real passphrase); provision stack foundation-test + offsite-backup stack prod (throwaway passphrase dev-validation-throwaway).
  • Other creds: pass olsicloud4/{HCLOUD_TOKEN,CLOUDFLARE_MASTER_TOKEN}; MinIO admin via the wob-admin-external mc alias (accessKey admin, NOT pass MINIO_BACKUP_* which is a different instance).

Next steps (Wave 2 → the goal: git clone git@git.olsitec.net)

Validate each live on the VM via bootstrap/run.sh up (images still unpinned → FOUNDATION_ALLOW_UNPINNED=1 or pin digests per VERSIONS header). Each component is a factory components/<svc>.ts, wired into the index.ts phase slots (ADR-006).

  1. T03 postgres · T04 rustfs (+ buckets) — data plane.
  2. T05 vault — sealed container + init-capture (reuse olsitec-core/run.sh pattern → unseal keys to vaultCredentials:* encrypted config) + passphrase-gated unseal helper (ADR-004). The hard one.
  3. T06 credentials@pulumi/random → Vault (CONTRACT_002 paths).
  4. T07 Caddy — DNS-01 TLS; needs a Cloudflare-enabled Caddy image (build via xcaddy; standard caddy:2 lacks the DNS plugin). Token already in foundation:cloudflareApiToken.
  5. T08 Forgejo — app.ini ← Postgres/RustFS/Vault; first admin headless; org + repo so git clone git@git.olsitec.net:olsitec/... works (forgeSshPort 2222, published).
  6. T10 runner · T12 backup (RustFS → replicate to the offsite olsitec-foundation bucket; scoped creds already in foundation:backup.offsite*).

Risks / watchouts

  • Pulumi.foundation.yaml self-quotes scalars + encryptionsalt is now load-bearing (decrypts 3 committed secrets) — keep it committed; don't strip the salt anymore.
  • VM SSH is port 222; the eventual real VM would be 22 (vm.sshPort handles it).
  • VERSIONS images are :PIN_DIGEST + RustFS is latest — pin before treating as production.
  • Don't run pulumi up against the production olsicloud4-* stacks. The home MinIO .local name is LAN-only; the VM must use the public minio.wob.olsitec.de:19000.
  • Everything is destroyable: provision (VM), offsite-backup (bucket+creds) via pulumi destroy.

Operating mode for next session: HIGH-RISK / INFRA (remote VM, Docker, secrets).