Targets, updates & first boot¶
Targets¶
| Target | What gets installed | Install media |
|---|---|---|
coreos |
Fedora CoreOS, stable stream | the stock live ISO after coreos-installer iso customize --dest-device <disk> --dest-ignition <host>.ign. No network is needed for the install, and Ignition is embedded for the installed system |
ucore |
Fedora CoreOS that rebases itself onto a ghcr.io/ublue-os/ucore* image (ucore-minimal, ucore, ucore-hci, with -nvidia / -zfs variants), like uCore's own autorebase example |
as for CoreOS, plus the autorebase units |
debian |
Debian stable (trixie) from the netinst image | the stock netinst with the preseed appended to the installer's initrd (so it answers from the first question on), boot menus that start the unattended entry after a second, and the host's files under /kiwi-server. xorriso -boot_image any replay keeps the original BIOS/UEFI boot setup |
Debian supports partitioning: regular | lvm | crypto (full-disk LUKS with
encrypt: true and a passphrase:). CoreOS and uCore take extra Butane
settings under coreos: (kernel arguments, services, boot_device, …).
The admin user gets passwordless sudo on every target. SSH is keys only unless
you set ssh_password_auth: true.
Updates¶
Updates are fetched continuously on every target. The reboot into them only
happens inside your window (updates.days, time, length_minutes, in local
time).
| Target | Installs updates | Reboots |
|---|---|---|
coreos |
Zincati, continuously | only inside the window (strategy = "periodic") |
ucore |
rpm-ostreed-automatic.timer stages them (the image's default) |
kiwi-staged-reboot.timer reboots into a staged deployment in the window |
debian |
unattended-upgrades, daily | kiwi-reboot-if-required.timer reboots in the window when /var/run/reboot-required exists |
updates.days: [] means any day, and updates.enabled: false turns all of it
off. The containers have their own schedule: the stack's weekly
kiwi-stack update (see below).
First boot¶
kiwi-role.service is a oneshot that runs /var/lib/kiwi-server/role.sh as
root after the network is up. It never runs again once
/var/lib/kiwi-server/role.done exists.
- A failed run is retried on the next boot and shown on the console. The log is
/var/log/kiwi-server-role.log. Follow it live withjournalctl -u kiwi-role -f. - On uCore the unit also waits for
/etc/ucore-autorebase/signed, so the role always runs on the final image. sudo bash /var/lib/kiwi-server/role.sh --forceruns it again by hand.
For a module role, the script then applies the stack:
- it creates the service user, installs or enables docker, loads kernel
modules and applies sysctls, and frees port 53 from systemd-resolved when the
dnsmodule is present; - it unpacks the stack into the stack directory (
docker_dir, default/home/user/docker) and installs the host units; - it installs
/usr/local/bin/kiwi-stackand/etc/kiwi-server/stack.env; - it opens the stack's ports in firewalld or ufw, if one of them is active;
- it enables
kiwi-stack.service(compose up at boot), the daily VPN restart and weekly update timers, and the module's own host units.
On the machine: kiwi-stack¶
sudo kiwi-stack start # compose up, routes into the mesh
sudo kiwi-stack stop
sudo kiwi-stack restart
sudo kiwi-stack update # pull, restart, prune
sudo kiwi-stack status
sudo kiwi-stack logs
sudo kiwi-stack vpn-restart # the VPN client and every container in its namespace
kiwi-stack start also routes the mesh subnet through the VPN client (through
the WireGuard server on a master), so the host and its containers reach every
other node.
What a render produces¶
output/<host>/ contains:
| File | What |
|---|---|
<host>.role.sh |
the role as one script: settings, embedded files (the rendered stack among them), the common library and the role body. Mode 0600, because it holds secrets |
<host>.stack/ |
module roles: the rendered docker-compose.yml, the module configs (nginx.conf, post-rules.txt, gw.sh, start.sh, torrc, Pi-hole's records) and the host units, for review. The script carries a copy |
<host>.bu, <host>.ign |
CoreOS/uCore: Butane (fcos 1.6.0) and Ignition: admin user, hostname, static network, time zone, update policy, kiwi-role.service, uCore autorebase units |
<host>.preseed.cfg, <host>.kiwi-server/ |
Debian: the preseed, and the files its late command copies in from /cdrom/kiwi-server |
<host>.iso |
the unattended installer |
README.txt |
the same, for that host |
Toolchain¶
| Tool | Used for |
|---|---|
butane |
Butane → Ignition (--strict) |
coreos-installer |
downloading and verifying the Fedora CoreOS ISO, iso customize |
xorriso, cpio, gzip, curl |
rebuilding and downloading the Debian netinst |
These run natively when installed, and otherwise in a small podman or docker
image (kiwi-server toolchain build). Inside the container a tool sees the
output and cache directories at the same paths, so nothing else changes.
--toolchain native or --toolchain container forces one or the other.