feat(bootstrap): real olsitec.net config + DNS records (steps 1+2)

CONTRACT_001 amendments: hosts.git, vm.sshPort (default 22; VM uses 222),
cloudflare.zoneId. config.ts + lib/context.ts (provider host uses sshPort).
- components/dns.ts: forge/vault/s3/git.olsitec.net A -> VM (DNS-only, own CF
  provider from encrypted token). Deployed + verified authoritative = 204.168.234.72.
- Pulumi.foundation.yaml: real config (olsitec.net, vm 204.168.234.72:222,
  letsencrypt-dns01) + encrypted secrets (cloudflare token, offsite creds).
  Master passphrase: pass olsitec-foundation/PULUMI_CONFIG_PASSPHRASE.
- run.sh: reproducible deploy (passphrase + ssh key from pass/home).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Niemann 2026-06-30 20:47:30 +02:00
parent db47037bdc
commit 185be52763
10 changed files with 141 additions and 60 deletions

View file

@ -0,0 +1,41 @@
// components/dns.ts
//
// Public A records for the foundation's hostnames → the VM (CONTRACT_001 hosts).
// DNS-only (proxied:false): Git-over-SSH and Vault/RustFS need raw TCP, and ACME
// DNS-01 doesn't want the Cloudflare proxy in front. Records are scoped to the
// foundation's own names — they do not touch the zone's other (Pulumi-managed)
// records. The Cloudflare token is read from the passphrase-encrypted config
// secret (CONTRACT_001 §1.3), so no env var is needed at deploy time.
import * as pulumi from "@pulumi/pulumi";
import * as cloudflare from "@pulumi/cloudflare";
import { DeployCtx } from "../lib/context";
export function deployDns(ctx: DeployCtx): cloudflare.Record[] {
const { cfg } = ctx;
const apiToken = new pulumi.Config("foundation").requireSecret("cloudflareApiToken");
const provider = new cloudflare.Provider("foundation-cloudflare", { apiToken });
const ip = cfg.vm.host; // for the test/initial deploy, vm.host is the VM's public IPv4
const hosts: { key: string; fqdn: string }[] = [
{ key: "forge", fqdn: cfg.hosts.forge },
{ key: "vault", fqdn: cfg.hosts.vault },
{ key: "s3", fqdn: cfg.hosts.s3 },
{ key: "git", fqdn: cfg.hosts.git },
];
return hosts.map(
(h) =>
new cloudflare.Record(
`dns-${h.key}`,
{
zoneId: cfg.cloudflare.zoneId,
name: h.fqdn,
type: "A",
content: ip,
proxied: false,
ttl: 300,
},
{ provider },
),
);
}