Fedora CoreOS on Raspberry Pi 4
A guide that walks through the steps to build and use coreos-assembler
to install Fedora CoreOS on a Pi 4.
This guide walks through the steps to assemble a Fedora CoreOS image that targets aarch64, and then continues to installing it onto a USB drive. Afterward, the USB drive is updated to include UEFI for the Raspberry Pi to facilitate booting.
Fedora CoreOS documentation now includes instructions for Provisioning Fedora CoreOS on the Raspberry Pi 4. In addition, the Fedora Project also provides official builds targeting aarch64, so building your own image from source is no longer necessary.
Required Items
The following items are used in this guide:
A host Raspberry Pi 4 running either Fedora Server or Fedora Workstation, and relevant peripherals and USB drive.
- This Raspberry Pi 4 should have one blue USB 3.0 port available.
- A target USB drive
- The latest release of Raspberry Pi 4 UEFI Firmware (homepage) downloaded and available.1
First-time Set Up
The following steps will only need to be run once to set up the environment for assembling CoreOS images.
Build the CoreOS Assembler image
The official CoreOS Assembler images target other architectures. In order to use CoreOS Assembler from a Raspberry Pi, a new image that targets aarch64 needs to be built. Start by cloning the source repository:
[robert@pi4 ~]$ git clone https://github.com/coreos/coreos-assembler.git
Cloning into 'coreos-assembler'...
remote: Enumerating objects: 37555, done.
remote: Total 37555 (delta 0), reused 0 (delta 0), pack-reused 37555
Receiving objects: 100% (37555/37555), 30.24 MiB | 4.30 MiB/s, done.
Resolving deltas: 100% (22698/22698), done.
Updating files: 100% (3663/3663), done.
With the source downloaded, change into the source directory and start the image build with podman build
:
[robert@pi4 ~]$ cd coreos-assembler
[robert@pi4 coreos-assembler]$ podman build -t localhost/coreos-assembler .
STEP 1: FROM registry.fedoraproject.org/fedora:32
Getting image source signatures
Copying blob 1bfcc9281f78 [=================>--------------------] 31.6MiB / 66.8MiB
Image creation took roughly one hour to complete for me, so expect to wait some time for it. Once complete, it should finish with output that looks similar to the following:
STEP 14: WORKDIR /srv/
--> 64d9e81c52f
STEP 15: RUN chown builder: /srv
--> f7c3e9149ce
STEP 16: RUN rm -rf /root/containerbuild
--> c2fc11389b2
STEP 17: RUN chmod g=u /etc/passwd
--> 5e2364b0c49
STEP 18: USER builder
--> 51c73f86b8d
STEP 19: ENTRYPOINT ["/usr/bin/dumb-init", "/usr/bin/coreos-assembler"]
STEP 20: COMMIT localhost/coreos-assembler
--> 7660ad1d9f0
7660ad1d9f0eb847327f4d4f70ae9b9c99d3d8c48713663472622f1e2c030037
[robert@pi4 coreos-assembler]$
With the image built, some configuration needs to be set in order to facilitate use of it.
Configure the cosa
Bash function
Add the command from coreos/coreos-assembler into ~/.bashrc
. In this example, the function is wrapped with echo '...' >> ~/.bashrc
to directly add it from the command line.2
[robert@pi4 coreos-assembler]$ cd
[robert@pi4 ~]$ echo 'cosa() {
> env | grep COREOS_ASSEMBLER
> set -x
> podman run --rm -ti --security-opt label=disable --privileged \
> --uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap 1001:1001:64536 \
> -v ${PWD}:/srv/ --device /dev/kvm --device /dev/fuse \
> --tmpfs /tmp -v /var/tmp:/var/tmp --name cosa \
> ${COREOS_ASSEMBLER_CONFIG_GIT:+-v $COREOS_ASSEMBLER_CONFIG_GIT:/srv/src/config/:ro} \
> ${COREOS_ASSEMBLER_GIT:+-v $COREOS_ASSEMBLER_GIT/src/:/usr/lib/coreos-assembler/:ro} \
> ${COREOS_ASSEMBLER_CONTAINER_RUNTIME_ARGS} \
> ${COREOS_ASSEMBLER_CONTAINER:-quay.io/coreos-assembler/coreos-assembler:latest} "$@"
> rc=$?; set +x; return $rc
> }' >> ~/.bashrc
The cosa
Bash function uses a few environment variables to configure its specific use. The primary one that is relevant here is the COREOS_ASSEMBLER_CONTAINER
variable, which causes the cosa
function to run using the locally created image.
[robert@pi4 ~]$ echo "export COREOS_ASSEMBLER_CONTAINER=localhost/coreos-assembler" >> ~/.bashrc
After the configuration has been applied to future initializations of Bash, it helps to also include the configuration into the currently running instance as well.
[robert@pi4 ~]$ . ~/.bashrc
Initialize the CoreOS working directory
To initialize the CoreOS build, create a new directory to track the assembly process. In this example, fcos
is used to match the documentation from coreos/coreos-assembler
[robert@pi4 ~]$ mkdir fcos
[robert@pi4 ~]$ cd fcos
Inside this directory, initialize an assembly configuration with cosa init
.
[robert@pi4 fcos]$ cosa init https://github.com/coreos/fedora-coreos-config
COREOS_ASSEMBLER_CONTAINER=localhost/coreos-assembler
+ podman run --rm -ti --security-opt label=disable --privileged --uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap 1001:1001:64536 -v /home/robert/fcos:/srv/ --device /dev/kvm --device /dev/fuse --tmpfs /tmp -v /var/tmp:/var/tmp --name cosa localhost/coreos-assembler init https://github.com/coreos/fedora-coreos-config
+ mkdir -p src
+ cd src
+ test -e config
+ case "${source}" in
+ git clone --recurse-submodules https://github.com/coreos/fedora-coreos-config config
Cloning into 'config'...
remote: Enumerating objects: 24, done.
remote: Counting objects: 100% (24/24), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 5551 (delta 14), reused 18 (delta 8), pack-reused 5527
Receiving objects: 100% (5551/5551), 1.10 MiB | 4.34 MiB/s, done.
Resolving deltas: 100% (3008/3008), done.
+ '[' -n '' ']'
+ set +x
Config commit: 5836c2366a448b8fd8278ab4939a1920e1a6a9af
+ manifest=config/manifest.yaml
+ '[' -f config/manifest.yaml ']'
+ mkdir -p cache
+ mkdir -p builds
+ mkdir -p tmp
+ mkdir -p overrides/rpm
+ mkdir -p overrides/rootfs
+ rc=0
+ set +x
As an optional final step to the assembly configuration, change the configuration to the stable
branch.
[robert@pi4 fcos]$ cd src/config/
[robert@pi4 config]$ git checkout stable
Branch 'stable' set up to track remote branch 'stable' from 'origin'.
Switched to a new branch 'stable'
[robert@pi4 config]$ cd -
/home/robert/fcos
Now the CoreOS assembly configuration is ready.
Install coreos-installer
The coreos-installer
application will later be used to write Fedora CoreOS to the target drive. While performing the one-time set up for other parts of the assembly, the installer can also be installed.
Install coreos-installer
from a terminal, like the following:
[robert@pi4 ~]$ sudo dnf install -y coreos-installer
Last metadata expiration check: 0:26:53 ago on Mon 07 Sep 2020 10:06:35 PM CDT.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
coreos-installer aarch64 0.6.0-1.fc32 updates 1.6 M
Transaction Summary
================================================================================
Install 1 Package
Total download size: 1.6 M
Installed size: 5.5 M
Downloading Packages:
coreos-installer-0.6.0-1.fc32.aarch64.rpm 984 kB/s | 1.6 MB 00:01
--------------------------------------------------------------------------------
Total 860 kB/s | 1.6 MB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : coreos-installer-0.6.0-1.fc32.aarch64 1/1
Running scriptlet: coreos-installer-0.6.0-1.fc32.aarch64 1/1
Verifying : coreos-installer-0.6.0-1.fc32.aarch64 1/1
Installed:
coreos-installer-0.6.0-1.fc32.aarch64
Complete!
Assemble a CoreOS Image
With everything prepared, CoreOS can now be assembled. To save time, both the cosa fetch
and cosa build
commands can be performed in succession.
[robert@pi4 fcos]$ cosa fetch && cosa build metal
COREOS_ASSEMBLER_CONTAINER=localhost/coreos-assembler
+ podman run --rm -ti --security-opt label=disable --privileged --uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap 1001:1001:64536 -v /home/robert/fcos:/srv/ --device /dev/kvm --device /dev/fuse --tmpfs /tmp -v /var/tmp:/var/tmp --name cosa localhost/coreos-assembler fetch
Config commit: 8f9328e14e37c82340170a67f82987f5680f479e
Using manifest: /srv/src/config/manifest.yaml
Running: rpm-ostree compose tree --repo=/srv/tmp/repo --cachedir=/srv/cache --touch-if-changed /srv/tmp/treecompose.changed --unified-core /srv/src/config/manifest.yaml --download-only --ex-lockfile=/srv/src/config/manifest-lock.overrides.aarch64.yaml
Loaded lockfiles:
/srv/src/config/manifest-lock.overrides.aarch64.yaml
rpm-ostree version: 2020.4
No previous commit for fedora/aarch64/coreos/stable
Enabled rpm-md repositories: fedora-coreos-pool
⠉ Updating metadata for 'fedora-coreos-pool' 28% [█████░░░░░░░░░░░░░░░] (1s)
Similar to building the CoreOS Assembler image, this will also take a long time. Go brew and drink a few cups of coffee or tea while you wait.
When the assembly has completed, the last few lines of output should look similar to the following:
+ cosa meta --workdir /srv --build 32.20200907.dev.0 --artifact metal --artifact-json /srv/tmp/build.metal/meta.json.new
/srv/builds/32.20200907.dev.0/aarch64/meta.json wrote with version stamp 1599467889158279969
+ /usr/lib/coreos-assembler/finalize-artifact fedora-coreos-32.20200907.dev.0-metal.aarch64.raw /srv/builds/32.20200907.dev.0/aarch64/fedora-coreos-32.20200907.dev.0-metal.aarch64.raw
+ rm -rf /srv/tmp/build.metal
+ rm -rvf /srv/builds/32.20200907.dev.0/aarch64/.metal.building
removed '/srv/builds/32.20200907.dev.0/aarch64/.metal.building'
+ rc=0
+ set +x
[robert@pi4 fcos]$
Install CoreOS to a target drive
With the CoreOS image assembled, it’s time to install it. Assuming that the host Raspberry Pi 4 has booted from a drive in one of the blue USB 3.0 ports, insert the target USB drive into the other blue USB 3.0 port.
If running from Fedora Workstation, ensure that any existing partitions are unmounted – but not ejected – before continuing.
Run coreos-installer
to write CoreOS
Start the installation by running coreos-installer
.
In the example command below, the ignition file is specified as /path/to/file.ign
. Change this to the path of the intended ignition file.
The command below assumes that the target drive is /dev/sdb
. This should be the case for any Raspberry Pi 4 running Fedora according to my previous guides; double-check the device identifier prior to running the command.
[robert@pi4 fcos]$ sudo coreos-installer install /dev/sdb --ignition-file /path/to/file.ign --image-file builds/latest/aarch64/fedora-coreos-32.*-metal.aarch64.raw --offline --insecure
Copying image from builds/latest/aarch64/fedora-coreos-32.20200907.dev.0-metal.aarch64.raw
Reading signature from builds/latest/aarch64/fedora-coreos-32.20200907.dev.0-metal.aarch64.raw.sig
Couldn't read signature file: No such file or directory (os error 2)
Signature not found; skipping verification as requested
> Read disk 2.7 GiB/2.7 GiB (100%)
Writing Ignition config
Install complete.
Fedora CoreOS is now installed to the USB drive; however, it is not yet bootable from a Raspberry Pi 4.
Add UEFI to the new EFI partition
The CoreOS assembler and installer assume that EFI is available on the target system. Because of this, no effort is made to include u-boot, UEFI, or other shim that facilitates Raspberry Pi boot.
Create a directory to mount the EFI partition, then mount the EFI partition onto it:
[robert@pi4 fcos]$ sudo mkdir -p /mnt/fcos-efi
[robert@pi4 fcos]$ sudo mount /dev/sdb2 /mnt/fcos-efi
Unpack UEFI into the EFI partition.1
[robert@pi4 fcos]$ cd /mnt/fcos-efi
[robert@pi4 fcos-efi]$ sudo unzip ~/RPi4_UEFI_Firmware_v1.19.zip
Archive: /home/robert/RPi4_UEFI_Firmware_v1.19.zip
inflating: RPI_EFI.fd
inflating: Readme.md
inflating: bcm2711-rpi-4-b.dtb
inflating: config.txt
inflating: fixup4.dat
inflating: overlays/miniuart-bt.dtbo
inflating: start4.elf
As with the guides for Fedora Server and Workstation, I similarly recommend disabling the rainbow square splash screen:
[robert@host rpi-uefi]$ echo "disable_splash=1" | sudo tee -a config.txt
disable_splash=1
Finally, unmount and clean up.
[robert@pi4 fcos-efi]$ cd -
/home/robert/fcos
[robert@pi4 fcos]$ sudo umount /mnt/fcos-efi
[robert@pi4 fcos]$ sudo rmdir /mnt/fcos-efi
The USB drive is now ready for booting.
Remove 3gb RAM limit
On the first boot, it is recommended to disable the RAM limit in UEFI. For steps to do this, refer to the Configure UEFI to disable the RAM limiter
section of my guide on Installing Fedora Server.
A fresh unpack of UEFI is used in this guide. Actually, UEFI can be copied from the running system, but I opt against this to avoid copying any boot configuration that was set up by the host Pi’s Fedora.
Ultimately, it doesn’t make much difference: The fresh install requires disabling the RAM limiter again; while the copied install requires either waiting several minutes for PXE to timeout or adjusting the boot order. ↩︎ ↩︎2
The command without Bash output is listed here to facilitate copy and paste:
echo 'cosa() { env | grep COREOS_ASSEMBLER set -x podman run --rm -ti --security-opt label=disable --privileged \ --uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap 1001:1001:64536 \ -v ${PWD}:/srv/ --device /dev/kvm --device /dev/fuse \ --tmpfs /tmp -v /var/tmp:/var/tmp --name cosa \ ${COREOS_ASSEMBLER_CONFIG_GIT:+-v $COREOS_ASSEMBLER_CONFIG_GIT:/srv/src/config/:ro} \ ${COREOS_ASSEMBLER_GIT:+-v $COREOS_ASSEMBLER_GIT/src/:/usr/lib/coreos-assembler/:ro} \ ${COREOS_ASSEMBLER_CONTAINER_RUNTIME_ARGS} \ ${COREOS_ASSEMBLER_CONTAINER:-quay.io/coreos-assembler/coreos-assembler:latest} "$@" rc=$?; set +x; return $rc }' >> ~/.bashrc