foundation/bootstrap/lib/context.ts
Andreas Niemann 185be52763 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>
2026-06-30 20:47:30 +02:00

61 lines
2.2 KiB
TypeScript

// lib/context.ts
//
// The shared deploy context every component receives (ADR-006). The bootstrap
// creates ONE docker.Provider (Docker-over-SSH to the foundation VM) and ONE
// foundation-net network; components then create their own container(s) against
// this shared provider/network, which gives the bootstrap full control over
// ordering and the phase GATES (e.g. Vault init between data-plane and Forgejo)
// that the vendored monolithic DockerDeployments cannot express.
//
// Validation override: the committed Pulumi.foundation.yaml carries placeholder
// VM coordinates (RFC-5737). For local/ephemeral validation against a dev Docker
// host, export FOUNDATION_DOCKER_HOST=ssh://user@host to point the provider there
// without editing committed config.
import * as pulumi from "@pulumi/pulumi";
import * as docker from "@pulumi/docker";
import { FoundationConfig, sshPrivateKeyPath } from "../config";
import { image } from "./versions";
/** Base context: shared provider + helpers, before the network exists. */
export interface BaseCtx {
cfg: FoundationConfig;
provider: docker.Provider;
sshKeyPath: string;
/** Resolve a pinned image by VERSIONS key suffix, e.g. ctx.image("POSTGRES"). */
image: (name: string) => string;
}
/** Full context handed to every component: base + the shared network. */
export interface DeployCtx extends BaseCtx {
network: docker.Network;
}
/** Signature every Wave-2+ component factory follows (ADR-006). */
export type ComponentFactory<T> = (ctx: DeployCtx) => T;
function providerHost(cfg: FoundationConfig): string {
return (
process.env.FOUNDATION_DOCKER_HOST ||
`ssh://${cfg.vm.user}@${cfg.vm.host}:${cfg.vm.sshPort}`
);
}
/**
* Build the shared Docker-over-SSH provider. SSH options mirror the vendored
* pulumi-docker wrapper (non-interactive host-key handling for automation).
*/
export function buildBaseContext(cfg: FoundationConfig): BaseCtx {
const sshKeyPath = sshPrivateKeyPath();
const provider = new docker.Provider("foundation-host", {
host: providerHost(cfg),
sshOpts: [
"-o",
"StrictHostKeyChecking=no",
"-o",
"UserKnownHostsFile=/dev/null",
"-i",
sshKeyPath,
],
});
return { cfg, provider, sshKeyPath, image };
}