Skip to content

Commit 945f471

Browse files
committed
doc: Update the documentation for the generic-iso
Related: HMS-10627
1 parent 0af682f commit 945f471

1 file changed

Lines changed: 120 additions & 103 deletions

File tree

Lines changed: 120 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,149 @@
1-
# ISOs
1+
# bootc generic-iso
22

3-
## Generic
3+
This ISO contains a bootable bootc root filesystem in /LiveOS/squashfs.img, the ISO
4+
is bootable as an ISO or as an image written to a USB flash drive.
45

5-
`image-builder` can build ISOs out of bootable containers. The image type to use to build ISOs is the `bootc-generic-iso` image type. `image-builder` takes the bootable container and explodes the relevant parts to put them into the correct places on the ISO this means that there is a small contract in place on what `image-builder` expects to exist in your bootable container:
6+
This ISO is created from a bootc container using image-builder. You create a
7+
custom container using podman, then run image-builder to turn it into an ISO.
68

7-
1. A kernel must live in `/usr/lib/module/*/vmlinuz`. If there are multiple kernels the behavior is undefined. This kernel will be placed in `/images/pxeboot/vmlinuz` on the ISO filesystem.
8-
2. An initramfs is expected to be next to the kernel with the filename `initramfs.img`. The initramfs is placed in `/images/pxeboot/initrd.img` on the ISO filesystem.
9-
3. The UEFI vendor is sourced by a directory name in `/usr/lib/efi/shim/*EFI/$VENDOR`. If there are multiple directories the behavior is undefined. The `BOOT` directory is always ignored.
10-
4. shim and grub2 EFI binaries (`shimx64.efi`, `mmx64.efi`, `gcdx64.efi`) are expected to be present in `/boot/efi/EFI/$VENDOR`.
11-
5. `/usr/share/grub2/unicode.pf` and `/usr/lib/grub/i386-pc` are expected to present. These are normally provided by the `grub2-common` and `grub2-pc-modules` packages respectively. The latter is only necessary on `x86_64`.
12-
5. Required executables in the container are: `podman`, `mksquashfs`, `xorriso`, `implantisomd5`, `grub2-mkimage` and `python`. If you are using a separate build container then these executables must exist in the build container.
13-
6. The container image is converted to a `squashfs` filesystem and put into `/LiveOS/squashfs.img` in the ISO.
9+
## bootc container
1410

15-
You can [define additional configuration](./05-sources-of-configuration.md#isoyaml) for an ISO inside your container.
11+
The bootc container has a few requirements:
1612

17-
If a `--bootc-installer-payload-ref` argument is optionally passed to `image-builder` when building a `bootc-generic-iso` then the container reference is copied from the hosts container storage to `/var/lib/containers/storage` in the squashfs filesystem.
13+
* Be based on a bootc container, eg. quay.io/fedora/fedora-bootc:latest
14+
* Include the dracut-live, erofs-utils packages
15+
* Include grub2 ISO bootloader related tools
16+
- grub2-efi-*-cdboot xorriso isomd5sum shim
17+
* Configure dracut to add the dmsquash-live module
18+
* Configure ostree to not use composefs
19+
* Rebuild the initramfs so that it includes the dmsquash-live module
20+
* Optionally setup the ISO menus and kernel cmdline with iso.yaml
1821

19-
### Example Containerfile
22+
## Sample Fedora bootc container
2023

21-
This container file builds a `Fedora` "payload" installer (a `boot.iso`). It installs the container that's mentioned in the `/usr/share/anaconda/interactive-defaults.ks` kickstart file.
24+
This is a simple example using the `image-builder` cmdline tool and a local install of podman.
2225

23-
```Dockerfile
24-
FROM quay.io/fedora/fedora-bootc:rawhide
26+
Save this in `Containerfile`:
2527

26-
RUN dnf install -qy \
27-
anaconda \
28-
anaconda-install-img-deps \
29-
anaconda-dracut \
30-
dracut-config-generic \
31-
dracut-network \
32-
net-tools \
33-
grub2-efi-x64-cdboot \
34-
plymouth \
35-
default-fonts-core-sans \
36-
default-fonts-other-sans \
37-
google-noto-sans-cjk-fonts
28+
```
29+
FROM quay.io/fedora/fedora-bootc:latest
30+
RUN dnf -y install grub2-efi-*-cdboot xorriso isomd5sum dracut-live erofs-utils shim && dnf clean all
31+
RUN mkdir /boot/efi && cp -r /usr/lib/efi/shim/*/EFI /boot/efi && cp -r /usr/lib/efi/grub2/*/EFI/* /boot/efi/EFI/
32+
33+
# Override using composefs for ostree (it is incompatible with the erofs rootfs)
34+
RUN cat <<EOF > /usr/lib/ostree/prepare-root.conf
35+
[composefs]
36+
enabled = no
37+
[sysroot]
38+
readonly = true
39+
EOF
40+
41+
# Include the dmsquash-live module in the initramfs
42+
RUN cat <<EOF > /usr/lib/dracut/dracut.conf.d/40-iso.conf
43+
compress="xz"
44+
add_dracutmodules+=" qemu qemu-net livenet dmsquash-live "
45+
early_microcode="no"
46+
EOF
47+
48+
# Override the default ISO menus
49+
RUN mkdir -p /usr/lib/image-builder/bootc
50+
RUN cat <<EOF > /usr/lib/image-builder/bootc/iso.yaml
51+
label: bootc-generic
52+
kernel_args:
53+
- console=ttyS0
54+
grub2:
55+
timeout: 5
56+
entries:
57+
- name: Boot Linux
58+
linux: \${kernelpath} \${root}
59+
initrd: \${initrdpath}
60+
- name: Boot Linux With debug
61+
linux: \${kernelpath} \${root} rd.debug=1
62+
initrd: \${initrdpath}
63+
EOF
3864
39-
# these are necessary build tools. if you use a separate build container then
40-
# these tools should be installed there
41-
RUN dnf install -qy \
42-
xorrisofs \
43-
squashfs-tools
65+
# Rebuild the initrd
66+
RUN set -xe; kver=$(ls /usr/lib/modules); env DRACUT_NO_XATTR=1 dracut -vf /usr/lib/modules/$kver/initramfs.img "$kver"
4467
45-
RUN dnf clean all
68+
# Mask services that aren't compatible with running from an ISO
69+
RUN systemctl mask bootc-generic-growpart.service bootc-publish-rhsm-facts.service bootloader-update.service rpm-ostree-fix-shadow-mode.service
4670
47-
RUN mkdir -p /boot/efi && cp -ra /usr/lib/efi/*/*/EFI /boot/efi
71+
RUN bootc container lint
72+
```
4873

49-
# ---
74+
Build this container using podman:
75+
```
76+
podman build -f ./Containerfile -t bootc-iso
77+
```
5078

51-
# some configuration for our ISO
79+
Run `image-builder` to create the ISO:
80+
```
81+
image-builder build --bootc-default-fs ext4 --bootc-ref localhost/bootc-iso:latest generic-iso
82+
```
5283

53-
RUN mkdir -p /usr/lib/image-builder/bootc
84+
If your container is on a remote system replace the
85+
`localhost/bootc-iso:latest` with the right url.
5486

55-
COPY <<EOT /usr/lib/image-builder/bootc/iso.yaml
56-
label: "Fedora-bootc-Installer"
57-
grub2:
58-
entries:
59-
- name: "Install Fedora (bootc)"
60-
linux: "/images/pxeboot/vmlinuz inst.stage2=hd:LABEL=Fedora-bootc-Installer console=tty0 inst.graphical selinux=0 rhgb quiet"
61-
initrd: "/images/pxeboot/initrd.img"
62-
EOT
63-
64-
# some configuration for anaconda
65-
66-
COPY <<EOT /usr/share/anaconda/interactive-defaults.ks
67-
bootc --source-imgref registry:quay.io/fedora/fedora-bootc:rawhide --target-imgref quay.io/fedora/fedora-bootc:rawhide
68-
EOT
69-
70-
# ---
71-
72-
# these things are normally performed by `lorax` to make `anaconda` work; this is the
73-
# bare minimum to get things to work
74-
75-
RUN echo "install:x:0:0:root:/root:/usr/libexec/anaconda/run-anaconda" >> /etc/passwd && \
76-
echo "install::14438:0:99999:7:::" >> /etc/shadow && \
77-
passwd -d root
78-
79-
RUN mv /usr/share/anaconda/list-harddrives-stub /usr/bin/list-harddrives && \
80-
mv /etc/yum.repos.d /etc/anaconda.repos.d && \
81-
ln -s /lib/systemd/system/anaconda.target /etc/systemd/system/default.target && \
82-
rm -v /usr/lib/systemd/system-generators/systemd-gpt-auto-generator
83-
84-
RUN ln -s /usr/lib/systemd/system/anaconda-shell@.service /usr/lib/systemd/system/autovt@.service
85-
86-
RUN mkdir /usr/lib/systemd/logind.conf.d
87-
COPY <<EOT /usr/lib/systemd/logind.conf.d/anaconda-shell.conf
88-
[Login]
89-
ReserveVT=2
90-
EOT
91-
92-
RUN mkdir "$(realpath /root)" && \
93-
kernel=$(kernel-install list --json pretty | jq -r '.[] | select(.has_kernel == true) | .version') && \
94-
DRACUT_NO_XATTR=1 dracut --force -v --zstd --reproducible --no-hostonly \
95-
--add "anaconda" \
96-
"/usr/lib/modules/${kernel}/initramfs.img" "${kernel}"
97-
98-
RUN mkdir /etc/systemd/user/pipewire.service.d/
99-
COPY <<EOT /etc/systemd/user/pipewire.service.d/allowroot.conf
100-
[Unit]
101-
ConditionUser=
102-
EOT
103-
104-
RUN mkdir /etc/systemd/user/pipewire.socket.d/
105-
COPY <<EOT /etc/systemd/user/pipewire.socket.d/allowroot.conf
106-
[Unit]
107-
ConditionUser=
108-
EOT
87+
## Sample CentOS 10 bootc container
88+
89+
The CentOS container is slightly different from the Fedora container due to the
90+
bootloader files being in a different location.
91+
92+
Replace the top 3 lines with:
93+
```
94+
FROM quay.io/centos/centos-bootc:c10s
95+
RUN dnf -y install grub2-efi-*-cdboot xorriso isomd5sum dracut-live erofs-utils shim && dnf clean all
96+
RUN cp -r /usr/lib/bootupd/updates/EFI/* /boot/efi/EFI/
97+
```
98+
99+
The remainder of the Containerfile is identical to the Fedora example.
100+
101+
# User config
102+
103+
When building the ISO you can use the `image-builder --blueprint user.toml`
104+
option to customize the users, including root. See the documentation at
105+
https://osbuild.org/docs/user-guide/blueprint-reference/#additional-users
106+
107+
For example, to set the root password use a minimal blueprint like this:
109108
```
109+
name = "setup-root"
110+
version = "1.0.0"
111+
112+
[[customizations.user]]
113+
name = "root"
114+
password = "root-password"
115+
```
116+
117+
And run `image-builder` like so:
118+
```
119+
image-builder build --bootc-default-fs ext4 --bootc-ref localhost/bootc-iso:latest --blueprint setup-root.toml generic-iso
120+
```
121+
122+
# Troubleshooting
110123

111-
You can then build this into an ISO:
124+
You can inspect the container you built by running bash:
112125

113126
```
114-
sudo podman build -t localhost/iso -f Containerfile
115-
sudo image-builder build --bootc-ref localhost/iso --bootc-default-fs ext4 bootc-generic-iso
127+
podman run --rm -it localhost/bootc-iso:latest /usr/bin/bash
116128
```
117129

118-
> [!WARNING]
119-
> *A `bootc`-system installed through Anaconda will fail to start the `systemd-remount-fs.service`. See [here](https://forge.fedoraproject.org/atomic-desktops/tracker/issues/72#issuecomment-593808) and [here](https://bugzilla.redhat.com/show_bug.cgi?id=2332319) for more information.*
130+
Check the contents of `/usr/lib/ostree/prepare-root.conf` and
131+
`/usr/lib/dracut/dracut.conf.d/40-iso.conf` to make sure they were created
132+
correctly. You can also run `lsinitrd --mod /usr/lib/modules/*/initramfs.img`
133+
to check to make sure the new initramfs contains the dmsquash-live and ostree
134+
modules.
120135

136+
## Fails to mount the OSTree root
121137

122-
For more examples, including for other operating systems, you can take a look at [this demonstration repository](https://github.com/ondrejbudai/bootc-isos).
138+
If you get an error like:
123139

124-
## Historical
140+
ostree-prepare-root[848]: ostree-prepare-root: Couldn't find specified OSTree root
125141

126-
### `bootc-installer`
142+
Check that the grub.cfg `ostree=...` entry in grub.cfg points to the path in the
143+
rootfs.img. The build process sets this uuid from the ostree directory so this really should not happen with an ISO build unless you change the ISO contents yourself.
127144

128-
There's an alternative image type called `bootc-installer` which makes more assumptions about the contents of the container. You should prefer using `bootc-generic-iso`.
145+
Or if the error looks like:
129146

130-
### `anaconda-iso`
147+
ostree-prepare-root: Failed to mount composefs: composefs: failed to mount: Input/output error
131148

132-
There was an alternative image type called `anaconda-iso` or `iso` in `bootc-image-builder` but this image type is not available in `image-builder`. See the [migration guide](./50-migration.md).
149+
Check the prepare-root.conf file to make sure composefs has been disabled.

0 commit comments

Comments
 (0)