1 01 Image Mode and the itg base Golden Image
Eric the IT Guy edited this page 2026-08-12 12:49:28 -05:00

Part 1: Image Mode and the itg-base Golden Image

What image mode actually is

Building a server in Fedora bootc feels like building a container, because it basically is one. The whole OS is an image you build with a Containerfile, push to a registry, and roll out. The mental model: the image is a cake recipe, every host bakes the exact same cake, and the only per-host difference is the crumbs each one drops on its own plate.

The three rules that drive every decision:

  • /usr is immutable and comes straight from the image. You cannot write to it at runtime.
  • /etc is a 3-way merge. Your local edits survive upgrades, which is a blessing and occasionally a curse.
  • /var is machine-local and never overwritten by the image. State lives here.

Because /usr is read-only, you do not "install and configure" at runtime. You bake configuration into the image with drop-ins, sysusers.d, tmpfiles.d, and build-time systemctl enable.

What lives in itg-base

FROM quay.io/fedora/fedora-bootc:latest. Then:

Users, via sysusers.d, not useradd. I declare ansible (1000), worker (1001), and itguyeric (2001) as system users in a sysusers file. Gotcha that cost me time: group lines (g) must come before the user lines (u) that reference them, or the build fails.

Passwordless wheel sudo via a drop-in, and the root password block stays commented out. This box is keys-only.

SSH: hardened sshd config plus baked-in public keys. I cannot drop authorized_keys into a home directory at build time because homes live in /var. So the public keys get COPY'd into /usr/share/ssh-keys/, and a tmpfiles.d rule materializes them into each user's ~/.ssh/authorized_keys on first boot. Public keys are safe to commit; private keys and real secrets never go in the image.

Packages. dnf install for the fleet baseline: cockpit-*, nfs-utils, podman, qemu-guest-agent, tuned, vim-enhanced (and later rsync, added in one line for the whole fleet). I also dnf remove the stuff I never want on a VM: iscsi, kdump, kexec.

Quality-of-life: tuned enabled with a profile, the timezone pinned with ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime, and an /etc/environment that sets EDITOR and SYSTEMD_EDITOR=vim so systemctl edit stops dumping me into nano.

A NetworkManager hostname-mode=none drop-in (the reason is Part 3), a loglevel=3 kernel arg via kargs.d, and a drop-in that sets the bootc auto-update timer schedule (Part 7).

The enable line. One build-time systemctl enable covers podman.socket sshd systemd-journald-audit.socket tuned and the shared NFS mount. Note what is NOT here: I do not enable the auto-update timer in the base (that is per-host), and you never systemctl enable a Quadlet-generated service.

Lessons

  • Configuration is data baked into the image, not commands run on a live box. If you find yourself wanting to SSH in and edit /usr, you are fighting the model.
  • Group-before-user in sysusers.
  • Public keys in the image are fine. Secrets are not. That line matters and it holds for the whole series.