1 08 First Real Workload itg prd book
Eric the IT Guy edited this page 2026-08-12 12:49:28 -05:00

Part 8: The First Real Workload — itg-prd-book

Everything before this was plumbing. itg-prd-book is the first host that actually does something: Calibre, calibre-web, and transmission, all as Quadlets, on a bootc image built by the pipeline.

Apps as Quadlets

A Quadlet is a .container (or .network) file that systemd turns into a generated service. You drop them in /usr/share/containers/systemd/ via the image and systemd runs them. Key rules I learned:

  • Give each one [Install] WantedBy=multi-user.target so it auto-starts. Without it, it just sits there.
  • Do NOT systemctl enable a Quadlet service. The generator handles it; enabling it by hand breaks things.
  • AutoUpdate=registry plus podman-auto-update.timer is what refreshes the app images (the 4 AM step from Part 7).

The apps are linuxserver.io images (lscr.io/linuxserver/...). Two settings make or break them: PUID/PGID must match the file owner (my worker user, 1001), and you set TZ. Get the PUID wrong and the app cannot write its own config, which looks like a hundred other problems.

Data disk vs NFS: pick per data type

This was a real design decision, not a coin flip:

  • App databases go on a local disk. SQLite over NFS is a corruption risk because of file locking, so the app configs and the Calibre metadata.db live on a local dataBook XFS disk (Part 2's first-boot format pattern).
  • Bulk media and downloads go on NFS. They are big, sequential, and lock-free, so the NFS shares are perfect for them.

SELinux volume labels

Podman volume suffixes matter here:

  • :Z relabels a volume private to one container (each app's /config).
  • :z relabels a volume as shared between containers (the Calibre library, which both calibre and calibre-web mount).
  • For the NFS download share you cannot relabel, so you pass context= on the mount instead (Part 2).

The Proxmox VM

Build the disk image with bootc-image-builder (bib), which now requires --rootfs xfs explicitly and defaults to --local. Output lands as a qcow2. Then on Proxmox:

  • qm importdisk the qcow2, qm set it as scsi0 (OS) and add a second disk as scsi1 (data).
  • VirtIO SCSI controller, not LSI (UEFI/OVMF has no LSI driver), q35 machine type, UEFI, and install qemu-guest-agent (already in the base).

The build has to finish and push before you create the VM, because you need the image to make the OS disk, then you add the data disk.

Lessons

  • Quadlets need WantedBy=multi-user.target and must never be systemctl enabled.
  • linuxserver PUID/PGID has to equal the file owner or the app is read-only to itself.
  • Databases on local disk (SQLite hates NFS locking), bulk media on NFS.
  • :Z private, :z shared, context= for NFS.
  • VirtIO SCSI on UEFI, every time.