// provision/index.ts — Phase 0: provision the throwaway foundation TEST VM. // // Isolated stack (platformName "foundation-test" → no name collision with the // production olsicloud4-* resources). Uses the vendored @olsitec/pulumi-hetzner // HetznerDeployment for one cx22, adds a firewall, and installs Docker via the // module's cloud-init lateCommands. // // GOTCHA (VENDORED.md): the module's cloud-init moves SSH to PORT 222 and creates // root + andiolsi users. The firewall + the Docker-over-SSH provider use :222. // // Token comes from ENV (export HCLOUD_TOKEN="$(pass olsicloud4/HCLOUD_TOKEN)"), // never committed. import * as pulumi from "@pulumi/pulumi"; import * as hcloud from "@pulumi/hcloud"; import { HetznerDeployment } from "@olsitec/pulumi-hetzner"; import * as os from "os"; const token = process.env.HCLOUD_TOKEN; if (!token) { throw new Error( 'HCLOUD_TOKEN env required: export HCLOUD_TOKEN="$(pass olsicloud4/HCLOUD_TOKEN)"', ); } const platformName = "foundation-test"; const datacenter = "nbg1-dc3"; // matches existing cx22 servers (known-good) // Dedicated throwaway key: the operator's id_rsa pubkey is already registered in // the project (olsicloud4-ssh-key) and Hetzner rejects duplicate key CONTENT, so // the test VM uses its own ed25519 key. SSH/Docker-over-SSH use the matching // private key (~/.ssh/foundation-test_ed25519) on port 222. const sshKeyPath = process.env.FOUNDATION_TEST_SSH_PUBKEY || `${os.homedir()}/.ssh/foundation-test_ed25519.pub`; // Install Docker CE on Debian 12 (runs in cloud-init runcmd, after base packages). const dockerInstall = [ "install -m 0755 -d /etc/apt/keyrings", "curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc", "chmod a+r /etc/apt/keyrings/docker.asc", 'echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable" > /etc/apt/sources.list.d/docker.list', "apt-get update", "apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin", "systemctl enable --now docker", "touch /root/.provision-done", ]; const dep = new HetznerDeployment(platformName, { platformName, hcloudToken: token, sshKeyPath, datacenter, servers: [ { name: "foundation-test", hostname: "foundation-test", type: "cx23", // current-gen Intel shared (cx22 is legacy/unavailable for new servers); 2c/4G image: "debian-12", labels: { purpose: "foundation-test", ephemeral: "true" }, cloudInitConfig: { lateCommands: dockerInstall }, }, ], }); // Own provider for the firewall (the module's provider is internal/private). const provider = new hcloud.Provider("foundation-test-hcloud", { token }); const firewall = new hcloud.Firewall( "foundation-test-fw", { name: "foundation-test-fw", rules: [ // SSH — cloud-init moves sshd to 222 (VENDORED.md gotcha) { direction: "in", protocol: "tcp", port: "222", sourceIps: ["0.0.0.0/0", "::/0"] }, // Caddy HTTP/HTTPS { direction: "in", protocol: "tcp", port: "80", sourceIps: ["0.0.0.0/0", "::/0"] }, { direction: "in", protocol: "tcp", port: "443", sourceIps: ["0.0.0.0/0", "::/0"] }, // Forgejo git-over-SSH (CONTRACT_001 forgeSshPort) { direction: "in", protocol: "tcp", port: "2222", sourceIps: ["0.0.0.0/0", "::/0"] }, { direction: "in", protocol: "icmp", sourceIps: ["0.0.0.0/0", "::/0"] }, ], }, { provider }, ); new hcloud.FirewallAttachment( "foundation-test-fw-attach", { firewallId: firewall.id.apply((id) => Number(id)), serverIds: [dep.servers[0].id.apply((id) => Number(id))], }, { provider }, ); // Outputs consumed by the foundation test stack + the operator. export const serverName = dep.serverInfo[0].name; export const publicIp = dep.serverInfo[0].publicIp; export const sshCommand = pulumi.interpolate`ssh -p 222 root@${dep.serverInfo[0].publicIp}`; export const dockerHost = pulumi.interpolate`ssh://root@${dep.serverInfo[0].publicIp}:222`;