<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fran Torres</title>
    <description>The latest articles on DEV Community by Fran Torres (@franute).</description>
    <link>https://dev.to/franute</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F63743%2Fe4874729-92ce-4ea1-90a4-f6b5a7f87ceb.JPG</url>
      <title>DEV Community: Fran Torres</title>
      <link>https://dev.to/franute</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/franute"/>
    <language>en</language>
    <item>
      <title>Pi-Hole setup using Quadlets</title>
      <dc:creator>Fran Torres</dc:creator>
      <pubDate>Thu, 22 Feb 2024 14:25:59 +0000</pubDate>
      <link>https://dev.to/franute/pi-hole-setup-using-quadlets-1fjf</link>
      <guid>https://dev.to/franute/pi-hole-setup-using-quadlets-1fjf</guid>
      <description>&lt;p&gt;I've had an old &lt;em&gt;Raspberry Pi Model B&lt;/em&gt; running &lt;a href="https://pi-hole.net/"&gt;Pi-Hole&lt;/a&gt; at home for quite a long time, but I always wanted to dig a bit deeper into using containers to deploy applications. Because of that, I recently purchased a RPi 4 and this week found some time to figure out a way to deploy it using podman.&lt;/p&gt;

&lt;p&gt;Since I started reading about containers, podman and such, it always looked a bit convoluted the way to run an application from the command line; many parameters basically, I didn't want to have one script launching one 100 characters command.&lt;br&gt;
I then learnt &lt;em&gt;docker-compose&lt;/em&gt; files, which are nice, but in my absolutely ignorant opinion seem to be only useful for local services (like on a development environment to spin a database); things you don't want to live forever as a service. And the second problem was: I wanted to use podman and, ideally, only native podman-related solutions.&lt;br&gt;
Fast forward until recently. I read about &lt;strong&gt;systemd-units&lt;/strong&gt; and &lt;strong&gt;quadlets&lt;/strong&gt; and liked what I saw, so here we are.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quadlets
&lt;/h2&gt;

&lt;p&gt;I won't go too deep into all the details about podman, systemd and quadlets as &lt;a href="https://blog.while-true-do.io/podman-quadlets/"&gt;Daniel Schier did it already&lt;/a&gt; way better than I will ever be able to.&lt;br&gt;
Basically you can split a container deployment within its multiple dependant components (volumes, network, the container itself...) and generate systemd services that can be easily managed. You can either do it manually by running the container from the command line (via &lt;code&gt;podman&lt;/code&gt;) and then generate the systemd unit with &lt;code&gt;podman generate systemd&lt;/code&gt; &lt;strong&gt;OR&lt;/strong&gt; you can use &lt;em&gt;quadlets&lt;/em&gt; to have a single centralised set of files that systemd will use to automatically generate the service units for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  Decissions and future goals
&lt;/h2&gt;

&lt;p&gt;[x] Use &lt;em&gt;rootfull&lt;/em&gt; containers for now (it felt easier not having to worry about port mapping).&lt;br&gt;
[x] &lt;a href="https://microos.opensuse.org/"&gt;openSUSE MicroOS&lt;/a&gt; will be the host system. I want to automate maintenance as much as possible and using an immutable &amp;amp; self updatable system is a first step.&lt;br&gt;
[ ] Automatically update the container.&lt;br&gt;
[ ] Use &lt;a href="https://docs.pi-hole.net/guides/dns/unbound/"&gt;unbound&lt;/a&gt;.&lt;br&gt;
[ ] Use rootless containers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deploying Pi-Hole via Quadlets
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Previous step
&lt;/h3&gt;

&lt;p&gt;Without going into much details, first of all make sure there are no processes blocking at least ports 53 (tcp and udp) and 80 tcp if Pi-Hole will only be acting as the DNS server and not DHCP.&lt;br&gt;
For example, here's the default installation of &lt;em&gt;openSUSE MicroOS&lt;/em&gt; and, as you can see there's nothing listening on those ports. For that we'll use the command &lt;code&gt;ss -tunlp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7utqtockzx5fxwv6ip2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7utqtockzx5fxwv6ip2.png" alt="Port mapping check in openSUSE MicroOS proving that nothing is listening in ports 53 or 80" width="800" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By contrast, a default installation of &lt;em&gt;Fedora&lt;/em&gt; shows the service &lt;code&gt;systemd-resolved&lt;/code&gt; listening on ports 53.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mpg60wtjjggc6zbwswq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mpg60wtjjggc6zbwswq.png" alt="Port mapping check in Fedora showing systemd-resolved listening in port 53" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll leave that up for research if you need to disable the service, but there's plenty of documentation on the topic.&lt;/p&gt;
&lt;h3&gt;
  
  
  Provisioning needed files
&lt;/h3&gt;

&lt;p&gt;As we are going to use a &lt;em&gt;rootfull&lt;/em&gt; container, we need to place our Quadlets in &lt;code&gt;/etc/containers/systemd/&lt;/code&gt;. We will create a bunch of files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two &lt;em&gt;.volume&lt;/em&gt; files for the volumes Pi-Hole needs.&lt;/li&gt;
&lt;li&gt;One &lt;em&gt;.network&lt;/em&gt; file to configure the network for the container.&lt;/li&gt;
&lt;li&gt;One &lt;em&gt;.container&lt;/em&gt; file for the main container.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  pihole-dnsmasq.volume
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=PiHole dnsmasq Container Volume

[Volume]
Label=app=pihole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  pihole-pihole.volume
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=PiHole Data Container Volume

[Volume]
Label=app=pihole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  pihole.network
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=PiHole Container Network

[Network]
Label=app=pihole
DisableDNS=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  pihole.container
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=PiHole Service Container

[Container]
Label=app=pihole
ContainerName=pihole
HostName=pihole
Image=docker.io/pihole/pihole:latest
Network=pihole.network
Volume=pihole-pihole.volume:/etc/pihole
Volume=pihole-dnsmasq.volume:/etc/dnsmasq.d
AddCapability=NET_ADMIN
AutoUpdate=registry
PublishPort=53:53/tcp
PublishPort=53:53/udp
PublishPort=80:80/tcp
# Ignore the next 2 ones if not using pi-hole as dhcp server and not using https
PublishPort=67:67/udp
PublishPort=443:443/tcp

Environment=DNSMASQ_LISTENING=all
# Next variables to be customised
Environment=WEBPASSWORD="pihole"
Environment=TZ=Europe/Madrid
Environment=DNS1=208.67.222.222
Environment=DNS2=208.67.220.220
Environment=TEMPERATUREUNIT=c

[Service]
Restart=unless-stopped

[Install]
WantedBy=multi-user.target default.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Change the webUI password to something better, set your timezone and temperature unit, and choose an upstream DNS provider (the one above is &lt;a href="https://www.opendns.com/"&gt;OpenDNS&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Generate and run service
&lt;/h3&gt;

&lt;p&gt;Let's ask systemd to generate services from these files now. Run the following command as root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And lastly, run the service. As we said at the beginning this service is rootfull, so needs to be run as root. Just run the next command in a terminal and you should be done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl start pihole.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there are any failures you can check what happened with &lt;code&gt;systemctl status pihole.service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I have created &lt;a href="https://codeberg.org/franute/pihole-microos"&gt;a repository&lt;/a&gt; to hold this code for future use.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.while-true-do.io/podman-quadlets/"&gt;While-true-do: Podman-quadlets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html"&gt;Podman systemd unit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.redhat.com/sysadmin/quadlet-podman"&gt;Red Hat - Make systemd better for Podman with Quadlet &lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.redhat.com/sysadmin/multi-container-application-podman-quadlet"&gt;Red Hat - Deploying a multi-container application using Podman and Quadlet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://microos.opensuse.org/"&gt;openSUSE MicroOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>podman</category>
      <category>raspberrypi</category>
      <category>opensuse</category>
    </item>
    <item>
      <title>Linux Desktop: rolling releases and immutability</title>
      <dc:creator>Fran Torres</dc:creator>
      <pubDate>Fri, 01 Apr 2022 14:51:55 +0000</pubDate>
      <link>https://dev.to/franute/linux-desktop-rolling-releases-and-immutability-35b7</link>
      <guid>https://dev.to/franute/linux-desktop-rolling-releases-and-immutability-35b7</guid>
      <description>&lt;p&gt;It's been a long time since my last (and first!) post, but I felt like I had nothing to share. I would like to start writing more often but family obligations, work and impostor syndrome keeps pushing me away from it.&lt;br&gt;
Anyway, after writing the &lt;a href="https://dev.to/franute/fedora-33-btrfs-snapshots-37ig"&gt;btrfs and snapper setup for Fedora 33&lt;/a&gt; and comparing it to openSuse's btrfs setup I realized that while it works, it's not as convenient as it could be.&lt;/p&gt;

&lt;p&gt;I am lazy. I can follow complex processes for my work but not when dealing with my computer. I expect it to work with as little interaction as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should linux desktop look like (to me)?
&lt;/h2&gt;

&lt;p&gt;I've been a linux desktop user for quite a while now and year by year I've added more requirements to my idea of an ideal linux desktop. Right now I could consider it something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As stable as possible, with recovery options when an update goes wrong. This includes not having to look at the updates too much, just consider they will work. Otherwise having an integrated recovery system.&lt;/li&gt;
&lt;li&gt;At least the kernel should be as up to date as possible, so that if I buy new hardware I don't need to consider switching to another distro.&lt;/li&gt;
&lt;li&gt;Updated packages or not too old. Especially regarding desktop environments.&lt;/li&gt;
&lt;li&gt;Closer to stock components if possible. I've got tired of customizations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, the options I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debian: stable is not an option unfortunately and when I've used testing or sid I've always had to be vigilant about the upgrades to avoid problems from time to time.&lt;/li&gt;
&lt;li&gt;The Ubuntu team is doing a great job with the &lt;a href="https://wiki.ubuntu.com/Kernel/LTSEnablementStack"&gt;Enablement Stack&lt;/a&gt;, but you will still be running some software that's years old like the desktop. Running the latest version and upgrade every 6 months could be an option, but I was too used to Debian based distros and wanted a change.&lt;/li&gt;
&lt;li&gt;OpenSuse Leap since version 15 is interesting. Basically every 2 years the new release will bring new kernel, desktops, etc; which will be a somewhat slow rolling experience. But that's still 2 years of waiting for major component changes. I had good experiences with openSuse in the past, their implementation of btrfs and snapshots is probably the best, so Tumbleweed could be an option.&lt;/li&gt;
&lt;li&gt;Arch and Manjaro: I've ran Manjaro in the past, and having that testing repository where they basically hold arch updates for a while helps a lot. You have to delete customizations though.&lt;/li&gt;
&lt;li&gt;Fedora: looked like a good balance between up-to-date components and stability, but lacked a polished recovery mechanism. Then I discovered Silverblue and made me consider it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've been running both systems for a while in the last year and here are my thoughts.&lt;/p&gt;

&lt;h2&gt;
  
  
  openSuse Tumbleweed
&lt;/h2&gt;

&lt;p&gt;It is a great system, I can't deny it. The OpenQA is great and the amount of testing they do is amazing.&lt;br&gt;
There's &lt;a href="https://rootco.de/2020-02-10-regular-releases-are-wrong/"&gt;an article from Richard Brown&lt;/a&gt; explaining why regular release distributions are not an option for the desktop in his opinion, and while I subscribe pretty much all of his thoughts, because of the insane amount of software that can be considered part of any distro, it's almost impossible to ensure that everything will work.&lt;/p&gt;

&lt;p&gt;For example, with the recent upgrade to Gnome 42 there are some broken components like the share section in configuration or cheese showing weird color artifacts. Are they deal breakers? Probably not, but that brings &lt;strong&gt;me&lt;/strong&gt; uncertainty that maybe someday something I need breaks. The good thing is that they react quite quickly with fixes from upstream. The solution could have been just to not upgrade the system until Gnome 42.1 was released, but as I said I don't want to need to spend too much time checking what's being updated. I could have also rolled back and that would have helped because it's super easy in openSuse, but I was afraid that the next time I tried to upgrade, something else would break.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://microos.opensuse.org/"&gt;MicroOs&lt;/a&gt; looks super promising. They're not using any new technology, they're just changed the way the system does the updates and having the whole system as read only (over simplifying). But right now it's in early stages, the base image is incredibly small and requires more work in general, but once they have it, that is going to be the real Tumbleweed experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fedora Silverblue
&lt;/h2&gt;

&lt;p&gt;I'm not going to talk about immutable OSs now, there are quite a few talks in youtube, in blogs, etc. But basically the idea is that the core system will be read only, so if an update fails you can always go back to exactly the same state you were previously.&lt;/p&gt;

&lt;p&gt;The fact that the base system can't be modified by the user brings some challenges mainly to developers, but also regular users. Where do you install your development libraries? How do I install applications?&lt;/p&gt;

&lt;p&gt;For the first question &lt;a href="https://containertoolbx.org/"&gt;toolbx&lt;/a&gt; and &lt;a href="https://podman.io/"&gt;podman&lt;/a&gt; should be enough. Even more considering that most devs are getting used to containers nowadays.&lt;br&gt;
The second question in general can be answered with &lt;a href="https://flatpak.org/"&gt;flatpaks&lt;/a&gt;, which are a great way to have distribution independent applications that are always updated. In reality everyone is still trying to figure out how to put all these pieces together in the best way and sometimes you find a problem with a flatpak app that wouldn't happen with the distribution packaged version. Bear in mind that for basically every technology a flatpak app wants to use from the underlying system, some &lt;a href="https://docs.flatpak.org/en/latest/sandbox-permissions.html#portals"&gt;sort of bridge&lt;/a&gt; has to be built and not everything works right now.&lt;br&gt;
Sometimes you'll have no other choice than to install the native packages into the system (what's called layering in Silverblue), but you shouldn't if possible.&lt;/p&gt;

&lt;p&gt;I've been able to live with Silverblue up to the point where if I have to install linux to my parents I think I'll just use it. Flatpak experience has been good in general and it is improving every day. Hopefully developers will continue to adapt their flatpaks to build from source and not just use the packaged sources. Maybe this is just me being picky, but looks safer to me than just repackaging another format into flatpak.&lt;br&gt;
Did I have to layer any packages? Yes. Unfortunately the Spanish ID smartcard requires 2 packages to be installed as RPMs directly and that forces you to have a browser installed natively (not as flatpak), so I have Chromium for that and Firefox as flatpak. Scanners don't work via flatpak, so your scanning application must be layered too. And lastly the nvidia drivers for my laptop. They are the only pain point of this setup because if there's a new kernel version coming I know I have to hold it for a week or so until a new version of the drivers is released. But only keeping an eye on the kernel I guess it's a price I'll have to pay. In my desktop with AMD hardware I can blindly install updates though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;I can't find a reason right now why I would need to change to a different distribution. The upgrade process even with regular Fedora has become incredibly safe, painless and nicely integrated with Gnome Software. Do you know what's the only problem I have with it? Being able to wait when the new version is released. I've done 33 to 34 and 34 to 35 and it went fine, but it's always better if you wait a month until things have settled a bit. You could even stay one version behind and you would still get kernel updates, but having an easy way to rollback I'm not considering it.&lt;br&gt;
Having to layer some packages is not ideal definitely and you must adapt your workflow when developing, but I'm taking it as an opportunity to learn more about containers and use them more frequently professionally and in my free time.&lt;/p&gt;

&lt;p&gt;I also have the feeling that I might have not been fair with Ubuntu and I could follow the same flow of upgrading every 6 months to the new release (waiting for a month for it to stabilize); and also that judging Tumbleweed because of 2 small issues with an update is not great and I'm sorry about it, but I always feel way more stressed than I should when something breaks and I need to find some balance and especially some peace of mind that I won't need to fix my computer a random day.&lt;/p&gt;

</description>
      <category>silverblue</category>
      <category>tumbleweed</category>
      <category>linux</category>
    </item>
    <item>
      <title>Fedora 33 &amp; BTRFS Snapshots</title>
      <dc:creator>Fran Torres</dc:creator>
      <pubDate>Mon, 25 Jan 2021 16:04:05 +0000</pubDate>
      <link>https://dev.to/franute/fedora-33-btrfs-snapshots-37ig</link>
      <guid>https://dev.to/franute/fedora-33-btrfs-snapshots-37ig</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Update (27th June 2022): Since I wrote this I've switched to silverblue, which led me to forget a bit about btrfs snapshotting in Fedora because you get that for free with rpm-ostree. But if anybody reaches this I've found &lt;a href="https://sysguides.com/fedora-36-with-luks-full-disk-encryption/?utm_source=pocket_mylist"&gt;a more complete article&lt;/a&gt; describing the whole process for Fedora 36 and adding disk encryption that might be worth reading before mine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Why Fedora and Btrfs?
&lt;/h1&gt;

&lt;p&gt;Distrohopping has been a major pain when using GNU/Linux. Debian Stable has been my main choice for many years but it's not perfect when dealing with modern hardware. I came back to Fedora after many years not using it with Fedora 31 and found that the system has become way smoother and stable than I remembered. Even the upgrades have become an almost painless process.&lt;br&gt;
As great as Fedora is right now, I still have that feeling that something might fail someday and I wanted to have a recovery system configured. Fedora Silverblue looks terrific and I want to be ready to use it, but I'm not yet unfortunately (I still have to get my head around the one purpose containers and podman).&lt;br&gt;
Until then, btrfs and snapshots seem to be the best option for me.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fedora 33 base install
&lt;/h2&gt;

&lt;p&gt;The default Fedora 33 installation creates a disk structure like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One 1Gb ext4 partition for /boot&lt;/li&gt;
&lt;li&gt;One Btrfs volume for the rest of the space&lt;/li&gt;
&lt;li&gt;One Btrfs subvolume called "root" mounted at /&lt;/li&gt;
&lt;li&gt;One Btrfs subvolume called "home" mounted at /home
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ df -h | grep vda
/dev/vda2        35G  7.1G   28G  21% /
/dev/vda2        35G  7.1G   28G  21% /home
/dev/vda1       976M  183M  727M  21% /boot

[franute@localhost ~]$ sudo btrfs sub list /
ID 256 gen 175 top level 5 path home
ID 258 gen 179 top level 5 path root
ID 265 gen 28 top level 258 path var/lib/machines
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;My main volume is called /dev/vda2 and the root btrfs subvolume has ID 258. Write down your volume path and ID as we'll need them later.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install &amp;amp; configure snapper
&lt;/h2&gt;

&lt;p&gt;Next I will install snapper and the dnf plugin to generate pre and post transactions every time something is installed on the system and create a configuration for root.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo dnf install -y snapper python3-dnf-plugin-snapper
...
Complete!
[franute@localhost ~]$ sudo snapper --config=root create-config /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a subvolume called .snapshots in /, but we would rather have it at a different level to be able to mount it manually if needed and not nested under the "root" subvolume.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo btrfs sub list /
ID 256 gen 965 top level 5 path home
ID 258 gen 1038 top level 5 path root
ID 265 gen 966 top level 258 path var/lib/machines
ID 267 gen 1038 top level 258 path .snapshots
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete that subvolume and create the new one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;franute@localhost ~]$ sudo btrfs sub delete /.snapshots
Delete subvolume (no-commit): '//.snapshots'
[franute@localhost ~]$ sudo mkdir /.snapshots
[franute@localhost ~]$ sudo mkdir /mnt/btrfs
[franute@localhost ~]$ sudo mount /dev/vda2 /mnt/btrfs
[franute@localhost ~]$ cd /mnt/btrfs/
[franute@localhost btrfs]$ ls
home  root
[franute@localhost btrfs]$ sudo btrfs sub create snapshots
Create subvolume './snapshots'
[franute@localhost btrfs]$ ls
home  root  snapshots
[franute@localhost btrfs]$ cd ..
[franute@localhost mnt]$ sudo umount /mnt/btrfs
[franute@localhost mnt]$ sudo rmdir /mnt/btrfs/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's modify &lt;em&gt;/etc/fstab&lt;/em&gt; to mount the snapshots subvolume at boot.&lt;br&gt;
Change it to look similar to this (do not change your UUID, just focus on the options after ext4 or btrfs):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6 /                       btrfs   defaults     0 0
UUID=1d095325-9db9-4ac9-af8f-54d698535a55 /boot                   ext4    defaults        1 2
UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6 /home                   btrfs   subvol=home     0 0
UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6 /.snapshots             btrfs   subvol=snapshots     0 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have added a new entry at the end and changed the &lt;em&gt;subvol=root&lt;/em&gt; from the first entry to just &lt;em&gt;defaults&lt;/em&gt;. The next change is important. Do you remember that subvolume ID from before (258)? We need to tell the system that we want that to be considered the default when mounting /dev/vda2 if no subvolume is specified. There's also a problem with how Fedora configures the bootloader options by default as it will try to boot from this very specific subvol, making the rollbacks useless.&lt;br&gt;
Now, we will set that subvol as the default and remove a specific arg from the bootloader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo btrfs sub set-default 258 /
[franute@localhost ~]$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-5.8.15-301.fc33.x86_64"
args="ro rootflags=subvol=root rhgb quiet"
root="UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6"
initrd="/boot/initramfs-5.8.15-301.fc33.x86_64.img"
title="Fedora (5.8.15-301.fc33.x86_64) 33 (Workstation Edition)"
id="c6bb0926115440f9b9f721746626df37-5.8.15-301.fc33.x86_64"
index=1
kernel="/boot/vmlinuz-0-rescue-c6bb0926115440f9b9f721746626df37"
args="ro rootflags=subvol=root rhgb quiet"
root="UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6"
initrd="/boot/initramfs-0-rescue-c6bb0926115440f9b9f721746626df37.img"
title="Fedora (0-rescue-c6bb0926115440f9b9f721746626df37) 33 (Workstation Edition)"
id="c6bb0926115440f9b9f721746626df37-0-rescue"

[franute@localhost ~]$ sudo grubby --update-kernel=ALL --remove-args="rootflags=subvol=root"
[franute@localhost ~]$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-5.8.15-301.fc33.x86_64"
args="ro rhgb quiet"
root="UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6"
initrd="/boot/initramfs-5.8.15-301.fc33.x86_64.img"
title="Fedora (5.8.15-301.fc33.x86_64) 33 (Workstation Edition)"
id="c6bb0926115440f9b9f721746626df37-5.8.15-301.fc33.x86_64"
index=1
kernel="/boot/vmlinuz-0-rescue-c6bb0926115440f9b9f721746626df37"
args="ro rhgb quiet"
root="UUID=279ddd2e-e753-483f-8ea9-3a8eab37f5e6"
initrd="/boot/initramfs-0-rescue-c6bb0926115440f9b9f721746626df37.img"
title="Fedora (0-rescue-c6bb0926115440f9b9f721746626df37) 33 (Workstation Edition)"
id="c6bb0926115440f9b9f721746626df37-0-rescue"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now restart, if you now check the default subvolume for / you should see 258:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo btrfs sub get-default /
ID 258 gen 1093 top level 5 path root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Snapshots
&lt;/h2&gt;

&lt;p&gt;By default there will be no snapshots in the system, but as soon as you use dnf to install something from the command line, it will generate 2 snapshots. Let's see what happens installing &lt;em&gt;htop&lt;/em&gt; for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo snapper ls
 # | Type   | Pre # | Date | User | Cleanup | Description | Userdata
---+--------+-------+------+------+---------+-------------+---------
0  | single |       |      | root |         | current     |         
[franute@localhost ~]$ sudo dnf install -y htop
...
Complete!
[franute@localhost ~]$ sudo snapper ls
 # | Type   | Pre # | Date                         | User | Cleanup | Description                  | Userdata
---+--------+-------+------------------------------+------+---------+------------------------------+---------
0  | single |       |                              | root |         | current                      |         
1  | pre    |       | Sun 24 Jan 2021 18:58:37 WET | root | number  | /usr/bin/dnf install -y htop |         
2  | post   |     1 | Sun 24 Jan 2021 18:58:38 WET | root | number  | /usr/bin/dnf install -y htop |   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see there are 2 new snapshots now: 1 is a snapshot with the state of the system before htop was installed and 2 has the current state (right after it is installed).&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollback
&lt;/h2&gt;

&lt;p&gt;Let's say that for some reason we want to rollback our system to right before installing htop. We can do it with the rollback operation from snapper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo snapper rollback 1
Creating read-only snapshot of current system. (Snapshot 3.)
Creating read-write snapshot of snapshot 1. (Snapshot 4.)
Setting default subvolume to snapshot 4.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After restarting the system, you'll see that the default subvolume has changed now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ sudo btrfs sub list /
ID 256 gen 1212 top level 5 path home
ID 258 gen 1174 top level 5 path root
ID 265 gen 1060 top level 258 path root/var/lib/machines
ID 268 gen 1167 top level 5 path snapshots
ID 269 gen 1166 top level 268 path snapshots/1/snapshot
ID 270 gen 1110 top level 268 path snapshots/2/snapshot
ID 271 gen 1166 top level 268 path snapshots/3/snapshot
ID 272 gen 1212 top level 268 path snapshots/4/snapshot
[franute@localhost ~]$ sudo btrfs sub get-default /
ID 272 gen 1213 top level 268 path snapshots/4/snapshot
[franute@localhost ~]$ sudo snapper ls
 # | Type   | Pre # | Date                         | User | Cleanup | Description                  | Userdata     
---+--------+-------+------------------------------+------+---------+------------------------------+--------------
0  | single |       |                              | root |         | current                      |              
1  | pre    |       | Sun 24 Jan 2021 18:58:37 WET | root | number  | /usr/bin/dnf install -y htop |              
2  | post   |     1 | Sun 24 Jan 2021 18:58:38 WET | root | number  | /usr/bin/dnf install -y htop |              
3  | single |       | Sun 24 Jan 2021 19:01:22 WET | root | number  | rollback backup              | important=yes
4* | single |       | Sun 24 Jan 2021 19:01:22 WET | root |         | writable copy of #1          |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have in fact booted from snapshot 4, which is just a writeable copy of snapshot 1. The previous state is retained in snapshot 3, so you can even go back to that state.&lt;br&gt;
Now let's check if htop is installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[franute@localhost ~]$ htop
bash: htop: command not found...
Similar command is: 'top'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! It worked.&lt;br&gt;
Setting up Fedora to work with Snapper is not very different from any other distro. The only real problem was the kernel arguments. Once you get rid of that, it works as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Improvements and considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Nested subvolumes will not be considered in the snapshots, you can use that to ignore certain folders. /var/log is a good candidate in that case, here's my setup.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID 256 gen 21503 top level 5 path root
ID 257 gen 21516 top level 5 path home
ID 261 gen 18514 top level 256 path var/lib/portables
ID 266 gen 18514 top level 256 path var/lib/machines
ID 269 gen 21515 top level 256 path var/log
ID 270 gen 17131 top level 5 path snapshots
ID 310 gen 17129 top level 270 path snapshots/1/snapshot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There's a problem with Gnome Software and apparently software upgrades performed with it will not generate pre and post snapshots, I'd like to dig into this and see how it works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can tweak this &lt;em&gt;root&lt;/em&gt; configuration we created in several ways. For example you can enable or disable timed snapshots, define when are they cleaned up, how many to store in the system...&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>fedora</category>
      <category>btrfs</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
