159 lines
6.6 KiB
Markdown
159 lines
6.6 KiB
Markdown
|
|
# bootc-image-builder spike plan — 1-week timebox
|
||
|
|
|
||
|
|
**Agent 3 of 9-agent wave, 2026-05-05.** Schedule: v0.7.
|
||
|
|
|
||
|
|
## Containerfile draft
|
||
|
|
|
||
|
|
```dockerfile
|
||
|
|
# veilor-os bootc image — Fedora 43 KDE base
|
||
|
|
FROM quay.io/fedora/fedora-bootc:43
|
||
|
|
|
||
|
|
ARG VEILOR_VERSION=0.6.0
|
||
|
|
|
||
|
|
RUN dnf install -y --setopt=install_weak_deps=False \
|
||
|
|
@kde-desktop-environment @kde-apps @core @hardware-support @standard \
|
||
|
|
kernel-modules kernel-modules-extra glibc-all-langpacks \
|
||
|
|
grub2-efi-x64 grub2-efi-x64-modules grub2-pc grub2-pc-modules \
|
||
|
|
grub2-tools grub2-tools-extra shim-x64 efibootmgr \
|
||
|
|
newt parted cryptsetup lvm2 btrfs-progs \
|
||
|
|
fail2ban fail2ban-firewalld usbguard usbguard-tools audit \
|
||
|
|
policycoreutils-python-utils tuned chrony firewalld plymouth \
|
||
|
|
git vim-enhanced tmux htop podman skopeo \
|
||
|
|
NetworkManager NetworkManager-wifi \
|
||
|
|
fontconfig freetype fira-code-fonts \
|
||
|
|
zram-generator \
|
||
|
|
&& dnf remove -y --noautoremove \
|
||
|
|
'abrt*' snapd kde-connect open-vm-tools-desktop mlocate man-db man-pages \
|
||
|
|
&& dnf clean all && rm -rf /var/cache/dnf
|
||
|
|
|
||
|
|
ARG GUM_VERSION=0.17.0
|
||
|
|
ARG GUM_SHA256=69ee169bd6387331928864e94d47ed01ef649fbfe875baed1bbf27b5377a6fdb
|
||
|
|
ADD https://github.com/charmbracelet/gum/releases/download/v${GUM_VERSION}/gum_${GUM_VERSION}_Linux_x86_64.tar.gz /tmp/gum.tgz
|
||
|
|
RUN echo "${GUM_SHA256} /tmp/gum.tgz" | sha256sum -c - \
|
||
|
|
&& tar -xzf /tmp/gum.tgz -C /tmp \
|
||
|
|
&& install -m0755 /tmp/gum_${GUM_VERSION}_Linux_x86_64/gum /usr/bin/gum
|
||
|
|
|
||
|
|
COPY overlay/ /
|
||
|
|
COPY assets/ /usr/share/veilor-os/assets/
|
||
|
|
COPY scripts/ /usr/share/veilor-os/scripts/
|
||
|
|
|
||
|
|
RUN bash /usr/share/veilor-os/scripts/10-harden-base.sh \
|
||
|
|
&& bash /usr/share/veilor-os/scripts/20-harden-kernel.sh \
|
||
|
|
&& bash /usr/share/veilor-os/scripts/selinux/build-policy.sh \
|
||
|
|
&& bash /usr/share/veilor-os/scripts/kde-theme-apply.sh \
|
||
|
|
&& bash /usr/share/veilor-os/scripts/30-apply-v03-theme.sh
|
||
|
|
|
||
|
|
RUN plymouth-set-default-theme details \
|
||
|
|
&& sed -i \
|
||
|
|
-e 's|^GRUB_DISTRIBUTOR=.*|GRUB_DISTRIBUTOR="veilor-os"|' \
|
||
|
|
/etc/default/grub
|
||
|
|
|
||
|
|
# bootc kargs go in /usr/lib/bootc/kargs.d/, not /etc/default/grub
|
||
|
|
RUN mkdir -p /usr/lib/bootc/kargs.d && cat > /usr/lib/bootc/kargs.d/10-veilor-hardening.toml <<'EOF'
|
||
|
|
kargs = [
|
||
|
|
"lockdown=integrity",
|
||
|
|
"slab_nomerge",
|
||
|
|
"init_on_alloc=1",
|
||
|
|
"init_on_free=1",
|
||
|
|
"randomize_kstack_offset=on",
|
||
|
|
"vsyscall=none",
|
||
|
|
"fbcon=nodefer",
|
||
|
|
]
|
||
|
|
EOF
|
||
|
|
|
||
|
|
RUN systemctl enable sshd fail2ban usbguard tuned auditd firewalld chronyd sddm \
|
||
|
|
veilor-firstboot.service veilor-modules-lock.service \
|
||
|
|
&& passwd -l root \
|
||
|
|
&& systemctl set-default graphical.target
|
||
|
|
|
||
|
|
RUN bootc container lint
|
||
|
|
LABEL org.veilor.version=${VEILOR_VERSION}
|
||
|
|
```
|
||
|
|
|
||
|
|
## bootc-image-builder config (`build/disk-config.toml`)
|
||
|
|
|
||
|
|
```toml
|
||
|
|
[customizations]
|
||
|
|
hostname = "veilor-os"
|
||
|
|
|
||
|
|
[[customizations.user]]
|
||
|
|
name = "admin"
|
||
|
|
password = "veilor"
|
||
|
|
groups = ["wheel"]
|
||
|
|
shell = "/bin/bash"
|
||
|
|
|
||
|
|
[customizations.kernel]
|
||
|
|
append = "lockdown=integrity slab_nomerge init_on_alloc=1 init_on_free=1 randomize_kstack_offset=on vsyscall=none fbcon=nodefer"
|
||
|
|
|
||
|
|
[customizations.installer.kickstart]
|
||
|
|
contents = """
|
||
|
|
zerombr
|
||
|
|
clearpart --all --initlabel
|
||
|
|
part /boot/efi --fstype=efi --size=600
|
||
|
|
part /boot --fstype=ext4 --size=1024
|
||
|
|
part btrfs.veilor --grow --encrypted --luks-version=luks2 --pbkdf=argon2id
|
||
|
|
btrfs none --label=veilor btrfs.veilor
|
||
|
|
btrfs / --subvol --name=root LABEL=veilor
|
||
|
|
btrfs /home --subvol --name=home LABEL=veilor
|
||
|
|
"""
|
||
|
|
```
|
||
|
|
|
||
|
|
## GitHub Actions workflow
|
||
|
|
|
||
|
|
`build-bootc-iso.yml`:
|
||
|
|
- runs-on ubuntu-24.04, **timeout 30 min** (vs 90 for livecd-creator)
|
||
|
|
- permissions: `contents: write`, `packages: write`
|
||
|
|
- Build OCI image: `podman build` + `podman push ghcr.io/veilor/veilor-os:43`
|
||
|
|
- Build ISO via `quay.io/centos-bootc/bootc-image-builder:latest`
|
||
|
|
with `--type anaconda-iso --rootfs btrfs --config /build/disk-config.toml`
|
||
|
|
- Reuse split + `softprops/action-gh-release@v2` from existing workflow
|
||
|
|
|
||
|
|
## Migration risks (10-row table)
|
||
|
|
|
||
|
|
| # | Risk | Severity | Mitigation |
|
||
|
|
|---|------|----------|------------|
|
||
|
|
| 1 | %post --nochroot overlay-copy disappears | Low | `COPY overlay/ /` is simpler — win |
|
||
|
|
| 2 | Update model: `bootc upgrade` (image swap) replaces `dnf upgrade` | High | `veilor-update` becomes thin `bootc upgrade --apply` wrapper |
|
||
|
|
| 3 | /usr is read-only at runtime | Medium | etc-overlay handles /etc writes; relocate any /usr writers to /etc or build-time |
|
||
|
|
| 4 | SELinux module compilation in container | Medium | Works in fedora-bootc:43 (verified per upstream pattern). Test spike day 2 |
|
||
|
|
| 5 | `transaction_progress.py` patch unnecessary | Low | bootc-image-builder doesn't use dnf at install. Drop the patch. Win |
|
||
|
|
| 6 | `rd.luks.uuid` is anaconda's job again | Low | Removes ~80 lines of fragile sed/grubby code. Win |
|
||
|
|
| 7 | LUKS prompt UX: anaconda native, not gum | High | gum installer becomes `live·shell` only. v1.0 install = anaconda's native UI |
|
||
|
|
| 8 | --privileged still required | None | Same as today |
|
||
|
|
| 9 | OCI image size: ~3.5 GB compressed vs ~2.8 GB squashfs | Low | zstd:max recovers ~400 MB |
|
||
|
|
| 10 | `kernel-install` BLS: `/etc/kernel/cmdline` not honored, `/usr/lib/bootc/kargs.d/*.toml` is | Medium | Already addressed in Containerfile draft |
|
||
|
|
|
||
|
|
## What we keep (zero churn)
|
||
|
|
|
||
|
|
- `overlay/*` — copied verbatim by `COPY overlay/ /`
|
||
|
|
- `scripts/*.sh` — invoked verbatim by Containerfile RUN
|
||
|
|
- `assets/*` — copied verbatim
|
||
|
|
- `test/*` — adapts: `podman run --rm -it ghcr.io/veilor/veilor-os:43 /bin/bash` smoke; QEMU ISO test unchanged
|
||
|
|
- `kickstart/install.ks` — kept as fallback. Tag last anaconda build as `v0.5.99-anaconda` before flipping
|
||
|
|
|
||
|
|
## Spike success criteria (1 week)
|
||
|
|
|
||
|
|
| Day | Milestone |
|
||
|
|
|-----|-----------|
|
||
|
|
| 1 | Containerfile builds clean (`podman build` exit 0, `bootc container lint` exit 0) |
|
||
|
|
| 2 | `podman run` boots into image, KDE binaries present, SELinux + hardening sysctls applied |
|
||
|
|
| 3 | bootc-image-builder produces installer ISO from OCI, ksvalidator clean |
|
||
|
|
| 4 | ISO boots in QEMU to anaconda live menu |
|
||
|
|
| 5 | Install completes, LUKS single-prompt, btrfs subvols present |
|
||
|
|
| 6 | First boot reaches SDDM, admin login works, password-change-on-first-login enforced |
|
||
|
|
| 7 | Buffer for fixes; doc `docs/BUILD-bootc.md`; tag `v0.5.99-anaconda` snapshot |
|
||
|
|
|
||
|
|
## Decision gate
|
||
|
|
|
||
|
|
- **PASS** (all 7 criteria green): tag `v0.5.99-anaconda` as last-anaconda;
|
||
|
|
merge `bootc-spike` → `main` as `v0.6.0-bootc`; deprecate
|
||
|
|
`kickstart/veilor-os.ks` (keep `kickstart/install.ks` for one cycle).
|
||
|
|
Update ROADMAP: v1.0 ships bootc-only.
|
||
|
|
|
||
|
|
- **FAIL** (any of risks 3, 4, 7, 10 unfixable in week 1): keep
|
||
|
|
anaconda path, defer migration to v1.1+; file each blocker as GH
|
||
|
|
issue with reproducer.
|
||
|
|
|
||
|
|
- **HYBRID FALLBACK**: ship anaconda ISO for v0.6/v0.7, ship bootc OCI
|
||
|
|
alongside (matches existing `veilor-atomic` stretch goal).
|