Building A DIY Fedora IoT OSTree

Now being fired up let’s familiarize ourselves with the essentials around Fedora IoT and OSTree to get our custom build going. What we are going to do is:

There is one severe thing I want to get out of the way before we proceed: building the Fedora IoT OSTree does only work properly on SELinux enabled host systems. That’s because upstream Fedora IoT comes with SELinux enabled and I don’t want to mess with that. It’s certainly possible but out of scope to do this on other systems, at least for now. So if you are currently running Debian, Ubuntu or anything else without SELinux shipped (and enabled) you’ll probably have to resort to the automated CI approach I’ll be tackling in the future.

Let’s Have Some Fun

First make sure that your workstation has access to the tools ostree, rpm-ostree and git. We’re going to need them when doing this manually. Spoiler: I’ve built a container image that brings all that packaged with tools that support this process. Skip this section if you can’t wait to get going - and consider contributing to the project btw.

We’ll need some temporary directories and files.

mkdir .cache .build-repo .deploy-repo .tmp
export COMMIT_FILE="$(mktemp)"

Next init the build and our target (production) OSTree repositories.

ostree --repo=".build-repo" init --mode=bare-user
ostree --repo=".deploy-repo" init --mode=archive

Let’s git clone the upstream git repository containing the Fedora IoT configuration.

git clone -b "f33" .source-repo

This will make sure that the upstream in version F33 is available in the .source-repo directory. We now need some form of custom configuration to throw into the Remix. See this example repository for reference. The example repository will add a custom package watchdog and it’s configuration file to the resulting OSTree.

Now copy everything together.

cp .source-repo/* .tmp/
cp ostree-files/* .tmp/

Some files we might want or have to merge. This applies to the so called It’s a script which will be executed in the resulting target filesystem of our Fedora IoT Remix that allows us to make last-minute changes like changing file permissions, etc.

cat ".source-repo/" "ostree-files/" > ".tmp/"
chmod +x ".tmp/"

What’s left to do before we can execute the build is to specify build metadata and a ref by which we identify our Remix’ versions.

sed -i "s,OSTREE_REF,THEIoT/stable/x86_64," ".tmp/ostree.json"
export COMMIT_SUBJECT="MBuilt | Builddate $(date --rfc-3339=seconds)"

This will set the REF we use in rpm-ostree rebase to THEIoT/stable/x86_64. Neat. It’s also preparing a built-time tag as metadata for the commit. So let’s not wait any longer and start building. Grab a cup of coffee, depending on your machine that could take a while…

rpm-ostree compose tree --unified-core --cachedir=".cache" --repo=".build-repo" --write-commitid-to="$COMMIT_FILE" ".tmp/ostree.json"

After a coffee or two with a (hopefully) finished build we now can commit the changes and add the result to our production repository. Remember? The one we created an empty directory for at the beginning.

ostree --repo=".build-repo" commit -b "THEIoT/stable/x86_64" -s "$COMMIT_SUBJECT" --tree=ref="$(cat "$COMMIT_FILE")"
ostree --repo=".deploy-repo" pull-local ".build-repo" "THEIoT/stable/x86_64"

Last things to do is to update / generate a so-called summary file in our “production” repository. This summary file contains the contents of the OSTree repository so that clients like a Raspberry Pi with Fedora IoT can process this remote and apply it’s REFs and commits.

ostree --repo=".deploy-repo" summary -u

Optionally (but highly recommended) you can also add a gpg signature to your commits. This reduces the risk that someone rolls out malicious updates from your repository. This requires the clients to know the public key so they can check the signature. I’ll save that part for another time.

ostree --repo=".deploy-repo" gpg-sign <commit-id> <gpg-key-id>


Go Ahead And Upload

You’ve now successfully built your first Fedora IoT Remix! In theory you only have to expose it somewhere, e.g. using NGINX and your Fedora IoT devices can start using it. If you want to add more commits to an existing repo just don’t initialize the .deploy-repo but keep it and repeat the steps on that one.

Now that we have done all those tedious steps, let’s make ourselves more comfortable. E.g. by using the FOSS project RPM-OSTree-Engine which is a container image packed with all the required dependencies and some tools easing out the steps we’ve just done.

Any thoughts of your own?

Feel free to raise a discussion with me on Mastodon or drop me an email.


The text of this post is licensed under the Attribution 4.0 International License (CC BY 4.0). You may Share or Adapt given the appropriate Credit.

Any source code in this post is licensed under the MIT license.