mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 19:01:42 +00:00
185 lines
10 KiB
Plaintext
185 lines
10 KiB
Plaintext
# Base image definition. Ubuntu 26.04 is "resolute" — confirmed against the
|
|
# archive and by a real build; the release postdates mkosi 25.3, so the
|
|
# codename is not one the toolchain can be assumed to know.
|
|
[Distribution]
|
|
Distribution=ubuntu
|
|
Release=resolute
|
|
Repositories=main,universe
|
|
|
|
[Output]
|
|
Format=disk
|
|
ImageId=spinifex
|
|
# Pinned so systemd-repart derives the same partition/filesystem UUIDs on
|
|
# every build, instead of mkosi's default fresh uuid4() per invocation.
|
|
# [Output] is correct here — verified against the pinned mkosi (25.3).
|
|
Seed=deadbeef-dead-beef-dead-beefdeadbeef
|
|
|
|
[Build]
|
|
# No loop devices: repart writes the partition table offline, which is what
|
|
# lets the build run unprivileged.
|
|
RepartOffline=yes
|
|
|
|
[Content]
|
|
# Every image built from this base is a bootable UEFI disk. mkosi
|
|
# installs the kernel below and owns the bootloader/ESP itself, so boot-time
|
|
# tweaks are expressed as mkosi settings rather than sed patches against
|
|
# extlinux/GRUB. Bootloader= defaults to systemd-boot, the native fit for
|
|
# Format=disk + RepartOffline=yes.
|
|
Bootable=yes
|
|
# mkosi's own installer, not debootstrap, builds the image: it pulls in only
|
|
# Packages= plus their dependency closure, not a debootstrap "Priority:
|
|
# required/important" baseline. apt is listed explicitly because of that —
|
|
# without it, the image has no package manager of its own at all, which
|
|
# breaks anything (including profile postinst scripts) that shells out to
|
|
# apt-get/apt-mark/dpkg expecting a normal Ubuntu system.
|
|
#
|
|
# systemd-boot-efi carries the actual EFI stub binaries bootctl installs
|
|
# into the ESP (systemd itself only carries bootctl). Unlike on Debian it is
|
|
# in Ubuntu's universe component, not main.
|
|
# cloud-init is not optional and not a convenience: every guest gets its SSH
|
|
# key and its user-data from IMDS via cloud-init, and the NoCloud seed that
|
|
# used to carry them was retired deliberately. The images this replaces are
|
|
# built from a stock Ubuntu cloud image and inherit cloud-init, sshd, sudo and
|
|
# a network renderer from it; mkosi installs only what is listed here, so a
|
|
# from-scratch image gets none of them and launches unreachable — no key, no
|
|
# user-data, and no error to say so.
|
|
#
|
|
# What each one is doing, since none can be dropped without breaking boot:
|
|
# cloud-init consumes IMDS: SSH keys, user-data, hostname, network
|
|
# openssh-server cloud-init installs the key into a sshd that must exist
|
|
# sudo the cloud-init default user is passwordless-sudo by
|
|
# convention; the fleet's tooling assumes it
|
|
# netplan.io cloud-init's renderer on Ubuntu — it writes
|
|
# /etc/netplan/50-cloud-init.yaml, and without a renderer to
|
|
# consume it the guest never configures its NIC, never
|
|
# reaches IMDS, and falls back to DataSourceNone
|
|
# dbus systemd only *Recommends* dbus and mkosi installs no
|
|
# Recommends, so without it listed here systemctl cannot
|
|
# reach the system bus at all ("Failed to connect to system
|
|
# scope bus"). Guests are driven by user-data that runs
|
|
# systemctl — the EKS and ECS bootstraps both do — so this
|
|
# is load-bearing, not diagnostics
|
|
# systemd-resolved
|
|
# the image's only DNS resolver. systemd is only a
|
|
# *Recommends* of it, so a from-scratch build gets a 0-byte
|
|
# /etc/resolv.conf that nothing ever populates: netplan
|
|
# renders to systemd-networkd, and networkd on its own does
|
|
# not write resolv.conf. glibc then falls back to localhost
|
|
# and every lookup dies with "[::1]:53 connection refused",
|
|
# which reads as a network fault rather than a missing
|
|
# package. A node that cannot resolve cannot pull a single
|
|
# container image, so this is load-bearing for both the EKS
|
|
# and ECS images
|
|
# lsb-release cloud-init shells out to it on Ubuntu; without it every
|
|
# boot lands a recoverable-error WARNING and cloud-init
|
|
# reports "degraded" forever, which costs us the ability to
|
|
# read that status as a real signal
|
|
# cloud-guest-utils
|
|
# provides growpart, which is the ONLY thing that expands the
|
|
# root partition to fill the volume a launch asked for. mkosi
|
|
# sizes the disk to its content, so the image ships with
|
|
# almost no free space and a node that pulls container images
|
|
# dies on arrival without this. Not a Recommends of anything
|
|
# here — cloud-init only Recommends gdisk — so it has to be
|
|
# named. systemd-repart is not an alternative: Ubuntu's
|
|
# systemd package carries no repart binary, unit or
|
|
# definitions at all. gdisk is deliberately absent: growpart
|
|
# resizes GPT through sfdisk, pulled in by the hard fdisk
|
|
# dependency, and e2fsprogs (also a dependency) supplies the
|
|
# resize2fs that cloud-init's resizefs module then runs.
|
|
#
|
|
# Deliberately NOT pinning datasource_list here: the guest recognises the
|
|
# platform from the SMBIOS system UUID the launcher spoofs (product_uuid
|
|
# starts with "ec2"), ds-identify narrows to Ec2 on its own, and pinning it
|
|
# per-image is the per-image customisation this whole migration exists to
|
|
# delete. The eks-node profile is the one exception and owns its own drop-in.
|
|
Packages=systemd
|
|
udev
|
|
linux-image-generic
|
|
apt
|
|
systemd-boot-efi
|
|
cloud-init
|
|
openssh-server
|
|
sudo
|
|
netplan.io
|
|
dbus
|
|
systemd-resolved
|
|
lsb-release
|
|
cloud-guest-utils
|
|
dhcpcd-base
|
|
|
|
# dhcpcd-base above is for the two paths that lease an address outside the
|
|
# primary NIC's normal netplan/networkd management: ecs-agent DHCPs a task ENI
|
|
# inside a per-task netns, and mulga-mgmt-net.sh one-shots a cross-host
|
|
# control-plane data NIC. Both were written against Alpine's busybox udhcpc,
|
|
# which Ubuntu does not ship, and both already prefer udhcpc and fall back to
|
|
# dhcpcd — so without this package the fallback resolves to nothing and they
|
|
# fail as an opaque network-setup error.
|
|
|
|
# Without this the guest boots and says nothing: the launcher gives every VM a
|
|
# serial port and `aws ec2 get-console-output` reads it, but a kernel with no
|
|
# console= writes to none of it, so the console stops after the UEFI bootloader
|
|
# and every boot failure is invisible. The images this replaces inherit the
|
|
# setting from the stock cloud image's GRUB config; mkosi assembles the UKI
|
|
# itself, so nothing supplies it.
|
|
#
|
|
# ttyS0 is deliberately LAST: Linux makes the final console= the controlling
|
|
# /dev/console, which is the one userspace and the login prompt land on, and
|
|
# that has to be the port the orchestrator captures. tty0 stays listed so a
|
|
# guest with a video device still shows its boot on screen.
|
|
KernelCommandLine=console=tty0 console=ttyS0,115200n8
|
|
|
|
# systemd-firstboot prompts on the console for anything the image does not
|
|
# already carry, and it does so before multi-user.target — an image missing
|
|
# these simply stops at "Please enter the new timezone name" and waits for a
|
|
# keystroke no VM guest is there to give. Setting them at build time leaves
|
|
# firstboot with nothing to ask.
|
|
#
|
|
# UTC and C.UTF-8 because the guest is a fleet node, not a desktop: logs
|
|
# correlate across hosts only if every guest agrees on the clock's zone, and
|
|
# a fixed locale keeps command output parseable.
|
|
Locale=C.UTF-8
|
|
Keymap=us
|
|
Timezone=UTC
|
|
|
|
# linux-image-generic drags in every linux-firmware-* split package
|
|
# (wifi/bluetooth/AMD+Intel graphics — none of it relevant to a headless VM
|
|
# guest). Left at the default, mkosi's per-kernel modules initrd embeds all
|
|
# of it into the UKI, which blew the UKI out to ~880MB and overflowed the
|
|
# default 512M ESP outright. Exclude= has to be paired with Include=: per
|
|
# mkosi's own docs Include= only ever adds on top of "everything" unless
|
|
# Exclude= first takes everything away, so Exclude=.* is what actually does
|
|
# the trimming here and Include=default (mkosi-initrd's own curated module
|
|
# list for booting a generic VM: virtio/storage/fs) adds back only what
|
|
# boot actually needs. This is a boot-time fix, not just a size one.
|
|
KernelModulesInitrdExclude=.*
|
|
KernelModulesInitrdInclude=default
|
|
|
|
# Two helpers every guest that behaves like an EC2 instance wants, and which
|
|
# both cost nothing on a guest that does not:
|
|
#
|
|
# mulga-ebs-byid mints the /dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_*
|
|
# links for hot-attached viperblock volumes. udev-driven, so
|
|
# it is inert until a volume is actually attached.
|
|
# mulga-mgmt-net configures a dual-NIC system VM's data + mgmt interfaces
|
|
# from a per-launch fw_cfg blob, before cloud-init crawls
|
|
# IMDS. Only system VMs get the blob; the helper exits 0
|
|
# without touching anything when it is absent.
|
|
#
|
|
# They live here rather than in a profile because neither is knowable at build
|
|
# time: any image may later be attached a volume, and any image may later be
|
|
# launched as a control plane. Gating either on profile composition means
|
|
# deciding a per-launch question at build time, and the image that guessed
|
|
# wrong fails with no route to 169.254.169.254 and nothing to say why.
|
|
#
|
|
# Sources are referenced where they already live rather than copied in — the .sh
|
|
# helpers are shared verbatim with the Alpine image that still consumes them, so
|
|
# a copy here would be a second version to keep in step. The .service files sit
|
|
# under scripts/images/eks-node-gpu/ only because that is the one existing
|
|
# systemd image; they are neither GPU- nor EKS-specific, and they move into this
|
|
# tree when scripts/images/ is deleted at cutover.
|
|
ExtraTrees=../scripts/images/eks-node/mulga-ebs-byid.sh:/usr/local/sbin/mulga-ebs-byid
|
|
../scripts/images/common/mulga-mgmt-net.sh:/usr/local/sbin/mulga-mgmt-net
|
|
../scripts/images/eks-node-gpu/mulga-ebs-byid.service:/etc/systemd/system/mulga-ebs-byid.service
|
|
../scripts/images/eks-node-gpu/99-mulga-ebs-byid.rules:/etc/udev/rules.d/99-mulga-ebs-byid.rules
|