Building your own custom Fedora Silverblue image
It's been over a year since Asteroid Linus Tech Tips hit the Linux desktop, and I'm happy to report that the move to image-based desktops is making some amazing progress! Recently some things have been landing in Fedora that have enabled me to remove more fragility from the client.
Currently, if you're making changes to your local install of Silverblue you're doing something like rpm-ostree add virt-manager libvirt
or whatever. This is great for things that you just want to not run in a toolbox, or for people who just can't bear to not have zsh
on the base image. Or maybe you need something from a 3rd party (like tailscale
) or you want to play with GNOME VRR and want to add that repo. The more things we add, the more things can go wrong.
For example, not fixing your RPMfusion config prior to upgrading can lead to issues. Or if you removed Firefox from the base image and you upgraded to Fedora 37 it would get stuck unless you resolved it manually. (Thanks for the fun firefox-langpacks!)
If you think this sounds suspiciously like PPAs-all-over-again then you'd be right! So what's the solution? The solution is to just not have the resolution on the client at all. Instead we can do these customizations to the base images ahead of time, and then generate an image. After the image is generated, then we put it on the machine. Read this spec here, and I've recently moved a few of my machines over to this new workflow.
Here's my first vid where I go into more detail, keep reading!
We can now declaratively generate operating system configs. And what new thing to do you have learn to do this? Not much, it's a Dockerfile! (or as the podman people call them, Containerfiles). Let's look at mine:
FROM ghcr.io/cgwalters/fedora-silverblue:37
# See https://pagure.io/releng/issue/11047 for final location
COPY etc /etc
COPY ublue-firstboot /usr/bin
RUN rpm-ostree override remove firefox firefox-langpacks && \
rpm-ostree install distrobox gnome-tweaks && \
sed -i 's/#AutomaticUpdatePolicy.*/AutomaticUpdatePolicy=stage/' /etc/rpm-ostreed.conf && \
systemctl enable rpm-ostreed-automatic.timer && \
systemctl enable flatpak-automatic.timer && \
rpm-ostree cleanup -m && \
ostree container commit
I can now take a Silverblue image (see the FROM), do what I want to it, and then it spits out an operating system. I was then able to use a GitHub action to build this image and push it to a registry. Fedora have enabled us to use container images as our OS.
After it's built and published (takes about 2 minutes) I did this still-wip command on my clients:
sudo rpm-ostree rebase --experimental ostree-unverified-registry:ghcr.io/ublue-os/base:latest
Wait for the chunks to download, and reboot into the image. The action rebuilds a new image every night for me, and I get the diffs downloaded and staged automatically. I can push these images to any OCI registry ... and those are mirrored globally. My one-off distro already has a world class CDN for distribution!
Then I took it a bit further, now that I had a base image I wanted to make my own customizations. So I built another image that sources from this base image to make more changes.
Now I have a base image that's basically Fedora with the small changes that I want, and then another image that has my ublue.it configs. Making your own custom images is now trivial.
ANYONE CAN DO THIS.
So what does this mean for my desktop?
It means that instead of you manually adding a COPR to enable GNOME VRR, you'll just rebase to an image that has it, and then you can revert back. When it merges upstream rebase back to vanilla Fedora when it's ready.
At some point some enterprising individual will just generate Nvidia images for people to consume. If it breaks you just rollback or stay on the known working one. It'll make waiting for NVK that much quicker. :D
Not getting what you want out of Silverblue? Anyone can make an image now. Add what you want. I made mine use Flathub by default, no problem, and I'm still getting all the normal Fedora updates. Custom kernels, remove systemd, your favorite Ansible playbooks ... if it can be shoved in a Dockerfile it's all (going to be) there.
And the best part? It's all Docker/Containerfiles. There's already tons of documentation on how to make these, and the tools already exist. No need to learn new languages or ways to do stuff, just some small adaptations to an already huge ecosystem.
No more frankendebians, PPA errors, malformed sources.list, and "I forgot to update a version number in a URL so my package manager broke". We can now just share Dockerfiles and have the machinery generate images. Better to have one place where we can fix the RPMfusion upgrade and send it out to people after it's built and working than to expect all of us to do it, by hand, like savages.
It's the power of having our home directories in git except now we can do this for our OS too. People are going to make awesome stuff with this!
Check out this thread for more info and more examples from the community:
And feel free to browse my stuff and make your own!