<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<atom:link href="https://seanbehan.ca/posts/tag/linux/rss.xml" rel="self" type="application/rss+xml" />
		<title>Sean Behan — Linux</title>
		<link>https://seanbehan.ca/posts/tag/linux</link>
		<description>Posts tagged “Linux”.</description>
		<language>en-CA</language>
		<!-- RSS wants an address here and readers show the name beside it. -->
		<managingEditor>sean@seanbehan.ca (Sean Behan)</managingEditor>
		<webMaster>sean@seanbehan.ca (Sean Behan)</webMaster>
		<lastBuildDate>Sun, 13 Sep 2026 03:14:46 GMT</lastBuildDate>
		<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/usb-cable-testing</guid>
		<title><![CDATA[USB Cable Testing on Linux]]></title>
		<description><![CDATA[usbmon turns Wireshark into a cable tester, and finds retransmissions on cables that supposedly work.]]></description>
		<link>https://seanbehan.ca/posts/usb-cable-testing</link>
		<pubDate>Wed, 15 Apr 2026 07:11:06 GMT</pubDate>
		<category>Linux</category><category>test</category><category>USB</category><category>Wireshark</category>
		<content:encoded><![CDATA[<p>I was interested in testing my USB cables that I know work, but wanted to see if they had any retransmission going on.</p><p>Then today, I found out Linux has a kernel module that allows you to &quot;monitor&quot; usb interfaces. Like... using wireshark.</p><p>I won&#x27;t explain how to set up wireshark for your distro, that&#x27;s for you to figure out.</p><p>Once you have wireshark set up, you just <code>sudo modprobe usbmon</code> then <code>lsusb</code>.</p><p>Find the USB interface you want to monitor in the list, then select it when starting wireshark (gui).</p><p>That&#x27;s about it... you can filter like this:</p><pre><code>usb.urb_status != 0 &amp;&amp; !(usb.urb_status == -115)</code></pre><p>Short post, but hope this helps you test your own USB cables for any errors that aren&#x27;t shown in dmesg, like failed packets.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/quadlets</guid>
		<title><![CDATA[Podman Quadlets]]></title>
		<description><![CDATA[Quadlets describe a container as a systemd unit, so systemd owns the lifecycle instead of Podman.]]></description>
		<link>https://seanbehan.ca/posts/quadlets</link>
		<pubDate>Fri, 28 Mar 2025 14:39:58 GMT</pubDate>
		<category>containers</category><category>Linux</category><category>Podman</category><category>Quadlet</category><category>systemd</category>
		<content:encoded><![CDATA[<h3>What are Quadlets?</h3><p>In this post I&#x27;ll show you what a quadlet is and how you can use it to manage your containers.</p><p>Quadlets are a new way to manage containers using systemd. They are a new format for systemd units that allow you to manage containers using systemd.</p><h3>Container Quadlets</h3><p>Here&#x27;s an example of a container quadlet.</p><pre><code class="language-systemd">[Container]
Image=docker.io/library/alpine:latest
Exec=sleep infinity
AutoUpdate=registry</code></pre><p>If you put this in ~/.config/containers/systemd/alpine.container you can start it with <code>systemctl --user start alpine</code> and it will start a new container.</p><p>Just make sure to <code>systemctl --user daemon-reload</code> to reload the systemd daemon after you create the quadlet. You have to do this every time, I won&#x27;t repeat this throughout the blog post.</p><h3>Pod Quadlets</h3><p>You can also use quadlets to manage pods. Here&#x27;s an example of a pod quadlet.</p><pre><code class="language-systemd">[Pod]</code></pre><p>Yep, that&#x27;s it. If you put it in <code>~/.config/containers/systemd/mypod.pod</code> you can start it with <code>systemctl --user start mypod-pod</code> and it will start a new pod.</p><p>But the best part is this. If you want to add a container to a pod all you have to do is this.</p><pre><code class="language-systemd">[Container]
Image=docker.io/library/alpine:latest
Exec=sleep infinity
AutoUpdate=registry
Pod=mypod.pod</code></pre><p>Now when you start <code>mypod-pod</code> it will start the container as well.</p><h3>Dependencies</h3><p>You can add dependencies.</p><pre><code class="language-systemd">[Unit]
After=alpine.service

[Container]
Image=docker.io/library/archlinux:latest
Exec=sleep infinity
AutoUpdate=registry
Pod=mypod.pod</code></pre><p>Now archlinux will start after alpine.</p><p>There are even more options. You can start .kube, .network, and .build quadlets too and they can depend on each other. See the <a href="https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html">docs </a>for more info!</p><p>---</p><h3>Example: Nginx and Certbot</h3><p>Okay so now lets run something useful :) How about an nginx container and a certbot container to get a certificate for it?</p><h3>Nginx Container</h3><p>First lets create a directory to hold our files.</p><pre><code class="language-sh">mkdir -p ~/.config/containers/systemd/www</code></pre><p>Next we create a quadlet for our nginx container.</p><pre><code class="language-systemd">[Container]
Image=docker.io/nginx:latest
PublishPort=80:80
PublishPort=443:443
AutoUpdate=registry
Volume=./www:/usr/share/nginx/html</code></pre><p>This will run a web server for us. If you aren&#x27;t root, you&#x27;ll need to enable unprivleged ports.</p><pre><code class="language-sh">sudo sysctl net.ipv4.ip_unprivileged_port_start=0</code></pre><p>Now we can start it with <code>systemctl --user start nginx</code> and it will start a new container.</p><p>If you browse to <code>http://localhost</code> you should see the nginx welcome page.</p><h3>Certbot Container</h3><p>Now we need to get a certificate for it. We can use certbot for this.</p><pre><code class="language-systemd">[Container]
Image=docker.io/certbot/certbot:latest
Volume=letsencrypt:/etc/letsencrypt
Volume=./www:/mnt
Exec=certonly --webroot --webroot-path /mnt --agree-tos --email your@email.com -d your.domain.com
AutoUpdate=registry</code></pre><p>Make sure to replace your@email.com and your.domain.com with your own email and domain.</p><p>Then start the container with <code>systemctl --user start certbot</code> and it will get a certificate for you.</p><h3>Nginx with SSL</h3><p>Now you can use the certificate in your nginx container.</p><pre><code class="language-systemd">[Container]
Image=docker.io/nginx:latest
PublishPort=80:80
PublishPort=443:443
AutoUpdate=registry
Volume=letsencrypt:/etc/letsencrypt</code></pre><p>That&#x27;s great, but now we need to configure nginx to use the certificate. We can do this by adding a volume for the configuration file.</p><pre><code class="language-systemd">[Container]
Image=docker.io/nginx:latest
PublishPort=80:80
PublishPort=443:443
AutoUpdate=registry
Volume=letsencrypt:/etc/nginx/certs
Volume=./nginx.conf:/etc/nginx/conf.d</code></pre><p>Along with a configuration file for nginx.</p><pre><code class="language-nginx">server {
    listen 443 ssl;
    server_name your.domain.com;

    ssl_certificate /etc/nginx/certs/live/your.domain.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/live/your.domain.com/privkey.pem;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}</code></pre><p>Again, make sure to replace your.domain.com with your own domain.</p><p>Now you can start the container with <code>systemctl --user start nginx</code> and it will start a new container with the certificate. You can verify this by going to <code>https://your.domain.com</code>.</p><p>Now you have a web server with HTTPS.</p><h3>Automatic Certificate Renewal</h3><p>If you want to renew your certificate automatically it&#x27;s as simple as this.</p><pre><code class="language-systemd">[Container]
Image=docker.io/certbot/certbot:latest
Exec=renew
AutoUpdate=registry
Volume=letsencrypt:/etc/letsencrypt</code></pre><p>Now you can create a timer for it in <code>~/.config/systemd/user/certbot.timer</code>.</p><pre><code class="language-systemd">[Unit]
Description=Renew Certbot certificates

[Timer]
OnCalendar=Sun 00:00:00
Persistent=true
Unit=certbot.service

[Install]
WantedBy=timers.target</code></pre><p>Now you enable the timer.</p><pre><code class="language-sh">systemctl --user enable --now certbot.timer</code></pre><p>Now your certificate will be renewed every Sunday at midnight.</p><p>That&#x27;s it! Now you have a web server with HTTPS and a certificate that will be renewed automatically.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/ostree</guid>
		<title><![CDATA[Using Ostree for file snapshots]]></title>
		<description><![CDATA[Ostree is not just for Silverblue. Using it as a content-addressed snapshot store for your own files.]]></description>
		<link>https://seanbehan.ca/posts/ostree</link>
		<pubDate>Sat, 27 May 2023 11:47:26 GMT</pubDate>
		<category>backup</category><category>Linux</category><category>OSTree</category>
		<content:encoded><![CDATA[<h3>Introduction</h3><p>Ostree is the software that allows rpm-ostree in Fedora Silverblue to keep snapshots of previous deployments and do incremental updates, but did you know it can also be used to keep snapshots of your own files? It&#x27;s actually quite easy once it&#x27;s all set up.</p><p>For this I would strongly suggest you use root for your ostree. Although you can use it without, you will be able to use files that regular users can&#x27;t use such as hardlinks if you&#x27;re root, which will speed up incremental snapshots very much.</p><h3>Initializing the Ostree Repository</h3><p>First you&#x27;ll want to create your inital ostree. Do this in a new folder, on a drive with lots of free space for the files you want to snapshot. You&#x27;ll need as much free space as all the files you want to snapshot.</p><pre><code class="language-sh">mkdir tree
sudo ostree init --repo=tree</code></pre><h3>Committing and Restoring Files</h3><p>Next you can start committing files to your new tree. Be sure to check the man pages for <code>ostree-commit</code> and <code>ostree-init</code>.</p><pre><code class="language-sh">sudo ostree commit --repo=tree --branch=master $PWD/dir</code></pre><p>Keep in mind you cannot commit individual files, only entire directories at a time. Now when you change something inside <code>/dir</code> you can commit again with the exact same command and you will have both copies in your ostree. To restore the original copy you can then use <code>ostree-checkout</code>.</p><pre><code class="language-sh">ostree refs --repo=tree master</code></pre><p>This will show you a list of all your commits. Now choose the one you want to restore.</p><pre><code class="language-sh">ostree checkout --repo=tree --union your-commit-sha dir</code></pre><h3>Important Considerations</h3><p>Make sure you check <code>ostree -h</code> for a list of ostree commands and read each of their man pages if you want to use them fully.</p><p>I use this on a filesystem that is already a RAID1. Make sure you keep proper backups, ostree can create snapshots but it won&#x27;t help you if your entire drive fails.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/flatpak-mesa</guid>
		<title><![CDATA[Flatpak Mesa Git]]></title>
		<description><![CDATA[Swapping the Flatpak Mesa runtime for mesa-git so a new AMD card stops falling back to software OpenGL.]]></description>
		<link>https://seanbehan.ca/posts/flatpak-mesa</link>
		<pubDate>Thu, 25 May 2023 17:48:28 GMT</pubDate>
		<category>graphics</category><category>Linux</category>
		<content:encoded><![CDATA[<h3>The Problem</h3><p>If you&#x27;ve switched to Flatpak for gaming you may notice that Mesa is sometimes a little bit old. The issue I had myself was that my 6000 series AMD graphics card didn&#x27;t have up to date graphics drivers, resulting in OpenGL games not running on the graphics card, but rather the CPUs OpenGL implementation, which made games such as CS:GO and Minecraft run at 5 or 10 FPS.</p><h3>The Solution</h3><p>To get the latest Mesa git on Flatpak you can install it like this:</p><pre><code class="language-sh">flatpak install org.freedesktop.Platform.GL.mesa-git org.freedesktop.Platform.GL32.mesa-git</code></pre><p>This will allow you to install the latest Mesa graphics drivers to allow applications to detect hardware properly and run better. Make sure when you are prompted for a version of Mesa to install you choose the latest version number that doesn&#x27;t have &quot;beta&quot; at the end.</p><h3>Usage</h3><p>Once you&#x27;ve done this you can run your Flatpak like this to use Mesa git.</p><pre><code class="language-sh">FLATPAK_GL_DRIVERS=mesa-git flatpak run com.valvesoftware.Steam</code></pre><p>You can also export <code>FLATPAK_GL_DRIVERS=mesa-git</code> in your <code>.bashrc</code> or <code>.profile</code> to use Mesa git for all Flatpak applications. This may cause issues though, and I&#x27;d personally advise you only use it when it&#x27;s needed.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/btrfs</guid>
		<title><![CDATA[BTRFS RAID1 and how to fix it]]></title>
		<description><![CDATA[Setting up a two-disk BTRFS RAID1 for a Steam library, and repairing it when a drive starts throwing errors.]]></description>
		<link>https://seanbehan.ca/posts/btrfs</link>
		<pubDate>Tue, 23 May 2023 14:39:58 GMT</pubDate>
		<category>backup</category><category>Linux</category><category>RAID</category>
		<content:encoded><![CDATA[<h3>BTRFS RAID1 Setup</h3><p>I mentioned in my previous post that I use an external drive to keep my Steam games on. In an attempt to not have to re-download hundreds of gigabytes of games I keep them on a RAID1 with 2x5TB drives that I use BTRFS to manage. In this post I&#x27;m going to outline how I set it all up, and how I manage it when issues arise.</p><h3>Formatting Drives</h3><p>First of all I had to format the drives, so I made sure they were empty and everything was backed up. Don&#x27;t do this unless you know for sure that all the data on all your drives is backed up somewhere else, or you want to delete it permanently.</p><p>Okay so the commands are easy, you just have to make sure you&#x27;re using the right ones as not to lose your data. Don&#x27;t run these commands without understanding what they do. Replace \_ with your drive letter. A lot of these commands need to be run with root, make sure to either elevate to root (<code>sudo -s</code>) or prepend the commands with <code>sudo</code>.</p><pre><code class="language-sh">lsblk</code></pre><pre><code class="language-sh">mkfs.btrfs /dev/sd_1
mkfs.btrfs /dev/sd_1</code></pre><h3>Creating the RAID1 Array</h3><p>Now you can mount the newly formatted drives to a single RAID1.</p><pre><code class="language-sh">mount /dev/sd_1 /mnt
btrfs device add /dev/sd_1 /mnt
btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt</code></pre><p>The last command might take a little bit of time, but once it&#x27;s finished your drives will be all ready to be used.</p><h3>Managing the Array</h3><p>Now if you need to swap out a drive, add another, or you unplug one when it&#x27;s writing you can simply balance again and btrfs should be able to balance back onto the drive.</p><pre><code class="language-sh">btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt</code></pre><p>You can view the status of the balance using:</p><pre><code class="language-sh">btrfs balance status</code></pre><p>You can remove a drive or add another using:</p><pre><code class="language-sh">btrfs device remove /dev/sd_1
btrfs device add /dev/sd_1</code></pre><p>Just make sure you balance right afterwards (which will take a VERY long time if you have lots of data, beware)</p><pre><code class="language-sh">btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt</code></pre>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/flatpak</guid>
		<title><![CDATA[Using any Linux Distribution with Flatpak]]></title>
		<description><![CDATA[Flatpak makes the host distribution almost irrelevant, down to proprietary codecs and games on musl Alpine.]]></description>
		<link>https://seanbehan.ca/posts/flatpak</link>
		<pubDate>Tue, 23 May 2023 13:49:32 GMT</pubDate>
		<category>graphics</category><category>Linux</category>
		<content:encoded><![CDATA[<h3>Introduction</h3><p>I was using Fedora Silverblue for nearly a year before I realized I had been using Flatpak&#x27;s for nearly all my software, which mind you isn&#x27;t much, but I can use Firefox, Chrome, and play any video game I want using Flatpak alone so it makes sense for me.</p><p>To get this working all you need is a distribution where you can install Flatpak. I&#x27;m using Alpine Linux edge with musl and even that works. Using Flatpak allows me to use proprietary video and audio codecs in Firefox and Chrome since musl doesn&#x27;t support those codecs as of right now.</p><h3>Setting up Flatpak</h3><p>If your distribution doesn&#x27;t already come with FlatHub like Alpine, you&#x27;ll need to <a href="https://flatpak.org/setup/">add it</a>.</p><pre><code class="language-sh">flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo</code></pre><h3>Installing Applications</h3><p>This will allow you access to the entire Flatpak library. You can search for software using:</p><pre><code class="language-sh">flatpak search steam</code></pre><p>Then install using:</p><pre><code class="language-sh">flatpak install com.valvesoftware.Steam</code></pre><p>Make sure you periodically update your Flatpak&#x27;s as well using:</p><pre><code class="language-sh">flatpak update</code></pre><h3>Steam and Gaming</h3><p>For Steam to work you&#x27;ll likely need to install some other Flatpak&#x27;s as well, but once they&#x27;re installed all your other gaming Flatpak&#x27;s should &quot;just work&quot;.</p><pre><code class="language-sh">flatpak install com.valvesoftware.Steam.CompatibilityTool.Proton</code></pre><p>You might also want to install your distribution&#x27;s <code>steam-devices</code> package if you want to use a game controller.</p><pre><code class="language-sh">sudo apt-get install steam-devices # ubuntu / debian
doas apk add steam-devices         # alpine</code></pre><h3>Managing Permissions with Flatseal</h3><p>I like to give the Steam Flatpak access to my external drives so I can keep games there instead of on my hard drive. To do this I simply install Flatseal and use Flatseal to give rw (read+write) access to the directory where my drives mount to.</p><pre><code class="language-sh">flatpak install com.github.tchx84.Flatseal</code></pre><h3>Google Chrome</h3><p>Next if you want to install Google Chrome.</p><pre><code class="language-sh">flatpak install com.google.Chrome</code></pre><h3>Conclusion</h3><p>That&#x27;s all you have to do, then you would have Google Chrome installed.</p><p>Flatpak uses it&#x27;s own runtime, remember to update all your Flatpak&#x27;s periodically with <code>flatpak update</code> to avoid security vulnerabilities and other issues.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/8814au</guid>
		<title><![CDATA[Fedora 8814au Kernel Module Compilation]]></title>
		<description><![CDATA[Compiling the out-of-tree 8814au driver for an Alfa AC1900 on Fedora, kernel headers and all.]]></description>
		<link>https://seanbehan.ca/posts/8814au</link>
		<pubDate>Thu, 12 May 2022 19:21:37 GMT</pubDate>
		<category>development</category><category>kernel</category><category>Linux</category>
		<content:encoded><![CDATA[<p>For my wireless card, the Alfa AC1900, I had to compile the module to get it to work on Linux since it wasn&#x27;t already part of the kernel.</p><h3>Prerequisites</h3><p>To do this you will need:</p><ol><li><code>make</code> and <code>gcc</code> or <code>clang</code></li><li><code>kernel-debug-devel</code> package</li><li>sudo permission to <code>insmod</code> the compiled module</li></ol><p>This[^1] is the only one I found that worked for me on the latest stable linux kernel, which as of today on Fedora is 5.17.6.</p><h3>Kernel Header Installation</h3><p>First you need to install the kernel development header package.</p><pre><code># Fedora
sudo dnf install kernel-debug-devel

# Ubuntu
sudo apt install linux-headers-$(uname -r)</code></pre><p>[^2]</p><h3>Building and Loading the Module</h3><p>Next you need to make the module.</p><pre><code>git clone https://github.com/morrownr/8814au.git
cd 8814au</code></pre><p>Now simply <code>make</code> the module using the <code>make</code> command and use <code>insmod</code> to load it.</p><pre><code>make -j16
sudo sh -c "modprobe cfg80211; insmod /home/codebam/8814au/8814au.ko"</code></pre><p>If everything worked successfully, you should now have a loaded 8814au module that you can use along with your wireless card to connect to WiFi.</p><p>[^1]: https://github.com/morrownr/8814au</p><p>[^2]: https://www.tecmint.com/install-kernel-headers-in-ubuntu-and-debian</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/podman-systemd</guid>
		<title><![CDATA[Podman Auto Updating Systemd Services]]></title>
		<description><![CDATA[podman generate systemd plus an autoupdate label: containers that start on boot and update themselves.]]></description>
		<link>https://seanbehan.ca/posts/podman-systemd</link>
		<pubDate>Thu, 23 Sep 2021 14:34:43 GMT</pubDate>
		<category>Docker</category><category>Linux</category><category>Podman</category>
		<content:encoded><![CDATA[<h3>Introduction</h3><p>Podman[^1] has a nice feature called <code>generate</code> that lets you generate different kinds of configuration files for starting pods. One that I use often is <code>podman generate systemd</code> which generates a new user service that can be started with <code>systemctl --user start container-yourcontainer.service</code> or enabled.</p><h3>Auto-Updating Containers</h3><p>If you want your container to auto update you can simply pass it the flag <code>--label &quot;io.containers.autoupdate=registry&quot;</code> when you&#x27;re creating it. The systemd service will automatically pull the latest versions of containers before starting them. You can manually update your container images now using <code>podman auto-update</code>.</p><p>If you want to update your images on a schedule you can enable the <code>podman-auto-update.timer</code> using `systemctl --user enable --now podman-auto-update.timer` which will auto update your containers every Monday morning.[^2]</p><h3>Kubernetes YAML Generation</h3><p>You can also generate a Kubernetes YAML configurations using `podman generate kube`. This can then be loaded in Kubernetes to run your containers.</p><p>[^1]: https://podman.io</p><p>[^2]: https://fedoramagazine.org/auto-updating-podman-containers-with-systemd/</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/podman-crun</guid>
		<title><![CDATA[Podman crun and cgroups v2]]></title>
		<description><![CDATA[Getting Podman onto cgroups v2 and crun on distributions that still default to cgroups v1 and runc.]]></description>
		<link>https://seanbehan.ca/posts/podman-crun</link>
		<pubDate>Sun, 19 Sep 2021 03:09:02 GMT</pubDate>
		<category>Docker</category><category>Linux</category><category>Podman</category>
		<content:encoded><![CDATA[<h3>Introduction</h3><p>Podman[^1] is a container management software similar to Docker that can run OCI containers as regular users (not root) by using container management libraries such as crun or runc, and cgroups v1 or v2. It can be used as a drop-in replacement for Docker and supports docker-compose using podman-compose.</p><p>Unfortunately for some distributions after installing podman the operating system defaults to cgroups v1 and runc, not cgroups v2 and crun. As was the case on Rocky Linux for me.</p><h3>Switching to crun</h3><p>First we can switch to crun instead of runc by installing crun with our package manager. It was already installed for me, but on Fedora you would use `sudo dnf install crun` Then you can edit the file <code>/usr/share/containers/containers.conf</code> and change the line <code>runtime = &quot;runc&quot;</code> to <code>runtime = &quot;crun&quot;</code>. Now you can verify that you&#x27;re using crun with <code>podman info | grep crun</code>.</p><pre><code>name: crun
package: crun-0.20.1-1.module+el8.4.0+643+525e162a.x86_64
path: /usr/bin/crun
  crun version 0.20.1</code></pre><h3>Enabling cgroups v2</h3><p>Now the harder part was enabling cgroups v2. Luckily I found a <a href="https://github.com/containers/podman/issues/9410#issuecomment-785840320">comment </a>on a GitHub issue outlining the steps you need to complete to get cgroups v2 to work.</p><p>First we can enable it in the kernel with</p><pre><code>sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"</code></pre><p>Then we can enable linger. This will also allow our containers to remain running after logging out.</p><pre><code>sudo loginctl enable-linger codebam</code></pre><p>Then the last step which made everything work for me is to set the <code>pid_limit=0</code>. For me it was in <code>/usr/share/containers/containers.conf</code> instead of <code>/etc/containers/</code>.</p><h3>Verification</h3><p>Now you can reboot. <code>podman info | grep cgroup</code> should say</p><pre><code>cgroupControllers: []
cgroupManager: systemd
cgroupVersion: v2</code></pre><p>Now we&#x27;re using cgroups v2 and crun.</p><p>[^1]: https://podman.io</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/silverblue</guid>
		<title><![CDATA[Fedora Silverblue]]></title>
		<description><![CDATA[Why an atomic rpm-ostree desktop stuck: updates that check out like git, and roll back the same way.]]></description>
		<link>https://seanbehan.ca/posts/silverblue</link>
		<pubDate>Sat, 13 Feb 2021 20:21:43 GMT</pubDate>
		<category>Linux</category>
		<content:encoded><![CDATA[<h3>Introduction</h3><p>Over the past few months I experimented with some new Linux distributions. Here I&#x27;ll show you the one I&#x27;m currently using and why I think it&#x27;s great.</p><img src="https://seanbehan.ca/img/20210213_15h31m29s_grim.webp" alt="Fedora Silverblue desktop screenshot" width="2560" height="1440" /><h3>Atomic Updates and Rollbacks</h3><p>Fedora Silverblue is what&#x27;s known as an Atomic operating system. On Fedora Silverblue every update is checked out similar to how git checks out a new reference. If you want to install packages into the base image you can use rpm-ostree install like you usually would, the only difference is that you need to reboot to boot into your new base system reference.</p><h3>Toolbox for Development</h3><p>If you don&#x27;t want to reboot there is a better way though. Instead of layering packages into your base image you can use a tool called toolbox which is simply a wrapper around podman for creating containers with the current Fedora image.</p><p>You can use toolbox enter and install and run any software as well as access files inside your home directory.</p><h3>Rebasing and Customization</h3><p>If at some point you do updates and your system doesn&#x27;t boot, you don&#x27;t have to worry. You can simply reboot and choose the last working base image and your system will boot up as normal, allowing you to fix any breakage.</p><p>Silverblue is so much more powerful than that though. You can rebase your entire system on different base images or Fedora versions. Now instead of installing your new desktop environment and risk breaking your operating system you can do an <code>rpm-ostree rebase</code> and rebase on another desktop environment. I used this to rebase on an image from <a href="https://fedoraproject.org/atomic-desktops/kinoite/">Kinoite</a> called base which just includes all the base packages and no desktop environment. Then I installed my window manager of choice and it&#x27;s dependencies. Now I have a fully modular Fedora installation along with <a href="https://swaywm.org/">Sway</a> and all the dependencies I need to use it.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/alpine-lbu</guid>
		<title><![CDATA[Alpine Linux LBU]]></title>
		<description><![CDATA[Alpine can commit changes back onto its own live ISO. Using LBU to build a persistent maintenance drive.]]></description>
		<link>https://seanbehan.ca/posts/alpine-lbu</link>
		<pubDate>Fri, 04 Dec 2020 03:09:46 GMT</pubDate>
		<category>Alpine</category><category>Linux</category>
		<content:encoded><![CDATA[<h3>What is LBU?</h3><p>Alpine Linux has a cool feature called LBU that lets you create a backup on top of the Live ISO. These backups are called local backups.</p><p>I plan on using LBU as a system maintenance drive. It allows you to save changes you make to the Live ISO and restore them automatically when you boot the next time.</p><h3>Setup and Committing</h3><p>To set up LBU I booted the Alpine Linux ISO, ran <code>setup-alpine</code>, mounted my drive to <code>/media/alpine_usb</code> and when I got to the disk selection I selected no disk, and <code>alpine_usb</code> as where to store the configs, and the default for cache.</p><p>Now when I make changes in the Alpine Linux Live ISO I can commit them.</p><p>To see what is being committed I first check <code>lbu status</code> which lists all the files being added or removed, then <code>lbu commit</code> to commit the changes.</p><p>When I was rebooting I had an issue where the drive would automount itself to /media/sdb and then wouldn&#x27;t work with lbu when I wanted to commit or check the status because it was already mounted. To fix this I just had to `umount /dev/sdb` on boot and then lbu worked as expected.</p><h3>Caching and Configuration</h3><p>To use cache you have to mount it to <code>/media/alpine_usb</code> so that it can write the cache files when you&#x27;re installing packages. I want this because it makes reinstalling my packages on reboot a lot faster, they can just be loaded from cache instead of from online repositories.</p><p>Upon reboot I had to reinstall all the packages I had installed using `apk upgrade` but since the cache is there it just installs everything really quickly.</p><p>I uncommented and changed the number of backups in <code>/etc/lbu/lbu.conf</code> to 20 so that I would be able to revert up to 20 commits in case I broke my configs.</p><p>I see Alpine LBU as a good way to keep a backup of changes to the ISO so it could be used as a system recovery disk with the tools that are needed.</p>]]></content:encoded>
	</item>
<item>
		<guid isPermaLink="true">https://seanbehan.ca/posts/2fa-everything</guid>
		<title><![CDATA[2FA Everything]]></title>
		<description><![CDATA[Moving a password store between pass and KeePass, and getting two YubiKeys to guard all of it.]]></description>
		<link>https://seanbehan.ca/posts/2fa-everything</link>
		<pubDate>Fri, 04 Dec 2020 01:38:10 GMT</pubDate>
		<category>Linux</category><category>security</category>
		<content:encoded><![CDATA[<h3>Password Management</h3><p>I&#x27;ll start this post by saying one thing. Are you SURE you want to wipe that yubikey? I spent the last 2 weeks redoing my entire password manager. Silly me forgot that I had my passwords encrypted using the yubikey I wiped to create new PGP keys.</p><p>Anyways over the past week or two I moved all my passwords from <a href="https://www.passwordstore.org/">pass</a> into <a href="https://keepass.info/">keepass </a>and then back into pass when keepass didn&#x27;t meet all my needs for a password manager. KeePass supported using yubikeys for decryption, but not more than one at a time. If I were to lose the key I would get permanently locked out.</p><p>Features I want in my password manager:</p><ul><li>2FA for password manager decryption</li><li>Mobile and desktop apps</li><li>Secure encryption</li></ul><p>What I settled on was this. I bought myself a [Yubikey 5C NFC](https://www.yubico.com/ca/product/yubikey-5c-nfc/) to go alongside my previous <a href="https://www.yubico.com/ca/product/yubikey-5c/">Yubikey 5C</a>. There might be better alternatives, but this is the one I purchased. This one had NFC and was convenient for accessing passwords on my phone and laptop.</p><h3>Yubikey PGP Key Generation</h3><p>To generate my PGP keys I actually generated them on the Yubikey itself, this way the private key never touches the laptop I used to generate the key.</p><pre><code>$ gpg --card-edit
gpg/card&gt; admin
gpg/card&gt; key-attr
gpg/card&gt; generate</code></pre><p>The <code>key-attr</code> command lets you choose the type and size of key you&#x27;re generating on the device. I used RSA 4096 for my Yubikey 5C and ed25519 for the Yubikey 5C NFC. I can&#x27;t use RSA or larger keys if I want to be able to use it with NFC.</p><p>I backed up my revokal certificates that were put in the <code>~/.gnupg/</code> directory as indicated after they were generated, and I exported and backed up the public keys, then I uploaded the keys to a keyserver.</p><pre><code>gpg --export --armor 0F6D5021A87F92BA &gt; 0F6D5021A87F92BA.asc
gpg --send-keys 0F6D5021A87F92BA

gpg --export --armor F9BC985B3BF972C7 &gt; F9BC985B3BF972C7.asc
gpg --send-keys F9BC985B3BF972C7</code></pre><p>I started putting passwords into pass using `pass init 0F6D5021A87F92BA F9BC985B3BF972C7`. That lets me encrypt to both Yubikeys at once. Now if I lose or accidentally wipe one of the Yubikeys again the other will be able to decrypt my passwords. I also signed the keys with each other, just to show that both are valid if one were to be lost.</p><p>While I did all this I thought I might as well enable 2FA using both the Yubikeys on every account that supported it. Google actually has something cool called Advanced Protection which allows you to set up your account with 2 yubikeys to login with, so I enabled that for my Google account.</p><p>I downloaded the [password store](https://play.google.com/store/apps/details?id=dev.msfjarvis.aps) Android app for my phone, along with <a href="https://www.openkeychain.org/">Openkeychain</a>.</p><p>This part wasn&#x27;t too hard to set up, I just searched for my key on the keyserver that I just uploaded it to, then imported it. I went through the setup to add a security token and imported it so that it was recognized as one of my keys.</p><h3>Git and Password Store Sync</h3><p>At this point I set up my password store with git to use for syncing. I set it up on some mirrors just in case one went down, and I backed it up to Nextcloud.</p><pre><code>git remote add all git@seanbehan.dev:pass
git remote set-url --add --push all git@seanbehan.dev:pass
git remote set-url --add --push all git@git.sr.ht:~codebam/pass
git remote set-url --add --push all git@git.maych.in:codebam/password-store
git push --set-upstream all master</code></pre><p>I actually set up git on my own server here too. To do this I added a new user named <code>git</code> and added my ssh keys to it, then inside it&#x27;s home directory I made git repositories to push to using.</p><pre><code>mkdir pass
cd pass
git init --bare</code></pre><h3>Yubikey for SSH</h3><p>I generated a new SSH key from within the password store app and used that for authentication from my phone. On my laptop I set up gpg-agent with ssh support so that I could use my yubikey as an SSH key as well as a PGP key.</p><h3><code>~/.bashrc</code></h3><pre><code class="language-sh">export GPG_TTY="$(tty)"
export SSH_AUTH_SOCK="/run/user/$UID/gnupg/S.gpg-agent.ssh"
gpg-connect-agent updatestartuptty /bye &gt; /dev/null</code></pre><h3><code>~/.gnupg/gpg.conf</code></h3><pre><code class="language-conf">use-agent</code></pre><p>Then I used <code>ssh-add -L</code> to show my public SSH key for each yubikey to put on the server.</p><p>I used pass for 2FA as well because the password store app supports that. I just scanned the code and installed <code>pass-otp</code> on Fedora to get support for OTPs.</p><p>I installed the <a href="https://github.com/passff/passff">PassFF</a> Firefox extention to get support for pass in my browser, and turned on autofill on my phone so that it can autofill everywhere.</p><p>I set up git to sign all my commits so that it shows that my commits are signed and valid.</p><pre><code>git config --global user.signingkey 0F6D5021A87F92BA
git config --global commit.gpgsign true</code></pre><h3>System-level U2F Authentication</h3><p>As an extra layer of security on Fedora I installed the <code>pam-u2f</code> package on and generated U2F logins.</p><pre><code>sudo pamu2fcfg -uroot &gt;&gt; /etc/u2f_mappings</code></pre><p>I ran it once for each key, then opened the file and edit it so it looked like this.</p><h3>Before</h3><pre><code>root:key1root:key2</code></pre><h3>After</h3><pre><code>root:key1:key2
codebam:key1:key2</code></pre><p>In <code>/etc/pam.d/system-auth</code> I added a line to the very top above all the other <code>auth</code>.</p><pre><code>auth	    required              pam_u2f.so authfile=/etc/u2f_mappings</code></pre><p>I added the same line to <code>/etc/pam.d/su</code> as well so that my user and root requires a yubikey to <code>su</code>.</p><p>This makes it so that <code>sudo</code>, <code>su</code>, and logging in through a <code>getty</code> (not in GDM for some reason, but I haven&#x27;t fixed it) require you to tap the yubikey before typing the password. Two factors of authentication for my computer, and every online service that supports it, backed by hardware.</p><p>Once I was done all this I committed my changes to my dotfiles pushed them to git so that I could easily set the same thing up on my desktop which is also running Fedora.</p>]]></content:encoded>
	</item>
	</channel>
</rss>