Skip to content

Latest commit

 

History

History
256 lines (195 loc) · 9.2 KB

File metadata and controls

256 lines (195 loc) · 9.2 KB

Bootc Hypervisor

Homelab virtualization platform delivered as immutable Fedora bootc images with rootless container workloads, KVM/QEMU VMs, and Incus system containers.

Atomic OS upgrades with instant rollback, declarative workload management via TOML configs, GPU passthrough (AMD/NVIDIA), and TPM2-backed secrets. No cloud dependencies.

Run local services like Pi-hole, VPN proxies, container registry, GPU-accelerated game streaming, AI workloads on an immutable OS that can't be broken by bad upgrades. Each service runs as a locked-down rootless container under its own system user. Updates are pulled from a container registry and applied atomically.

Why

I was no longer willing to struggle with what happens when I update the base OS on my home server. Invariably one or more things would break, sometimes in complex entagled ways. This system gives instant rollback for the base system, and the workloadctl package allows for independent isolation for various services and workloads.

Quick Start

Already running a bootc system:

sudo bootc switch ghcr.io/bensmith/hypervisor-bootc:latest
sudo systemctl reboot

Install from ISO:

just build-iso-base
sudo dd if=output/bootiso/install.iso of=/dev/sdX bs=4M status=progress
# Boot from USB and install

Create a workload:

sudo workloadctl create webserver \
  --image docker.io/nginxinc/nginx-unprivileged:alpine \
  --ports 8080:8080 \
  --enable

workloadctl status webserver
curl http://localhost:8080

Images

fedora-bootc-minimal              Minimal Fedora bootc (kernel, systemd, bootc) - built from Fedora's bootc project
  └── hypervisor-bootc             Full stack: libvirt, QEMU/KVM, Incus, Podman 5
      ├── hypervisor-nvidia:rpmfusion   NVIDIA via RPMFusion (akmod-nvidia, CUDA)
      ├── hypervisor-nvidia:negativo17  NVIDIA via negativo17 (nvidia-driver-cuda)
      └── hypervisor-amd                AMD ROCm + Mesa

All images published to ghcr.io/bensmith/ with datetime tags, signed with cosign (keyless OIDC).

What's in hypervisor-bootc

The base image is headless and includes:

  • Virtualization: libvirt, QEMU/KVM, virt-install
  • System containers: Incus (LXC)
  • Application containers: Podman 5, podman-compose, crun, skopeo
  • Workload management: workloadctl
  • Networking: firewalld, NetworkManager, bridge-utils, wireguard-tools, dnsmasq
  • Storage: btrfs-progs, xfsprogs, lvm2, mdadm, cifs-utils, NVMe tools
  • Monitoring: btop, htop, iotop, sysstat, smartmontools, lm_sensors
  • Security: fail2ban, SELinux, audit, seatd
  • Utilities: tmux, neovim, just, jq, distrobox, fwupd

GPU Variants

Each inherits from hypervisor-bootc and adds kernel GPU drivers:

Variant Driver Includes
hypervisor-nvidia:rpmfusion akmod-nvidia CUDA libs, nvidia-container-toolkit, CDI
hypervisor-nvidia:negativo17 nvidia-driver-cuda More granular packaging, earlier updates
hypervisor-amd ROCm + Mesa HIP, OpenCL, rocm-smi, VA-API

Image Tags

hypervisor-bootc:44-YYYYMMDD-HHMM     # Versioned + timestamped
hypervisor-bootc:44                    # Per-version floating (Fedora 44)
hypervisor-bootc:latest                # Stable Fedora version
hypervisor-nvidia:rpmfusion-44         # Per-version floating (RPMFusion)
hypervisor-nvidia:rpmfusion            # Stable Fedora version (RPMFusion)
hypervisor-nvidia:negativo17-44        # Per-version floating (negativo17)
hypervisor-nvidia:negativo17           # Stable Fedora version (negativo17)
hypervisor-amd:44                      # Per-version floating (AMD)
hypervisor-amd:latest                  # Stable Fedora version (AMD)

:latest / :rpmfusion / :negativo17 always track the stable Fedora version. Pin to a specific version using the bare version number (:43, :44). Supported versions are defined in fedora-versions.yml.

Workload System (workloadctl)

workloadctl is a standalone tool (RPM-packaged, no bootc dependency) that manages rootless podman containers as declarative TOML configs. It should work on systemd Linuxes with Podman 5.3+.

Each workload gets:

  • A dedicated system user (_wl-<name>) with its own UID/subuid namespace
  • A systemd service generated at boot
  • Automatic volume directory creation
  • Optional TPM2-encrypted secrets via systemd credentials
# Create and start
sudo workloadctl create pihole \
  --image pihole/pihole:latest \
  --ports 53:53 80:80 \
  --enable

# Manage
workloadctl list                    # List all workloads
workloadctl status pihole           # Service status
workloadctl logs -f pihole          # Follow logs
sudo workloadctl update pihole      # Pull new image, auto-rollback on failure
sudo workloadctl shell pihole       # Interactive shell

# Secrets
echo -n "my-key" | sudo workloadctl secret create api-key
sudo workloadctl secret list

Or write a TOML config directly:

# /etc/workloads.d/webserver.toml
[workload]
name = "webserver"

[container]
image = "docker.io/nginxinc/nginx-unprivileged:alpine"

[network]
ports = ["8080:8080"]

See the workloadctl README for install instructions and the full feature set.

Installation and Updates

Install

From a bootc system:

sudo bootc switch ghcr.io/bensmith/hypervisor-bootc:latest
sudo systemctl reboot

From installer ISO (build locally or download from releases):

just build-iso-base              # Or: just build-iso-nvidia-rpmfusion
sudo dd if=output/bootiso/install.iso of=/dev/sdX bs=4M status=progress

Update

bootc upgrade --check            # Check for updates
sudo bootc upgrade               # Apply atomically
sudo systemctl reboot

Switch Variants

# Switch to latest stable
sudo bootc switch ghcr.io/bensmith/hypervisor-nvidia:negativo17
sudo systemctl reboot

# Pin to a specific Fedora version
sudo bootc switch ghcr.io/bensmith/hypervisor-bootc:44
sudo bootc switch ghcr.io/bensmith/hypervisor-nvidia:rpmfusion-44

Promoting a New Fedora Release

All version management is a one-file edit to fedora-versions.yml.

1. Add a new version (e.g. F45 ships, F44 stays stable):

stable: 44
supported: [44, 45]
rechunker: 44

Open PR, merge. Next nightly produces :44 + :45 tags; :latest stays on 44.

2. Promote new stable (once F45 is validated):

stable: 45
supported: [44, 45]
rechunker: 45

Next build moves :latest / :rpmfusion / :negativo17 to the F45 image.

3. Drop an EOL version (e.g. F43 goes EOL):

stable: 45
supported: [45, 46]
rechunker: 45

No new :43 builds. Old :43-YYYYMMDD tags remain in GHCR as immutable history. To prune: gh api -X DELETE /user/packages/container/hypervisor-bootc/versions/<id>.

Building Locally

Requires just and podman.

# Container images
just build-base-local                    # Base hypervisor (from local minimal)
just build-amd-local                     # AMD GPU variant
just build-nvidia-rpmfusion-local        # NVIDIA variant
just build-all-local                     # Everything

# ISOs (rootfs: xfs, btrfs, or ext4)
just build-iso-base                      # Base hypervisor ISO
just build-all-isos                      # All variant ISOs

# Development: build, create qcow2, deploy to libvirt VM
just aio-local

# Tests
just test                                # workloadctl unit tests
just test-vm-build && just test-vm       # Full VM integration tests (libvirt + SWTPM)

# Push to local registry
just push-all

Weekly automated builds via GitHub Actions: fedora-bootc-minimal on Saturdays, all hypervisor variants on Sundays.

Design

  • Bootc for immutability/usr is read-only, /etc is mutable config, /var is persistent data. Atomic updates with instant rollback.
  • Rootless containers via dedicated users — Each workload gets a unique _wl-{name} user with its own UID namespace. No privileged containers.
  • systemd-native — Generators for boot-time provisioning, credentials for secrets, cgroup v2 for resource limits, journal for logging.
  • TPM2-backed secrets — Hardware encryption, machine-specific, safe to commit encrypted blobs to images.
  • Explicit hardware opt-in — No device access by default; convenience flags (--gpu, --audio, --input, --virtualization) for common scenarios.

Documentation

License

MIT (Containerfiles, configs, tooling). Fedora packages and upstream components under their respective licenses.