Skip to content

Support variant of bootc install to-filesystem omitting bootupctl, fstab #949

Open
@scottcwang

Description

@scottcwang

I'm playing with booting fedora-bootc as a live image. The end goal is a diskless setup where PXE downloads GRUB, GRUB downloads the initramfs and kernel, and dracut (livenet module) downloads the root squashfs (remotely built), mounts it as a live image, and lets ostree boot it. I don't need day-two updates. If my understanding is correct, this resembles how Fedora CoreOS runs from RAM.

I put together a working proof of concept (below) where I make a disk image with a GRUB boot partition, ESP, boot partition, and root partition, and run bootc install to-filesystem on the root partition. bootc install to-filesystem installs fedora-bootc to the root partition, writes fstab, and runs bootupctl to install GRUB to the boot partition. However, I end up deleting the generated fstab and disregarding the boot partition, since I really only need the squashfs of the root partition without fstab, and I'll roll my own GRUB config (writing my own /boot/loader/entries/ostree-1.conf).

In other words, this workflow would be much simpler if bootc install to-filesystem had an option to only install the container image to a given root, and omit writing fstab and running bootupctl. Are there any considerations I'm not thinking of that would make booting fedora-bootc as a live image a bad idea?

Proof of concept

Constructing the squashfs:

#!/usr/bin/env bash

mkdir output

TMPDIR=$(mktemp --directory --tmpdir=output)
mkdir ${TMPDIR}/{efi,boot,root}

truncate ${TMPDIR}/disk.raw --size 16GiB
# boot partition needs to be on the same disk image, since otherwise bootupctl will complain
sfdisk ${TMPDIR}/disk.raw << EOF
label: gpt
label-id: $(uuidgen)
start=1M, size=1M, type="BIOS boot", uuid="$(uuidgen)"
size=100M, type=uefi, uuid="$(uuidgen)"
size=8G, type=linux, uuid="$(uuidgen)"
type=linux, uuid="$(uuidgen)"
EOF
DEVICE=$(sudo losetup --nooverlap --show --partscan --find ${TMPDIR}/disk.raw)

sudo mkfs.fat ${DEVICE}p2
sudo mount ${DEVICE}p2 ${TMPDIR}/efi

bootuuid=$(uuidgen)
sudo mkfs.ext4 -O "^orphan_file" -U ${bootuuid} ${DEVICE}p3
sudo mount ${DEVICE}p3 ${TMPDIR}/boot

rootuuid=$(uuidgen)
sudo mkfs.ext4 -O "^orphan_file" -U ${rootuuid} ${DEVICE}p4
sudo mount ${DEVICE}p4 ${TMPDIR}/root

sudo podman build --tag fedora-bootc-live - <<EOF
FROM quay.io/fedora/fedora-bootc:latest
RUN dnf install --assumeyes dracut-live
RUN echo 'add_dracutmodules+=" livenet "' > /usr/lib/dracut/dracut.conf.d/01-livenet.conf
RUN mkdir /tmp/dracut ; dracut --rebuild \$(find /usr/lib/modules -name initramfs.img)
RUN echo "root" | passwd -s root
EOF

# without --skip-fetch-check: ERROR Installing to filesystem: Verifying fetch: Creating importer: failed to invoke method OpenImage: failed to invoke method OpenImage: pinging container registry localhost: Get "https://localhost/v2/": dial tcp [::1]:443: connect: connection refused
sudo podman run \
    --rm \
    --privileged \
    --pull=newer \
    --security-opt label=type:unconfined_t \
    --volume ./${TMPDIR}/root:/var/root \
    --volume ./${TMPDIR}/boot:/var/root/boot \
    --volume ./${TMPDIR}/efi:/var/root/boot/efi \
    --volume /var/lib/containers:/var/lib/containers \
    --pid host \
    localhost/fedora-bootc-live:latest \
        bootc install to-filesystem --generic-image --skip-fetch-check /var/root

sudo mount -o remount,rw ${DEVICE}p4 ${TMPDIR}/root
OSTREE_DEPLOY=$(cd ${TMPDIR}/root ; find ostree/boot.1/default -name 0 -type l | head -1)
sudo rm ${TMPDIR}/root/${OSTREE_DEPLOY}/etc/fstab
KERNEL_DIR=$(find ${TMPDIR}/root/${OSTREE_DEPLOY}/usr/lib/modules -mindepth 1 -maxdepth 2 -type d | head -1)
INITRAMFS_IMG=output/initramfs.img
VMLINUZ=output/vmlinuz
sudo cp ${KERNEL_DIR}/initramfs.img ${INITRAMFS_IMG}
sudo cp ${KERNEL_DIR}/vmlinuz ${VMLINUZ}

sync
sudo umount ${TMPDIR}/boot
sudo umount ${TMPDIR}/efi
sudo umount ${TMPDIR}/root

sudo mkdir ${TMPDIR}/root/LiveOS
sudo dd if=${DEVICE}p4 of=${TMPDIR}/root/LiveOS/rootfs.img status=progress
SQUASHFS_IMG=output/squashfs.img
sudo mksquashfs ${TMPDIR}/root ${SQUASHFS_IMG}

sudo losetup --detach ${DEVICE}

sudo rm -rf ${TMPDIR}

Taking it for a spin. This makes a disk image with just a boot partition, installs GRUB manually, adds the squashfs / initramfs / kernel, and writes a config that references them:

#!/usr/bin/env bash

SQUASHFS_IMG=$1
INITRAMFS_IMG=$2
VMLINUZ=$3
OSTREE_DEPLOY=$4

mkdir output

TMPDIR=$(mktemp --directory --tmpdir=output)
mkdir ${TMPDIR}/{efi,boot}

truncate ${TMPDIR}/disk.raw --size 16GiB
sfdisk ${TMPDIR}/disk.raw << EOF
label: gpt
label-id: $(uuidgen)
start=1M, size=1M, type="BIOS boot", uuid="$(uuidgen)"
size=100M, type=uefi, uuid="$(uuidgen)"
type=linux, uuid="$(uuidgen)"
EOF
DEVICE=$(sudo losetup --nooverlap --show --partscan --find ${TMPDIR}/disk.raw)

sudo mkfs.fat ${DEVICE}p2
sudo mount ${DEVICE}p2 ${TMPDIR}/efi

bootuuid=$(uuidgen)
sudo mkfs.ext4 -O "^orphan_file" -U ${bootuuid} ${DEVICE}p3
sudo mount ${DEVICE}p3 ${TMPDIR}/boot

## --write-uuid is required. --with-static-configs doesn't work
sudo podman run \
    --rm \
    --privileged \
    --pull=newer \
    --security-opt label=type:unconfined_t \
    --device ${DEVICE}:${DEVICE}:rwm \
    --volume ./${TMPDIR}/boot:/var/root/boot \
    --volume ./${TMPDIR}/efi:/var/root/boot/efi \
    --pid host \
    localhost/fedora-bootc-live:latest \
        bootupctl backend install --device ${DEVICE} /var/root --write-uuid

sudo mkdir --parents ${TMPDIR}/boot/loader/entries
sudo tee ${TMPDIR}/boot/loader/entries/ostree-1.conf <<EOF
title Fedora Linux
version 1
options root=live:UUID=$(sudo blkid ${DEVICE}p3 -s UUID -o value) rw rd.live.ram boot=UUID=$(sudo blkid ${DEVICE}p3 -s UUID -o value) rw console=tty0 console=ttyS0 ostree=/${OSTREE_DEPLOY}
linux /vmlinuz
initrd /initramfs.img
EOF
sudo mkdir ${TMPDIR}/boot/LiveOS
sudo cp ${SQUASHFS_IMG} ${TMPDIR}/boot/LiveOS/squashfs.img
sudo cp ${INITRAMFS_IMG} ${TMPDIR}/boot/initramfs.img
sudo cp ${VMLINUZ} ${TMPDIR}/boot/vmlinuz
sync

sudo umount ${TMPDIR}/{boot,efi}
sudo losetup --detach ${DEVICE}

cp ${TMPDIR}/disk.raw .
sudo rm -rf ${TMPDIR}

#### TEST

sudo virt-install --name fedora-bootc --cpu host --vcpus 4 --memory 4096 --disk disk.raw --os-variant fedora-eln --import --boot uefi,menu=on,useserial=on --noautoconsole
sudo virsh console fedora-bootc
sudo virsh destroy fedora-bootc
sudo virsh undefine --nvram fedora-bootc

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/installIssues related to `bootc install`enhancementNew feature or requesttriagedThis looks like a valid issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions