pub const DEFAULT_TEMPLATE: &str = "#cloud-config\n# yah-cloud mirror bootstrap (R092-F2 \u{2014} containerd + yubaba + cloudflared + tailscaled).\n#\n# Substitutions (written as {{ KEY }} with inner spaces so these docs survive rendering):\n# {{ MACHINE_NAME }} \u{2014} machine name from .yah/cloud/machines/<name>.toml\n# {{ YAH_YUBABA_URL }} \u{2014} HTTPS URL of the yah-yubaba release tar.gz\n# (published by .github/workflows/release.yml per musl target;\n# R406-T13: now also contains the kamaji binary +\n# yubaba.service + kamaji.service + yubaba.slice)\n# {{ YAH_YUBABA_SHA256 }} \u{2014} lowercase hex sha256 of the tar.gz at YAH_YUBABA_URL\n# {{ YUBABA_CHANNEL }} \u{2014} release channel: stable | beta\n# {{ CONTAINERD_VERSION }} \u{2014} containerd apt version pin (e.g. 1.7.2~3-0~debian-bookworm);\n# use DEFAULT_CONTAINERD_VERSION constant for Phase 1 baseline\n# {{ HEADSCALE_PREAUTH_KEY }} \u{2014} Tailscale/Headscale pre-auth key (consumed once at join)\n# {{ MESH_LOGIN_SERVER_ARG }} \u{2014} expands to ` --login-server <url>` when a custom Headscale\n# coordinator is configured; empty string for Tailscale SaaS\n# {{ TAGS }} \u{2014} comma-joined machine.mesh_tags for Tailscale advertise-tags\n# {{ CLOUDFLARED_BLOCK }} \u{2014} cloudflared apt-repo install + `cloudflared service install\n# <tok>` (token is a positional arg, not a --token flag \u{2014}\n# R330-B29) + `systemctl enable --now cloudflared` when\n# machine.cloudflared is set; empty string otherwise\n# {{ OPERATOR_BRIDGE_BLOCK }} \u{2014} tailscaled install + `tailscale up` + ufw allow on tailscale0\n# when machine.hosts_operator_bridge = true; empty otherwise\n# {{ COSIGN_VERIFY_BLOCK }} \u{2014} cosign install + `cosign verify-blob` of the yubaba tarball\n# against a pinned GitHub-OIDC identity-regexp when\n# yubaba_cosign_identity_regexp is set (R330-F19/F20); empty\n# string otherwise (sha256 verify stays as the trust gate)\n#\n# The yubaba tarball is curl-fetched at boot (not base64-embedded) because Hetzner caps\n# user_data at 32 KiB (R040-F11). The runcmd verifies sha256, extracts, and installs\n# /usr/local/bin/yubaba + /usr/local/bin/kamaji + three systemd units under\n# /etc/systemd/system/ before the systemd hand-off.\n#\n# Supervision model (W154, R406-T13): yubaba.service and kamaji.service are sibling\n# units, both pinned to yubaba.slice (created by the slice unit, owned by kamaji via\n# Slice= directive). Kamaji starts first (UDS server up before yubaba\'s first Hello);\n# yubaba joins on After=kamaji.service. systemd\'s role is reduced to supervising the\n# two siblings \u{2014} it does NOT see individual workloads, which kamaji owns directly via\n# pidfds + cgroup-v2 syscalls under yubaba.slice.\n#\n# Containerd is the container runtime yubaba drives via gRPC. Podman/podman-compose\n# were removed in R092-F2 (yubaba is now the workload lifecycle owner; see yah-yubaba-\n# integration-testing.md for the ContainerRuntime abstraction).\n#\n# Tailscale (operator-bridge) is optional: only installed when machine.hosts_operator_bridge\n# is true. The yubaba cluster mesh uses its own WireGuard plane (yah-cluster-mesh.md) and\n# does not depend on Tailscale for cluster-internal traffic.\n\nhostname: {{MACHINE_NAME}}\npreserve_hostname: false\n\npackage_update: true\npackage_upgrade: true\npackages:\n - wireguard-tools\n - chrony\n - curl\n - ca-certificates\n - openssh-server\n - ufw\n\nruncmd:\n # Disk bounds FIRST, before anything on this box starts writing. yah doctrine:\n # no process ever grows on disk without an explicit ceiling \u{2014} a full disk takes\n # the node down no matter how good the software above it is. Debian\'s journald\n # default is 10% of the filesystem (capped at 4G), which is a fraction, not a\n # bound. RuntimeMaxUse also bounds RAM, since /run is tmpfs.\n - mkdir -p /etc/systemd/journald.conf.d\n - sh -c \'printf \"[Journal]\\nSystemMaxUse=500M\\nSystemKeepFree=1G\\nSystemMaxFileSize=50M\\nRuntimeMaxUse=64M\\n\" > /etc/systemd/journald.conf.d/10-yah-disk-bounds.conf\'\n - systemctl restart systemd-journald\n # containerd \u{2014} kamaji\'s container backend. Installed unpinned: yubaba drives\n # it over a stable gRPC API, and an exact apt version pin matches neither the\n # Debian repo\'s suffixed versions (e.g. 1.6.20~ds1) nor newer point releases,\n # so it broke first-boot on Debian 12/13 alike (R330-T9).\n - apt-get install -y containerd\n - systemctl enable --now containerd\n # Yubaba + kamaji bundle \u{2014} fetch + verify + install (R406-T13).\n # The tarball contains: yubaba, kamaji, yubaba.service, kamaji.service,\n # yubaba.slice. cloud-init lays the binaries under /usr/local/bin and the units\n # under /etc/systemd/system/ before systemctl daemon-reload.\n - curl -fsSL -o /tmp/yah-yubaba.tar.gz {{YAH_YUBABA_URL}}\n # cosign verify-blob \u{2014} primary trust gate when yubaba_cosign_identity_regexp is\n # set (R330-F19/F20). sha256 line below stays as a redundant integrity check.\n{{COSIGN_VERIFY_BLOCK}}\n - sh -c \'echo \"{{YAH_YUBABA_SHA256}} /tmp/yah-yubaba.tar.gz\" | sha256sum -c -\'\n - tar -xzf /tmp/yah-yubaba.tar.gz -C /tmp\n - sh -c \'cp /tmp/yubaba-*/yubaba /usr/local/bin/yubaba\'\n - sh -c \'cp /tmp/yubaba-*/kamaji /usr/local/bin/kamaji\'\n - chmod +x /usr/local/bin/yubaba /usr/local/bin/kamaji\n - sh -c \'cp /tmp/yubaba-*/yubaba.slice /etc/systemd/system/yubaba.slice\'\n - sh -c \'cp /tmp/yubaba-*/kamaji.service /etc/systemd/system/kamaji.service\'\n - sh -c \'cp /tmp/yubaba-*/yubaba.service /etc/systemd/system/yubaba.service\'\n # litestream-headscale.service \u{2014} headscale DB replication for whichever node\n # holds the ingress owner role. Laid down here and never enabled: leader.rs\n # starts it on gaining that role and stops it on losing it. It MUST be\n # pre-staged for the same reason headscale.service is (see the coordinator\n # pre-stage block below) \u{2014} yubaba runs ProtectSystem=strict and cannot write\n # /etc/systemd/system, so a unit it \"installs\" at runtime is a silent EROFS.\n - sh -c \'cp /tmp/yubaba-*/litestream-headscale.service /etc/systemd/system/litestream-headscale.service\'\n - chmod 0644 /etc/systemd/system/yubaba.slice /etc/systemd/system/kamaji.service /etc/systemd/system/yubaba.service /etc/systemd/system/litestream-headscale.service\n - sh -c \'rm -rf /tmp/yah-yubaba.tar.gz /tmp/yubaba-*\'\n # litestream \u{2014} the replicate/restore binary litestream-headscale.service execs\n # and leader.rs shells for `litestream restore` before starting the appliance.\n # Absent from every node in the fleet as of 2026-09-04, which made the whole\n # DB-continuity path inert regardless of configuration.\n #\n # PINNED TO 0.3.13, NOT LATEST (0.5.x): litestream 0.5 is a rewrite onto the\n # LTX format with a changed config schema, and `litestream::generate_config`\n # emits the 0.3 `dbs[].replicas[].url` shape. Moving to 0.5 is a real\n # migration \u{2014} new config emitter, and a replica written by 0.3 is not a\n # replica 0.5 reads \u{2014} not a version bump. Checksums below were computed by\n # downloading these exact assets, not copied from the release page.\n # A BLOCK SCALAR, not a plain multi-line one: the `echo \"litestream: ...\"`\n # below contains a colon-space, which YAML reads as a mapping indicator and\n # which broke this template\'s parse when it was first written inline.\n - |-\n sh -c \'\n case \"$(dpkg --print-architecture)\" in\n amd64) LS_ARCH=amd64; LS_SHA=eb75a3de5cab03875cdae9f5f539e6aedadd66607003d9b1e7a9077948818ba0 ;;\n arm64) LS_ARCH=arm64; LS_SHA=9585f5a508516bd66af2b2376bab4de256a5ef8e2b73ec760559e679628f2d59 ;;\n *) echo \"litestream: unsupported arch, skipping\" >&2; exit 0 ;;\n esac\n curl -fsSL -o /tmp/litestream.tar.gz \\\n \"https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-${LS_ARCH}.tar.gz\"\n echo \"${LS_SHA} /tmp/litestream.tar.gz\" | sha256sum -c -\n tar -xzf /tmp/litestream.tar.gz -C /usr/local/bin litestream\n chmod +x /usr/local/bin/litestream\n rm -f /tmp/litestream.tar.gz\n \'\n # headscale \u{2014} the coordination server\'s own binary, on EVERY node rather than\n # only the one that was promoted (R858-T4).\n #\n # Why every node: `headscale_appliance::appliance_spec` is a NATIVE workload,\n # so kamaji forks `/var/lib/yah-cloud/headscale/headscale` and pulls nothing.\n # Until now the binary arrived only via `POST /headscale/deploy` \u{2014} the promote\n # path \u{2014} which is why us-west-001 had it (51,593,368 bytes, mtime Jun 22) and\n # us-south-001 had no binary, no config.yaml and no DB. On 2026-09-03\n # ownership moved to south anyway and the appliance ran nowhere for 37 hours.\n # A moveable native appliance needs its executable to be a PROVISIONED\n # PREREQUISITE on every candidate, not a side effect of having once been the\n # coordinator. Staged and never started: leader.rs decides who runs it.\n #\n # Pinned to 0.23.0 \u{2014} the same pin `cloud::mesh::HEADSCALE_VERSION` and\n # `yubaba::DEFAULT_HEADSCALE_VERSION` already carry, kept in lockstep by\n # convention like the config renderers (there is no dependency edge from this\n # template to either constant, so a bump has to touch all three).\n #\n # Checksums were computed by DOWNLOADING these exact assets, not copied off\n # the release page \u{2014} the same standard the litestream block above records. The\n # amd64 size matches the binary already on us-west-001 byte-for-byte, which is\n # the corroboration that this is the asset the fleet is already running.\n #\n # A BLOCK SCALAR for the same reason as litestream\'s: the `echo \"headscale:\n # ...\"` below contains a colon-space, which YAML reads as a mapping indicator.\n - |-\n sh -c \'\n case \"$(dpkg --print-architecture)\" in\n amd64) HS_ARCH=amd64; HS_SHA=d9193dad4b070b9b3f6d54c8f14366952944b6e917672c0bc1dfd8f5491287a7 ;;\n arm64) HS_ARCH=arm64; HS_SHA=99fa9b2944c50759882b578e78aa11968d6fdec9bbfeced88237a1138b89e9fe ;;\n *) echo \"headscale: unsupported arch, skipping\" >&2; exit 0 ;;\n esac\n mkdir -p /var/lib/yah-cloud/headscale\n curl -fsSL -o /tmp/headscale \\\n \"https://github.com/juanfont/headscale/releases/download/v0.23.0/headscale_0.23.0_linux_${HS_ARCH}\"\n echo \"${HS_SHA} /tmp/headscale\" | sha256sum -c -\n mv /tmp/headscale /var/lib/yah-cloud/headscale/headscale\n chmod +x /var/lib/yah-cloud/headscale/headscale\n \'\n # Channel goes into a drop-in (yubaba.service\'s ExecStart bakes the default args;\n # the channel is operator-tunable per node).\n - mkdir -p /etc/systemd/system/yubaba.service.d\n - sh -c \'printf \"[Service]\\nEnvironment=YUBABA_CHANNEL={{YUBABA_CHANNEL}}\\n\" > /etc/systemd/system/yubaba.service.d/channel.conf\'\n # Cloudflare Tunnel \u{2014} public ingress (when machine.cloudflared is set)\n{{CLOUDFLARED_BLOCK}}\n # Operator-bridge \u{2014} Tailscale mesh access (when machine.hosts_operator_bridge = true)\n{{OPERATOR_BRIDGE_BLOCK}}\n # Firewall \u{2014} allow SSH; yubaba RPC (7443) reachability depends on mesh role:\n # mesh-only (deny public) when joining a mesh, or public on a standalone\n # coordinator so the operator can attach + `yah mesh bootstrap` it before any\n # mesh exists to reach it over (R330-F28 #13).\n - ufw --force enable\n - ufw allow 22/tcp\n{{UFW_YUBABA_RULE}}\n # Coordinator pre-stage (standalone only) \u{2014} cloud-init runs unsandboxed at boot,\n # so it lays down the headscale.service unit + opens ufw 80/443 here. yubaba runs\n # under ProtectSystem=strict and CANNOT write /etc/systemd/system or /etc/ufw, so\n # `yah mesh bootstrap` only writes config + `systemctl enable --now headscale`\n # against this pre-staged unit (R330-F28 #15). Empty for joining nodes.\n{{COORDINATOR_PRESTAGE_BLOCK}}\n # /var/lib/yah/yubaba (the secret store, in yubaba.service\'s ReadWritePaths)\n # is created by the unit itself via StateDirectory=yah/yubaba (R589-T2), so no\n # pre-mkdir crutch is needed here \u{2014} the unit no longer fails 226/NAMESPACE.\n # Bring up the supervision tree (W154 ordering): slice \u{2192} kamaji \u{2192} yubaba.\n # kamaji.service has After=yubaba.slice + PartOf=yubaba.slice; yubaba.service\n # has After=kamaji.service + Wants=kamaji.service, so enabling yubaba\n # transitively starts the other two \u{2014} but enabling each explicitly here makes\n # the bring-up order deterministic and surfaces failure on the right unit.\n - systemctl daemon-reload\n - systemctl enable --now yubaba.slice\n - systemctl enable --now kamaji.service\n - systemctl enable --now yubaba.service\n";Expand description
Built-in fallback template, used when .yah/infra/cloud-init/mirror.yml
is absent. Keeps the binary self-contained for tests + new workspaces.