Replaces the Debian VM that hosted the Gitea Actions runner and adds two new hosts on goose, all provisioned by Ignition instead of cloud-init: - oswald-runner: Gitea Actions runner, keeping its registration in /var/lib/oswald_runner on disk rather than running ephemeral, which was leaving stale offline runners behind whenever a job was interrupted. - ai: LiteLLM proxy and the Gitea MCP server. - oswl-connector: tailscaled against headscale, advertising 192.168.7.0/24 and itself as an exit node. Their registration tokens and keys come from Infisical through the new butane_vars plumbing, so nothing secret is committed -- but each one does land in plaintext in the rendered Ignition snippet on the node, which is the tradeoff for having no cloud-init here. The provider gains an ssh block on both nodes because Proxmox has no API for uploading snippets. That, the snippets content type, and the headscale preauth key all have to be set up by hand first; flatcar-todo.md has the steps and the reasoning behind the awkward parts. Co-Authored-By: Claude Opus 5 <[email protected]>
76 lines
3.1 KiB
YAML
76 lines
3.1 KiB
YAML
# Butane config for a Flatcar VM running the official httpd (Apache) image
|
|
# as a docker container. Applied by Ignition on FIRST BOOT only: to change a
|
|
# running VM, edit this file and taint the VM so it is rebuilt from the image.
|
|
variant: flatcar
|
|
version: 1.0.0
|
|
|
|
systemd:
|
|
units:
|
|
- name: webserver.service
|
|
enabled: true
|
|
contents: |
|
|
[Unit]
|
|
Description=httpd webserver container
|
|
After=docker.service
|
|
Requires=docker.service
|
|
[Service]
|
|
TimeoutStartSec=0
|
|
ExecStartPre=-/usr/bin/docker rm --force webserver
|
|
ExecStart=/usr/bin/docker run --name webserver --rm -p 80:80 httpd:latest
|
|
ExecStop=/usr/bin/docker stop webserver
|
|
Restart=always
|
|
RestartSec=5s
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
# Experimental: Flatcar ships no qemu-guest-agent binary, so this runs one
|
|
# from an Alpine container against the virtio-serial channel Proxmox
|
|
# exposes when the VM's `agent.enabled` is true (see qemu_guest_agent in
|
|
# tfvars). --network host is required so qemu-ga reports the host's real
|
|
# network interfaces/IP instead of the container's own bridge IP.
|
|
# --pid host + the /sbin/shutdown bind mount (see /opt/qga-shutdown.sh
|
|
# below) are required so guest-shutdown/reboot actually reach the host
|
|
# instead of Alpine's own busybox init inside the container.
|
|
# --privileged + host /dev is broader access than qemu-ga strictly needs,
|
|
# but keeps this simple for a first try.
|
|
- name: qemu-guest-agent.service
|
|
enabled: true
|
|
contents: |
|
|
[Unit]
|
|
Description=QEMU guest agent (containerized)
|
|
After=docker.service
|
|
Requires=docker.service
|
|
[Service]
|
|
TimeoutStartSec=0
|
|
ExecStartPre=-/usr/bin/docker rm --force qemu-guest-agent
|
|
ExecStart=/usr/bin/docker run --name qemu-guest-agent --rm --privileged \
|
|
--network host --pid host -v /dev:/dev \
|
|
-v /opt/qga-shutdown.sh:/sbin/shutdown:ro \
|
|
alpine:latest sh -c \
|
|
"apk add --no-cache qemu-guest-agent util-linux && exec qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0"
|
|
Restart=always
|
|
RestartSec=5s
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
|
|
storage:
|
|
files:
|
|
# qemu-ga always execs "/sbin/shutdown <flag> +0 <reason>" (flag is -H
|
|
# halt, -P powerdown, -r reboot) to handle guest-shutdown/guest-reboot.
|
|
# Inside the container that path is Alpine's own busybox shutdown, which
|
|
# only affects the container's namespace. Bind-mounted over /sbin/shutdown
|
|
# in the container (see qemu-guest-agent.service above), this shim uses
|
|
# nsenter to re-enter the real host's namespaces (PID 1 in the container
|
|
# is the host's actual systemd, since the container runs with --pid host)
|
|
# and calls the host's real systemctl instead.
|
|
- path: /opt/qga-shutdown.sh
|
|
mode: 0755
|
|
contents:
|
|
inline: |
|
|
#!/bin/sh
|
|
case "$1" in
|
|
-H) action=halt ;;
|
|
-r) action=reboot ;;
|
|
*) action=poweroff ;;
|
|
esac
|
|
exec nsenter --target 1 --mount --uts --ipc --net -- systemctl "$action"
|