bootc is ridiculously amazing for headless servers – everyone knows that! It’s also a great fit for appliance-style graphical kiosks. What about a daily driver like a desktop or laptop? The TL;DR is it’s amazing, and I thought I’d share my experience.

OK, it’s been about three months since I moved my home server to bootc and setup Gitea to automate everything, even my Rasberry Pi. OMG, I love it so much and the setup keeps expanding. I’ve added a number of additional containerized services on my server (photo prism, LMS, Navidrome, etc), upgraded my switches to 2.5Gb, and I have six bootc repos building nine images automatically for a number of different purposes. Anyway, a colleague at work, who’s a bad influence on me, convinced me I need a new desktop. He was so right. My old Intel i7-4770k (Haswell!!!) system was 10 years old and really showing it’s age. Rather than go down the ginormous rabbit hole of PC gear, I decided it was easier/better to, more or less, copy his setup. Thanks Mark! :) I ended up getting:
- AMD Ryzen 9 9900x
- 64G Ram @6000
- Asus x670e-f
- 1TB fast NVME
- New power supply & a USB C front panel for the case.
- and best of all a new ultra wide monitor (Samsung 34″ S50GC)
A quick aside, I take a lot of pride in being frugal, but my previous monitor was a good example of being too frugal. As soon as I plugged in the new screen, I felt my eyes “sigh” in relief. I never realized how hard my previous screen was on my eyes. This is why you should never repurpose a large, 1080p digital signage screen that you got for free as your main monitor. ….anyway back to the point of this blog.
The Goal:
For some reason I enjoy GNOME on my laptop and KDE on my desktop, and I wanted to stick with this. I’m coming from the rpm-ostree world and essentially I just want the rpms of the OS to be versioned in the container. I rely heavily on flatpaks, toolbox, and podman for my applications and my system looks something like this diagram:

I’m using the default BTRFS partition layout w/ subvolumes for root & home. Basically, everything I need to persist in /var & /home comes pre-configured so virtually no setup is required outside of installing the flatpaks and/or containers and copying my old home directory over.
It all starts with the Containerfile
I started by looking at the Kinoite and Aurora configs for how they were built. I copied a few things from their setups, but not much. As a rule I think it’s important to keep these builds simple, and I don’t need a lot of complexity for my setup. All I’m doing is adding the rpmfusion repos, KDE plus some additional software/packages, and doing a little clean up per Kinoite, and running some of the rpmfusion multimedia setup instructions. It really didn’t take a lot of time.
FROM quay.io/fedora/fedora-bootc:40
#copy configs
COPY etc etc
RUN mkdir -p /var/roothome /data
#install rpmfusion
RUN dnf install -y https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
#install & configure packages
RUN dnf groupinstall -y "KDE Plasma Workspaces" && \
dnf install -y bash-completion bcache-tools bwm-ng cockpit cockpit-podman cockpit-storaged cockpit-ws cockpit-pcp cockpit-podman cockpit-machines cockpit-selinux cups cups-browsed dmraid ethtool firefox firewalld fuse-exfat fwupd gamemode gdb git htop input-leap kamera k3b libvirt-daemon lm_sensors nfs-utils nss-mdns pcp pcp-selinux powertop qemu-kvm samba sysstat thermald tuned vim-enhanced virt-install virt-manager vulkan-tools xdpyinfo wget && \
dnf remove -y plasma-discover-offline-updates plasma-discover-packagekit plasma-pk-updates tracker tracker-miners plasma-x11 plasma-workspace-x11 && \
dnf swap -y ffmpeg-free ffmpeg --allowerasing && dnf update -y @multimedia --setopt="install_weak_deps=False" --exclude=PackageKit-gstreamer-plugin && dnf groupinstall -y "Sound and Video" && dnf swap -y mesa-va-drivers mesa-va-drivers-freeworld && dnf swap -y mesa-vdpau-drivers mesa-vdpau-drivers-freeworld
#configure unit files
RUN systemctl enable lm_sensors sysstat tuned fstrim.timer podman.socket podman-auto-update.timer cockpit.socket libvirtd.socket && \
systemctl set-default graphical.target
Build & Test
It took me about four builds to land on the set of packages, and it was really easy to deploy a VM to give it a quick sanity test. This helped speed up the real install and pass the time while Amazon shipped the hardware. Dropping it into a Gitea repo and scheduling regular builds was a breeze.

Anaconda ❤️ Bare metal
Just like with my server I decided to use Anaconda to provision the container. What I learned from the last attempt is that if you supply a kickstart with only the ostreecontainer
command, then you get a perfect interactive installation experience. My kickstart was one line:
ostreecontainer --url [my_registry]/workstation-bootc:latest
This is ideal for one-off systems like this where it doesn’t makes sense to iron out things like partitioning details. After following the basic anaconda spokes for users, disks, & networking, my system was up and running very fast.

Final Thoughts
If you’re wondering if you should do this for your setup, the answer is a solid maybe. For a lot of people, I suspect they will be better served by “outsourcing” a lot of this to their OS vendor. This is basically the goal of all the Fedora Atomic Desktops and/or Universal Blue. If you like the idea of an immutable desktop, I recommend most people start there. Those also allow containerfile semantics to augment the images. With my experiment, I wanted to answer the “can I?” “should I?” questions, and for me, this is a no-brainer. A lot of that comes down to just how easy this is to pull off, automate w/ git, and change/adapt the setup as my needs change. So if you have access to github, gitlab, etc and you like this idea, then you can & should check it out.
Miscellaneous thoughts in no particular order:
- bootc and git SCALE. I know I only have ~6 repos building, but all the work is done by robots and I literally don’t think about it.
- After doing this for a brief time on my desktop, I would be completely comfortable using the same setup on my work laptop.
- I expect to periodically add/change the RPMs and I love the fact that I’ll have a complete GIT audit trail. Another bonus is I can easily just “move” this setup to any system (thank you borg+vorta for handling my /home dir).
- I’ve never had a system this fast & powerful and I absolutely love it. I don’t feel the need to upgrade to every CPU generation, but I’m starting to think 5-6 years is the sweet spot for me. Waiting 10 year was a mistake.
- Ultra-wide monitors are where it’s at – what have I been doing with my life!!!!!
- I hate thermal paste and seating heat syncs
- I like that gamers keep PC going and keep aesthetics in mind, but …..do we really need LEDs on everything here? Let me answer that. We don’t!
Thanks for hanging out; I hope this is helpful/interesting to others.
UPDATE to Fedora 41 October 29th 2024
OK, so I’ve been loving this setup for a couple weeks and Fedora 41 just shipped today. I was hoping that all I would have to change in my containerfile was the image tag to :41. DNF5 didn’t like a couple of my commands and cockpit-pcp isn’t in the repos anymore. It was super fast to update my commands. Once those ran fine inside a container, I just committed/pushed my changes and ran sudo bootc upgrade --apply
for a flawless upgrade. It’s amazing!
Here’s the updated file – I want to stress it was really easy to get here. Enjoy!
FROM quay.io/fedora/fedora-bootc:41
#copy configs
COPY etc etc
RUN mkdir -p /var/roothome /data
#install rpmfusion
RUN dnf install -y https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
#install & configure packages
RUN dnf group install -y "KDE Plasma Workspaces" && \
dnf install -y --skip-unavailable bash-completion bcache-tools bwm-ng cockpit cockpit-podman cockpit-storaged cockpit-ws cockpit-pcp cockpit-podman cockpit-machines cockpit-selinux cups cups-browsed dmraid ethtool firefox firewalld fuse-exfat fwupd gamemode gdb git htop input-leap kamera k3b libvirt-daemon lm_sensors nfs-utils nss-mdns pcp pcp-selinux powertop qemu-kvm samba sysstat thermald tuned vim-enhanced virt-install virt-manager vulkan-tools xdpyinfo wget && \
dnf remove -y plasma-discover-offline-updates plasma-discover-packagekit plasma-pk-updates tracker tracker-miners plasma-x11 plasma-workspace-x11 && \
dnf swap -y ffmpeg-free ffmpeg --allowerasing && dnf update -y @multimedia --setopt="install_weak_deps=False" --exclude=PackageKit-gstreamer-plugin && dnf group install -y sound-and-video" && dnf swap -y mesa-va-drivers mesa-va-drivers-freeworld && dnf swap -y mesa-vdpau-drivers mesa-vdpau-drivers-freeworld
#configure unit files
RUN systemctl enable lm_sensors sysstat tuned fstrim.timer podman.socket podman-auto-update.timer cockpit.socket libvirtd.socket && \
systemctl set-default graphical.target
Awesome stuff! Was looking for something like this for a while. I love the concept of bootable containers but never saw an example of how it could work on the Linux desktop. I’ll dig deeper into this based on your blog. Cheers!
Hey Eric,
I hope you try it and like it as much as I do. This setup w/ my git automation has been a game changer for me. You may want to also check out these repos for more ideas: https://github.com/vrothberg/fedora-bootc-workstation & https://github.com/martinpitt/workstation-bootc
Cheers,