bootc-dev / bootc-dev/bootc

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

Open
#949 4 comments 0 reactions 0 assignees View on GitHub
area/install enhancement triaged
Dominant language
Rust
Stars
2.3k
Forks
230
Avg merge
3d 12h
Merged PRs (30d)
38

Description

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:

```sh
#!/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 - < /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:

```sh
#!/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 <

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.