<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>linux on foosel.net</title><link>https://foosel.net/tags/linux/</link><description>Recent content in linux on foosel.net</description><generator>Hugo</generator><language>en-us</language><copyright>Gina Häußge (foosel)</copyright><lastBuildDate>Fri, 23 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://foosel.net/tags/linux/feed.xml" rel="self" type="application/rss+xml"/><item><title>TIL: How to work around tailscale breaking IPv6 on the host</title><link>https://foosel.net/til/2026-01-23-how-to-work-around-tailscale-breaking-ipv6-on-the-host/</link><pubDate>Fri, 23 Jan 2026 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2026-01-23-how-to-work-around-tailscale-breaking-ipv6-on-the-host/</guid><description>&lt;p&gt;Yesterday I ran into an incredibly weird issue. I installed the &lt;a href="https://tailscale.com/"&gt;Tailscale&lt;/a&gt; client on two of my virtual servers hosted in the Hetzner Cloud (running Ubuntu) and suddenly the websites they offered stopped working. I suspected Tailscale and indeed, &lt;code&gt;tailscale down&lt;/code&gt; immediately restored functionality.&lt;/p&gt;
&lt;p&gt;The websites in question are actually on GitHub Pages and my servers are just acting as reverse proxy to resolve domain and TLS, and a look into the web server&amp;rsquo;s &lt;code&gt;error.log&lt;/code&gt; showed that the issue in serving was that the server could no longer reach its upstream at &lt;code&gt;github.io&lt;/code&gt; when Tailscale was active. It wasn&amp;rsquo;t a general loss of external connectivity though - IPv4 addresses still worked great, the webserver however was trying to connect to the upstream via IPv6 and this is where things failed.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Yesterday I ran into an incredibly weird issue. I installed the <a href="https://tailscale.com/">Tailscale</a> client on two of my virtual servers hosted in the Hetzner Cloud (running Ubuntu) and suddenly the websites they offered stopped working. I suspected Tailscale and indeed, <code>tailscale down</code> immediately restored functionality.</p>
<p>The websites in question are actually on GitHub Pages and my servers are just acting as reverse proxy to resolve domain and TLS, and a look into the web server&rsquo;s <code>error.log</code> showed that the issue in serving was that the server could no longer reach its upstream at <code>github.io</code> when Tailscale was active. It wasn&rsquo;t a general loss of external connectivity though - IPv4 addresses still worked great, the webserver however was trying to connect to the upstream via IPv6 and this is where things failed.</p>
<p>I did some quick tests, pinging Google&rsquo;s DNS on both IPv4 (<code>8.8.8.8</code>) and IPv6 (<code>2001:4860:4860::8888</code>) with Tailscale running, and that showed that while Tailscale was running, IPv6 connectivity just broke down completely while IPv4 continued to work:</p>
<pre tabindex="0"><code>$ sudo tailscale up &amp;&amp; ping -c 3 8.8.8.8 &amp;&amp; sudo tailscale down
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=117 time=3.98 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=117 time=3.69 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=117 time=3.63 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 3.631/3.771/3.986/0.162 ms

$ sudo tailscale up &amp;&amp; ping -c 3 2001:4860:4860::8888 &amp;&amp; sudo tailscale down
PING 2001:4860:4860::8888(2001:4860:4860::8888) 56 data bytes

--- 2001:4860:4860::8888 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2051ms
</code></pre><p>As a next step, I checked the route that would be taken for resolving <code>2001:4860:4860::8888</code> with and without Tailscale:</p>
<pre tabindex="0"><code>$ ip route get 2001:4860:4860::8888
2001:4860:4860::8888 from :: via fe80::1 dev eth0 src aaaa:bbbb:cccc:dddd::1 metric 1024 pref medium

$ sudo tailscale up &amp;&amp; ip route get 2001:4860:4860::8888 &amp;&amp; sudo tailscale down
2001:4860:4860::8888 from :: via fe80::1 dev eth0 src fd7a:115c:a1e0::aaaa:bbbb metric 1024 pref medium
</code></pre><p>So, the issue was that for some reason, while Tailscale was running the system decided to use Tailscale&rsquo;s internal IPv6 <code>fd7a:115c:a1e0::aaaa:bbbb</code> set on <code>tailscale0</code> as the source IP but send the packet through the default route and <code>eth0</code>, and that didn&rsquo;t work. It basically hijacked the IPv6 traffic, even when the Tailnet wasn&rsquo;t even involved.</p>
<p>The routes looked fine to me and some buddies I asked also didn&rsquo;t spot anything amiss:</p>
<pre tabindex="0"><code>$ ip -6 rule show
0:      from all lookup local
5210:   from all fwmark 0x80000/0xff0000 lookup main
5230:   from all fwmark 0x80000/0xff0000 lookup default
5250:   from all fwmark 0x80000/0xff0000 unreachable
5270:   from all lookup 52
32766:  from all lookup main

$ ip -6 route show table local
local ::1 dev lo proto kernel metric 0 pref medium
local aaaa:bbbb:cccc:dddd::1 dev eth0 proto kernel metric 0 pref medium
local fd7a:115c:a1e0::aaaa:bbbb dev tailscale0 proto kernel metric 0 pref medium
local fe80::5fdc:58a7:1a93:da5a dev tailscale0 proto kernel metric 0 pref medium
local fe80::9400:ff:fe0d:61a1 dev eth0 proto kernel metric 0 pref medium
multicast ff00::/8 dev eth0 proto kernel metric 256 pref medium
multicast ff00::/8 dev tailscale0 proto kernel metric 256 pref medium

$ ip -6 route show table 52
fd7a:115c:a1e0::53 dev tailscale0 metric 1024 pref medium
fd7a:115c:a1e0::/48 dev tailscale0 metric 1024 pref medium

$ ip -6 route show table main
aaaa:bbbb:cccc:dddd::/64 dev eth0 proto kernel metric 256 pref medium
fd7a:115c:a1e0::aaaa:bbbb dev tailscale0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fe80::1 dev eth0 metric 1024 pref medium
</code></pre><p>From what I could see, firing up Tailscale would add the following new rules to the routing table:</p>
<pre tabindex="0"><code>$ ip route show table all &gt; ts-off.txt
$ sudo tailscale up &amp;&amp; ip route show table all &gt; ts-on.txt &amp;&amp; sudo tailscale down
$ diff ts-off.txt ts-on.txt
0a1,2
&gt; 100.a.b.c dev tailscale0 table 52
&gt; 100.100.100.100 dev tailscale0 table 52
3a6
&gt; local 100.x.y.z dev tailscale0 table local proto kernel scope host src 100.x.y.z
12a16,17
&gt; fd7a:115c:a1e0::53 dev tailscale0 table 52 metric 1024 pref medium
&gt; fd7a:115c:a1e0::/48 dev tailscale0 table 52 metric 1024 pref medium
13a19
&gt; fd7a:115c:a1e0::aaaa:bbbb dev tailscale0 proto kernel metric 256 pref medium
17a24
&gt; local fd7a:115c:a1e0::aaaa:bbbb dev tailscale0 table local proto kernel metric 0 pref medium
</code></pre><p>I still have not figured out what is actually going on there, and a reproduction on a fresh server so far also wasn&rsquo;t successful. The problem is that packets are being sent with the wrong source IPv6, but that&rsquo;s just a symptom of the underlying cause.</p>
<p>Thankfully, my buddy Jub came up with the workaround to change the default route to use a fixed IPv6 source address - the correct one - and that solved the issue (by fixing the symptom):</p>
<pre tabindex="0"><code>ip -6 route replace default via fe80::1 dev eth0 src aaaa:bbbb:cccc:dddd::1
</code></pre><p>I put that on a new <code>post-up</code> line into the network setup in <code>/etc/network/interface.d/50-cloud-init.cfg</code></p>
<pre tabindex="0"><code>auto eth0:0
iface eth0:0 inet6 static
    address aaaa:bbbb:cccc:dddd::/64
    gateway fe80::1
    post-up route add -net :: netmask 0 gw fe80::1%eth0 || true
    post-up ip -6 route replace default via fe80::1 dev eth0 src aaaa:bbbb:cccc:dddd::1 || true
    pre-down route del -net :: netmask 0 gw fe80::1%eth0 || true
</code></pre><p>A reboot confirmed that this works as a <strong>workaround</strong>.</p>
<p>But as I mentioned, I still can&rsquo;t make any sense of the underlying issue. I found <a href="https://github.com/tailscale/tailscale/issues/17936">one open bug report in Tailscale&rsquo;s bug tracker</a> that sounded familiar, but it didn&rsquo;t fully match my situation. I also have to admit that my administration skills kinda get a bit fuzzy when it comes to full blown route analysis &amp; debugging - so should you have any ideas at all what is actually causing this behaviour here, please get in touch <a href="https://chaos.social/@foosel">on Mastodon</a> - I&rsquo;d love to see this mystery solved, but am out of my depth here 😅</p>
]]></content:encoded></item><item><title>TIL: How to automatically sync screenshots from the Steamdeck to Immich</title><link>https://foosel.net/til/2025-03-25-how-to-automatically-sync-screenshots-from-the-steamdeck-to-immich/</link><pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2025-03-25-how-to-automatically-sync-screenshots-from-the-steamdeck-to-immich/</guid><description>&lt;p&gt;As part of &lt;a href="https://chaos.social/@foosel/114105591362840338"&gt;my ongoing effort to reduce my dependency on US services&lt;/a&gt;, I just moved my photos
from Google Photos to a self-hosted &lt;a href="https://immich.app/"&gt;immich&lt;/a&gt; instance (which I btw can only recommend so far).&lt;/p&gt;
&lt;p&gt;You might remember from &lt;a href="https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/"&gt;a previous TIL&lt;/a&gt;
that I had my Steamdeck configured to push my screenshots into a custom album on Google Photos. Obviously I had to change that now as well,
but sadly couldn&amp;rsquo;t use the existing &lt;a href="https://rclone.org/"&gt;rclone&lt;/a&gt;-based setup for it.&lt;/p&gt;</description><content:encoded><![CDATA[<p>As part of <a href="https://chaos.social/@foosel/114105591362840338">my ongoing effort to reduce my dependency on US services</a>, I just moved my photos
from Google Photos to a self-hosted <a href="https://immich.app/">immich</a> instance (which I btw can only recommend so far).</p>
<p>You might remember from <a href="https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/">a previous TIL</a>
that I had my Steamdeck configured to push my screenshots into a custom album on Google Photos. Obviously I had to change that now as well,
but sadly couldn&rsquo;t use the existing <a href="https://rclone.org/">rclone</a>-based setup for it.</p>
<p>My first idea was to utilize <a href="https://github.com/simulot/immich-go">immich-go</a>, as I have just successfully used that for the
three day long import of over 50000 pictures from my Google Photos takeout into immich. But that turned out to not be the right tool here: in order to not even try to
upload already existing files it will fetch an asset list from immich first, and while that really improves performance for large batch imports,
it takes way too long for uploading a single new screenshot.</p>
<p>So instead I went with something self-built which utilizes <a href="https://immich.app/docs/api/">immich&rsquo;s API</a>.</p>
<h2 id="a-custom-upload-script">A custom upload script</h2>
<p>The first part is this little bash script that will take a file as input, upload it to a pre-configured immich instance and also add it to a
pre-defined album (which already has to exist). This lives in <code>~/.local/bin/immich-upload.sh</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>set -e
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>IMMICH_SERVER<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://immich.example.com&#34;</span>
</span></span><span style="display:flex;"><span>IMMICH_KEY<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;your api key goes here&#34;</span>
</span></span><span style="display:flex;"><span>IMMICH_ALBUM<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;your album id goes here&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>INPUT<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$INPUT<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;immich-upload.sh &lt;file&gt;&#34;</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>file_modified<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>stat -c %Y <span style="color:#e6db74">&#34;</span>$INPUT<span style="color:#e6db74">&#34;</span> | date --iso-8601<span style="color:#f92672">=</span>seconds<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>name<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span>$INPUT<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ---</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Uploading </span>$INPUT<span style="color:#e6db74"> to immich...&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>upload<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>curl -sL --request POST <span style="color:#e6db74">&#34;</span>$IMMICH_SERVER<span style="color:#e6db74">/api/assets&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Content-Type: multipart/form-data&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Accept: application/json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;X-API-Key: </span>$IMMICH_KEY<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;deviceId=\&#34;curl/steamdeck\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;deviceAssetId=\&#34;</span>$name<span style="color:#e6db74">-</span>$file_modified<span style="color:#e6db74">\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;fileCreatedAt=\&#34;</span>$file_modified<span style="color:#e6db74">\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;fileModifiedAt=\&#34;</span>$file_modified<span style="color:#e6db74">\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;assetData=@\&#34;</span>$INPUT<span style="color:#e6db74">\&#34;&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>id<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$upload<span style="color:#e6db74">&#34;</span> | jq -r .id<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Uploaded file, asset id is </span>$id<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ---</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Adding file to album </span>$IMMICH_ALBUM<span style="color:#e6db74">...&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>payload<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>jq -n --arg id $id <span style="color:#e6db74">&#39;{ids:[$ARGS.named.id]}&#39;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>album<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>curl -sL --request PUT <span style="color:#e6db74">&#34;</span>$IMMICH_SERVER<span style="color:#e6db74">/api/albums/</span>$IMMICH_ALBUM<span style="color:#e6db74">/assets&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Content-Type: application/json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Accept: application/json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;X-API-Key: </span>$IMMICH_KEY<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -d <span style="color:#e6db74">&#34;</span>$payload<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;... done&#34;</span>
</span></span></code></pre></div><h2 id="reacting-to-new-screenshots">Reacting to new screenshots</h2>
<p>I use <a href="https://github.com/watchexec/watchexec">watchexec</a> to listen for changes in my custom screenshot folder
(<a href="https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/">see this TIL post on how to set that up</a>)
and calling the upload script with the correct file name. I downloaded a release build of <code>watchexec</code> and threw it into <code>~/.local/bin</code>, then created another
script <code>~/.local/bin/sync-screenshots</code> that takes care of setting all of the correct parameters<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/env bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>WATCHEXEC<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>HOME<span style="color:#e6db74">}</span><span style="color:#e6db74">/.local/bin/watchexec&#34;</span>
</span></span><span style="display:flex;"><span>FOLDER<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>HOME<span style="color:#e6db74">}</span><span style="color:#e6db74">/.steam_screenshots&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">${</span>WATCHEXEC<span style="color:#e6db74">}</span> --exts jpg,png,mp4 --fs-events create --emit-events-to environment -w $FOLDER -o queue -p -v -- <span style="color:#e6db74">&#39;/home/deck/.local/bin/immich-upload.sh &#34;$WATCHEXEC_COMMON_PATH/$WATCHEXEC_CREATED_PATH&#34;&#39;</span>
</span></span></code></pre></div><h2 id="putting-it-all-together">Putting it all together</h2>
<p>Finally, a new systemd unit in <code>~/.config/systemd/user/sync-screenshots.service</code> takes care of starting this bash script and keeping it running:</p>
<pre tabindex="0"><code>[Unit]
Description=Sync Steam Screenshots

[Service]
ExecStart=%h/.local/bin/sync-screenshots
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
</code></pre><p>I enabled and started that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>systemctl --user enable sync-screenshots
</span></span><span style="display:flex;"><span>systemctl --user start sync-screenshots
</span></span></code></pre></div><p>Then I took a screenshot and confirmed that the script had run:</p>
<pre tabindex="0"><code>Mar 25 15:17:03 steamdeck sync_screenshots[77135]: [Running: /home/deck/.local/bin/immich-upload.sh &#34;$WATCHEXEC_COMMON_PATH/$WATCHEXEC_CREATED_PATH&#34;]
Mar 25 15:17:03 steamdeck sync_screenshots[77188]: Uploading /home/deck/.steam_screenshots/7_20250325151703_1.png to immich...
Mar 25 15:17:04 steamdeck sync_screenshots[77188]: Uploaded file, asset id is 141dc605-edef-48f1-83b5-00bd9d72b13e
Mar 25 15:17:04 steamdeck sync_screenshots[77188]: Adding file to album 0ce35e68-a564-4e26-921e-c486cd9e4725...
Mar 25 15:17:05 steamdeck sync_screenshots[77188]: ... done
Mar 25 15:17:05 steamdeck sync_screenshots[77135]: [Command was successful]
</code></pre><p>And indeed, upon checking my immich instance, I was also looking at the freshly uploaded screenshot. Mission accomplished!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>It&rsquo;s currently reacting to newly added <code>jpg</code>, <code>png</code> or <code>mp4</code> files. The latter is in preparation of hopefully another toolchain to automatically convert clips from
<a href="https://store.steampowered.com/gamerecording">Steam&rsquo;s game recorder</a> that will automatically push its results into the screenshot folder as well, but that&rsquo;s only an idea for now.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>TIL: How to fix VirtualBox on Fedora 40 with Kernel 6.12+</title><link>https://foosel.net/til/2025-02-27-how-to-fix-virtualbox-on-fedora-40-with-kernel-612/</link><pubDate>Thu, 27 Feb 2025 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2025-02-27-how-to-fix-virtualbox-on-fedora-40-with-kernel-612/</guid><description>&lt;p&gt;I (accidentally&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;) did a software update on my laptop last night, and this morning when I needed my Win10 VM for something, VirtualBox threw an error like this at me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;VirtualBox can&amp;rsquo;t operate in VMX root mode. Please disable the KVM kernel extension, recompile your kernel and reboot (VERR_VMX_IN_VMX_ROOT_MODE).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A quick web search for &amp;ldquo;fedora update virtualbox vboxisomaker&amp;rdquo; gave me &lt;a href="https://discussion.fedoraproject.org/t/139896"&gt;this forum post&lt;/a&gt; and consequently
&lt;a href="https://www.virtualbox.org/ticket/22248"&gt;this bug report&lt;/a&gt;, in which I found the solution: I just had to add the kernel parameter &lt;code&gt;kvm.enable_virt_at_load=0&lt;/code&gt; to disable KVM -
which comes enabled by default since Kernel 6.12. I accomplished that with grubby:&lt;/p&gt;</description><content:encoded><![CDATA[<p>I (accidentally<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>) did a software update on my laptop last night, and this morning when I needed my Win10 VM for something, VirtualBox threw an error like this at me:</p>
<blockquote>
<p>VirtualBox can&rsquo;t operate in VMX root mode. Please disable the KVM kernel extension, recompile your kernel and reboot (VERR_VMX_IN_VMX_ROOT_MODE).</p>
</blockquote>
<p>A quick web search for &ldquo;fedora update virtualbox vboxisomaker&rdquo; gave me <a href="https://discussion.fedoraproject.org/t/139896">this forum post</a> and consequently
<a href="https://www.virtualbox.org/ticket/22248">this bug report</a>, in which I found the solution: I just had to add the kernel parameter <code>kvm.enable_virt_at_load=0</code> to disable KVM -
which comes enabled by default since Kernel 6.12. I accomplished that with grubby:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo grubby --update-kernel<span style="color:#f92672">=</span>ALL --args<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;kvm.enable_virt_at_load=0&#34;</span>
</span></span></code></pre></div><p>After a reboot, VirtualBox started again.</p>
<p>Given how often VirtualBox breaks for me on updates, long term I think I really need to find a different solution&hellip; And yes, I also really need to upgrade to Fedora 41, I know 😉</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I needed to a quick reboot before an online call and promptly forgot to uncheck &ldquo;install updates&rdquo; on the reboot dialog. Which made me be late on the call. Meh.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>TIL: How to print Deutsche Post stamps via the command line on a Brother QL label printer</title><link>https://foosel.net/til/2024-01-11-how-to-print-deutsche-post-stamps-via-the-command-line-on-a-brother-ql-label-printer/</link><pubDate>Thu, 11 Jan 2024 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2024-01-11-how-to-print-deutsche-post-stamps-via-the-command-line-on-a-brother-ql-label-printer/</guid><description>&lt;p&gt;&lt;em&gt;Update from 2024-01-12: I&amp;rsquo;ve updated the scripts to support both 50mm and 62mm wide labels, and added some more whitespace trimming to the basic stamp. The post has been adjusted accordingly.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I recently acquired a &lt;a href="https://www.brother-usa.com/products/QL820NWB"&gt;Brother QL-820NWB label printer&lt;/a&gt; to be able to quickly create labels for boxes and such, and ideally also print out Deutsche Post&amp;rsquo;s &amp;ldquo;print yourself&amp;rdquo; stamps with it. The Deutsche Post stamp shop allows me to download PDFs targeting the 62mm wide endless labels for that printer, for the two types of stamps I&amp;rsquo;m interested in (stamp, and address label with stamp). But my attempts in printing those directly to the printer through Gnome&amp;rsquo;s printer integration weren&amp;rsquo;t successful, things were too small, the cutter didn&amp;rsquo;t work etc.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>Update from 2024-01-12: I&rsquo;ve updated the scripts to support both 50mm and 62mm wide labels, and added some more whitespace trimming to the basic stamp. The post has been adjusted accordingly.</em></p>
<p>I recently acquired a <a href="https://www.brother-usa.com/products/QL820NWB">Brother QL-820NWB label printer</a> to be able to quickly create labels for boxes and such, and ideally also print out Deutsche Post&rsquo;s &ldquo;print yourself&rdquo; stamps with it. The Deutsche Post stamp shop allows me to download PDFs targeting the 62mm wide endless labels for that printer, for the two types of stamps I&rsquo;m interested in (stamp, and address label with stamp). But my attempts in printing those directly to the printer through Gnome&rsquo;s printer integration weren&rsquo;t successful, things were too small, the cutter didn&rsquo;t work etc.</p>
<p>I knew that printing to the printer via my local instance of <a href="https://github.com/pklaus/brother_ql_web">brother_ql_web</a> works flawlessly, and that the library this is based on, <a href="https://github.com/pklaus/brother_ql">brother_ql</a>, has a command line interface. So I thought, why not just convert the PDFs to individual PNGs, and then print those?</p>
<p>Through the magic of some shell scripting, I&rsquo;m now able to do just that, right from the command line.</p>
<p>I installed the <code>brother_ql</code> Python package via pip:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pip install --user brother_ql
</span></span></code></pre></div><p>I had to do a little manual patch to make it work with the latest versions of the required Pillow dependency, by editing <code>brother_ql/conversion.py</code> and changing <code>Image.ANTIALIAS</code> to <code>Image.LANCZOS</code>.</p>
<p>I also made sure my <code>.bash_profile</code> contains the address and model of my printer:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export BROTHER_QL_PRINTER<span style="color:#f92672">=</span>tcp://192.168.x.x
</span></span><span style="display:flex;"><span>export BROTHER_QL_MODEL<span style="color:#f92672">=</span>QL-820NWB
</span></span></code></pre></div><p>Then I created two shell scripts, one for printing stamps and one for printing labels.</p>
<p>The first one, <code>porto_print</code>, takes care of printing the stamps. It resizes, trims, adds a new border and then extends to the native width for the selected label size (50mm by default, or 62mm if requested) while keeping a right alignment:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Usage:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#   porto_print &lt;pdf&gt; [50|62]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tmpdir<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>mktemp -d<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cleanup<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  rm -rf <span style="color:#e6db74">&#34;</span>$tmpdir<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>trap cleanup EXIT
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>PDF<span style="color:#f92672">=</span>$1
</span></span><span style="display:flex;"><span>LABEL<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>2<span style="color:#66d9ef">:-</span>50<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>PNG<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>PDF%.*<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">case</span> $LABEL in
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;50&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    WIDTH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;554&#34;</span>
</span></span><span style="display:flex;"><span>    ;;
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;62&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    WIDTH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;696&#34;</span>
</span></span><span style="display:flex;"><span>    ;;
</span></span><span style="display:flex;"><span>  *<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Unsupported label size: </span>$LABEL<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    exit -1
</span></span><span style="display:flex;"><span>    ;;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">esac</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Converting PDF to individual PNGs...&#34;</span>
</span></span><span style="display:flex;"><span>pdftoppm <span style="color:#e6db74">&#34;</span>$PDF<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span>$tmpdir<span style="color:#e6db74">/</span>$PNG<span style="color:#e6db74">&#34;</span> -png -r <span style="color:#ae81ff">600</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> file in <span style="color:#66d9ef">$(</span>ls $tmpdir/*.png<span style="color:#66d9ef">)</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Printing </span>$file<span style="color:#e6db74">...&#34;</span>
</span></span><span style="display:flex;"><span>  mogrify -background white -bordercolor white -resize 696x -trim -border 25x25 -gravity east -extent <span style="color:#e6db74">${</span>WIDTH<span style="color:#e6db74">}</span>x284 <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  brother_ql print -l $LABEL <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span></code></pre></div><p>The second one, <code>porto_address_print</code>, does basically the same, just with slightly different parameters and left alignment:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Usage:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#   porto_address_print &lt;pdf&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tmpdir<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>mktemp -d<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cleanup<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  rm -rf <span style="color:#e6db74">&#34;</span>$tmpdir<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>trap cleanup EXIT
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>PDF<span style="color:#f92672">=</span>$1
</span></span><span style="display:flex;"><span>LABEL<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>2<span style="color:#66d9ef">:-</span>50<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>PNG<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>PDF%.*<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">case</span> $LABEL in
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;50&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    WIDTH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;554&#34;</span>
</span></span><span style="display:flex;"><span>    ;;
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;62&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    WIDTH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;696&#34;</span>
</span></span><span style="display:flex;"><span>    ;;
</span></span><span style="display:flex;"><span>  *<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Unsupported label size: </span>$LABEL<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    exit -1
</span></span><span style="display:flex;"><span>    ;;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">esac</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Converting PDF to individual PNGs...&#34;</span>
</span></span><span style="display:flex;"><span>pdftoppm <span style="color:#e6db74">&#34;</span>$PDF<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span>$tmpdir<span style="color:#e6db74">/</span>$PNG<span style="color:#e6db74">&#34;</span> -png -r <span style="color:#ae81ff">600</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> file in <span style="color:#66d9ef">$(</span>ls $tmpdir/*.png<span style="color:#66d9ef">)</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Printing </span>$file<span style="color:#e6db74">...&#34;</span>
</span></span><span style="display:flex;"><span>  mogrify -bordercolor white -background white -resize 696x -trim -border 25x25 -gravity West -extent <span style="color:#e6db74">${</span>WIDTH<span style="color:#e6db74">}</span>x839 <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> 
</span></span><span style="display:flex;"><span>  brother_ql print -l $LABEL <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span></code></pre></div><p>Both of these were placed under <code>~/.local/bin</code> and made executable. I can now call them both from anywhere on the command line, just passing the path to the PDF to print.</p>
<p>The result is one or more nicely printed stamps or address labels, ready to be stuck to an envelope:</p>
<p><img src="https://foosel.net/til/2024-01-11-how-to-print-deutsche-post-stamps-via-the-command-line-on-a-brother-ql-label-printer/result.jpg" alt="Printed stamp and printed stamp with address label, freshly printed from example files through the two scripts" loading="lazy">
</p>
<p>Now, this should hopefully make it easier for me to print all those address labels for OctoPrint sticker shipments in the future ;) Next step: Automated QR code labels for the various boxes on my shelves ^^</p>
]]></content:encoded></item><item><title>TIL: How to fix GRUB after a SteamOS update</title><link>https://foosel.net/til/2023-11-25-how-to-fix-grub-after-steamos-update/</link><pubDate>Sat, 25 Nov 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2023-11-25-how-to-fix-grub-after-steamos-update/</guid><description>&lt;p&gt;My partner just ran into an issue after updating his SteamDeck to the latest SteamOS version (3.4.x to 3.5.7).&lt;/p&gt;
&lt;p&gt;He has a dual boot setup running using &lt;a href="https://github.com/jlobue10/SteamDeck_rEFInd"&gt;rEFInd&lt;/a&gt;, and while that survived the OS update just fine, when he wanted to return to SteamOS after a quick stint in Windows today, he was greeted by a GRUB boot menu.&lt;/p&gt;
&lt;p&gt;Detective foosel to the rescue.&lt;/p&gt;
&lt;p&gt;Attempting to boot the SteamOS entry in grub resulted in an error like this (with another device UUID):&lt;/p&gt;</description><content:encoded><![CDATA[<p>My partner just ran into an issue after updating his SteamDeck to the latest SteamOS version (3.4.x to 3.5.7).</p>
<p>He has a dual boot setup running using <a href="https://github.com/jlobue10/SteamDeck_rEFInd">rEFInd</a>, and while that survived the OS update just fine, when he wanted to return to SteamOS after a quick stint in Windows today, he was greeted by a GRUB boot menu.</p>
<p>Detective foosel to the rescue.</p>
<p>Attempting to boot the SteamOS entry in grub resulted in an error like this (with another device UUID):</p>
<pre tabindex="0"><code>error: no such device: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
error: file `/boot/vmlinuz-linux-neptune` not found.
error: you need to load the kernel first.

Press any key to continue...
</code></pre><p>So it couldn&rsquo;t find it&rsquo;s boot device and due to that also not the kernel stored thereon.</p>
<p>Entering the Deck&rsquo;s boot manager and manually booting <code>\efi\steamos\steamoscl.efi</code> also led to the same situation.</p>
<p>I was able to still boot into SteamOS via the fallback entry however (which also had a different boot device UUID).</p>
<p>And it took me way too long<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> to simply just get the idea to let Linux update its GRUB entries:</p>
<pre tabindex="0"><code>sudo update-grub
</code></pre><p>That fixed it.</p>
<p>No idea if the dual boot setup played a roll in this mess or if it was just some random hiccup, my Deck&rsquo;s update went without a hitch 🤷‍♀️ But if it happens again I now have this entry to check 😁</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I reinstalled rEFInd, rebuilt the EFI entries (<code>sudo efibootmgr -c -d /dev/nvme0n1 -p 1 -L &quot;SteamOS&quot; -l \\efi\\steamos\\steamcl.efi</code>) and the initramfs files (<code>mkinitcpio -P</code>) before getting the idea to maybe start at the bottom instead of the top.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>TIL: How to fix VirtualBox on Fedora 38 with Kernel 6.4.10+ by adding a missing include</title><link>https://foosel.net/til/2023-09-07-how-to-fix-virtualbox-on-fedora-38-with-kernel-6410/</link><pubDate>Thu, 07 Sep 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2023-09-07-how-to-fix-virtualbox-on-fedora-38-with-kernel-6410/</guid><description>&lt;p&gt;I recently did a software update on my laptop running Fedora 38, and that also brought in a kernel update. Starting my Win10 VirtualBox VM afterwards no longer worked as it needed the kernel module to be recompiled. However, that failed:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ sudo /sbin/vboxconfig
[sudo] password for gina:
vboxdrv.sh: Stopping VirtualBox services.
depmod: WARNING: could not open modules.order at /lib/modules/6.3.8-200.fc38.x86_64: No such file or directory
depmod: WARNING: could not open modules.builtin at /lib/modules/6.3.8-200.fc38.x86_64: No such file or directory
depmod: WARNING: could not open modules.builtin.modinfo at /lib/modules/6.3.8-200.fc38.x86_64: No such file or directory
vboxdrv.sh: Starting VirtualBox services.
vboxdrv.sh: Building VirtualBox kernel modules.
egrep: warning: egrep is obsolescent; using grep -E
vboxdrv.sh: failed: Look at /var/log/vbox-setup.log to find out what went wrong.
There were problems setting up VirtualBox. To re-start the set-up process, run
/sbin/vboxconfig
as root. If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system&amp;#39;s documentation for more information.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A look into &lt;code&gt;/var/log/vbox-setup.log&lt;/code&gt; revealed an error along the lines of this one&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;</description><content:encoded><![CDATA[<p>I recently did a software update on my laptop running Fedora 38, and that also brought in a kernel update. Starting my Win10 VirtualBox VM afterwards no longer worked as it needed the kernel module to be recompiled. However, that failed:</p>
<pre tabindex="0"><code>$ sudo /sbin/vboxconfig 
[sudo] password for gina: 
vboxdrv.sh: Stopping VirtualBox services.
depmod: WARNING: could not open modules.order at /lib/modules/6.3.8-200.fc38.x86_64: No such file or directory
depmod: WARNING: could not open modules.builtin at /lib/modules/6.3.8-200.fc38.x86_64: No such file or directory
depmod: WARNING: could not open modules.builtin.modinfo at /lib/modules/6.3.8-200.fc38.x86_64: No such file or directory
vboxdrv.sh: Starting VirtualBox services.
vboxdrv.sh: Building VirtualBox kernel modules.
egrep: warning: egrep is obsolescent; using grep -E
vboxdrv.sh: failed: Look at /var/log/vbox-setup.log to find out what went wrong.

There were problems setting up VirtualBox.  To re-start the set-up process, run
  /sbin/vboxconfig
as root.  If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system&#39;s documentation for more information.
</code></pre><p>A look into <code>/var/log/vbox-setup.log</code> revealed an error along the lines of this one<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<pre tabindex="0"><code>/tmp/akmodsbuild.bPlgZsDR/BUILD/VirtualBox-kmod-7.0.10/_kmod_build_6.4.10-200.fc38.x86_64/vboxnetflt/linux/VBoxNetFlt-linux.c: In function &#39;vboxNetFltLinuxForwardToIntNetInner&#39;:
/tmp/akmodsbuild.bPlgZsDR/BUILD/VirtualBox-kmod-7.0.10/_kmod_build_6.4.10-200.fc38.x86_64/vboxnetflt/linux/VBoxNetFlt-linux.c:1570:40: error: implicit declaration of function &#39;skb_gso_segment&#39;; did you mean &#39;skb_gso_reset&#39;? [-Werror=implicit-function-declaration]
 1570 |             struct sk_buff *pSegment = skb_gso_segment(pBuf, 0 /*supported features*/);
      |                                        ^~~~~~~~~~~~~~~
      |                                        skb_gso_reset
/tmp/akmodsbuild.bPlgZsDR/BUILD/VirtualBox-kmod-7.0.10/_kmod_build_6.4.10-200.fc38.x86_64/vboxnetflt/linux/VBoxNetFlt-linux.c:1570:40: warning: initialization of &#39;struct sk_buff *&#39; from &#39;int&#39; makes pointer from integer without a cast [-Wint-conversion]
cc1: some warnings being treated as errors
</code></pre><p>I did some web searching and came across <a href="https://discussion.fedoraproject.org/t/87492">this post on the Fedora forums</a> with someone having the exact same issue, and found <a href="https://discussion.fedoraproject.org/t/6-4-10-200-fc38-x86-64-created-problems-with-virtual-box/87492/12">a solution in the comments courtesy of Peter Francis</a>:</p>
<blockquote>
<p>Adding</p>
<pre><code>#include &lt;net/gso.h&gt;
</code></pre>
<p>below the line</p>
<pre><code>#include &lt;linux/inetdevice.h&gt;
</code></pre>
<p>in <code>/usr/share/virtualbox/src/vboxhost/vboxnetflt/linux/VBoxNetFlt-linux.c</code> fixed it for me.</p>
<p>Hopefully when the file gets overwritten on next VirtualBox update the fix will be already added by VirtualBox’s programmers.</p>
</blockquote>
<p>And what can I say, it also fixed it for me! And should this not get fixed in the next update, now I&rsquo;ll know where to find the solution again - my own TIL post 😉</p>
<p>PS: Something tells me this won&rsquo;t be the last VirtualBox related TIL post I&rsquo;ll write&hellip;</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This is copy-pasted from someone else, as my log file got overwritten by the successful compile later. However it looked very much like this error, apart from my Kernel already being at 6.4.13.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>TIL: How to monitor network traffic on my USG via Wireshark</title><link>https://foosel.net/til/2023-08-28-how-to-monitor-network-traffic-on-my-usg-via-wireshark/</link><pubDate>Mon, 28 Aug 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2023-08-28-how-to-monitor-network-traffic-on-my-usg-via-wireshark/</guid><description>&lt;p&gt;I&amp;rsquo;m currently trying to figure out some internal network issues&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; and for that need to monitor the traffic of a specific device on my network. I&amp;rsquo;m using a Unifi USG as my router (behind the ISP&amp;rsquo;s Fritzbox that I consider hostile since it&amp;rsquo;s not mine). I found &lt;a href="https://www.reddit.com/r/Ubiquiti/comments/ar444z/what_is_the_best_way_to_monitor_traffic_of_a/egkv91p/"&gt;this post on reddit&lt;/a&gt; that explains how to capture traffic on the USG via &lt;code&gt;tcpdump&lt;/code&gt; and send it through the SSH session to Wireshark on my laptop:&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;m currently trying to figure out some internal network issues<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and for that need to monitor the traffic of a specific device on my network. I&rsquo;m using a Unifi USG as my router (behind the ISP&rsquo;s Fritzbox that I consider hostile since it&rsquo;s not mine). I found <a href="https://www.reddit.com/r/Ubiquiti/comments/ar444z/what_is_the_best_way_to_monitor_traffic_of_a/egkv91p/">this post on reddit</a> that explains how to capture traffic on the USG via <code>tcpdump</code> and send it through the SSH session to Wireshark on my laptop:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ssh admin@192.168.1.1 <span style="color:#e6db74">&#39;sudo tcpdump -f -i eth1 -w - src 192.168.1.12&#39;</span> | wireshark -k -i - 
</span></span></code></pre></div><p>I could confirm that this works and created a small script to make it easier to use by throwing this into <code>~/.local/bin/gatedump</code><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ARGS<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>TCPDUMP<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;sudo tcpdump -f -w - </span>$ARGS<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ssh usg <span style="color:#e6db74">&#34;</span>$TCPDUMP<span style="color:#e6db74">&#34;</span> | wireshark -k -i -
</span></span></code></pre></div><p>This now allows me to easily run <code>tcpdump</code> remotely with custom arguments, e.g. <code>gatedump -i eth1 host 192.168.1.123</code>, and have it fire up Wireshark automatically. Wish me luck I&rsquo;ll now be able to figure out what&rsquo;s going on on my network, because it&rsquo;s driving me up the wall.</p>
<p><em>Update from 2023-12-06</em>: In case you are wondering how this story ended, the issue resolved itself with the next OS update of my partner&rsquo;s iPhone. So whatever caused it, it&rsquo;s gone now, and I hope for good.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>The iPhone of my partner seems to do something that makes my ISP&rsquo;s router freak out and drop packets every couple of minutes. No issue when he&rsquo;s not here or doesn&rsquo;t have it connected to the WiFi, immediate packet loss when it&rsquo;s on the WiFi. It started at the start of this month and we are both currently out of explanations.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><code>ssh usg</code> does automatically use the correct host, port and user thanks to an entry in <code>~/.ssh/config</code>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>TIL: How to fix VirtualBox on Fedora 38 with Kernel 6.3.5 by disabling IBT</title><link>https://foosel.net/til/2023-06-13-how-to-fix-virtualbox-on-fedora-38-with-kernel-635/</link><pubDate>Tue, 13 Jun 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2023-06-13-how-to-fix-virtualbox-on-fedora-38-with-kernel-635/</guid><description>&lt;p&gt;For accounting and some windows only software (👋 Affinity Designer) I have a Windows 10 VM running in VirtualBox on my Framework running Fedora 38. Apparently I got a kernel update recently and as of this morning the VM refused to start. It just hung, and a look into &lt;code&gt;journalctl&lt;/code&gt; showed something like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Jun 13 10:23:50 draper kernel: traps: Missing ENDBR: 0xffff9b688c308f30
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After some searching I came across &lt;a href="https://forums.virtualbox.org/viewtopic.php?p=536761#p536761"&gt;this thread on the VirtualBox forums&lt;/a&gt; which explained the issue and also includes the solution. Apparently the VirtualBox kernel driver &lt;a href="https://www.virtualbox.org/ticket/21435"&gt;triggers Intel&amp;rsquo;s IBT (indirect branch tracking)&lt;/a&gt;. The solution is to disable that&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; by passing &lt;code&gt;ibt=off&lt;/code&gt; as a kernel parameter:&lt;/p&gt;</description><content:encoded><![CDATA[<p>For accounting and some windows only software (👋 Affinity Designer) I have a Windows 10 VM running in VirtualBox on my Framework running Fedora 38. Apparently I got a kernel update recently and as of this morning the VM refused to start. It just hung, and a look into <code>journalctl</code> showed something like this:</p>
<pre tabindex="0"><code>Jun 13 10:23:50 draper kernel: traps: Missing ENDBR: 0xffff9b688c308f30
</code></pre><p>After some searching I came across <a href="https://forums.virtualbox.org/viewtopic.php?p=536761#p536761">this thread on the VirtualBox forums</a> which explained the issue and also includes the solution. Apparently the VirtualBox kernel driver <a href="https://www.virtualbox.org/ticket/21435">triggers Intel&rsquo;s IBT (indirect branch tracking)</a>. The solution is to disable that<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> by passing <code>ibt=off</code> as a kernel parameter:</p>
<pre tabindex="0"><code>sudo grubby --update-kernel=ALL --args=&#34;ibt=off&#34;
</code></pre><p>After a reboot I could rebuild the vbox kernel driver via <code>/sbin/vboxconfig</code>, which ran through without issues, and after that the VM started up just fine.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Honestly, I&rsquo;d prefer to keep <a href="https://lwn.net/Articles/889475/">IBT</a> enabled for security reasons, but I need the VM to work. Let&rsquo;s hope VirtualBox fixes this soon, though given how long this seems to have gone on I&rsquo;m a bit skeptical.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>TIL: How to add Battle.net games to the Steamdeck</title><link>https://foosel.net/til/2023-04-15-how-to-add-battle-net-games-to-the-steamdeck/</link><pubDate>Sat, 15 Apr 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2023-04-15-how-to-add-battle-net-games-to-the-steamdeck/</guid><description>&lt;p&gt;&lt;em&gt;Update 2023-06-07: It turns out that these days, the by far easiest way to get Battle.net on the SteamDeck is using &lt;a href="https://github.com/moraroy/NonSteamLaunchers-On-Steam-Deck"&gt;NonSteamLaunchers-On-Steam-Deck&lt;/a&gt;, as I recently saw on &lt;a href="https://www.gamingonlinux.com/2023/05/get-battlenet-ea-epic-games-and-more-on-steam-deck-the-easy-way/"&gt;Gaming On Linux&lt;/a&gt;. I haven&amp;rsquo;t gotten a chance to try this myself yet, but it certainly looks very much straight forward, albeit not featuring individual game entries in Steam. For your quick Diablo fix, it should hopefully be just fine though.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Battle.net is currently having a spring sale and I&amp;rsquo;ve been eyeing Diablo II: Resurrected for a while now, so I jumped on the chance (and while at it also got StarCraft Remastered). But given that these days I primarily game on the Steamdeck, I needed to find a way to install Battle.net on my deck and also install individual launchers for the games.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>Update 2023-06-07: It turns out that these days, the by far easiest way to get Battle.net on the SteamDeck is using <a href="https://github.com/moraroy/NonSteamLaunchers-On-Steam-Deck">NonSteamLaunchers-On-Steam-Deck</a>, as I recently saw on <a href="https://www.gamingonlinux.com/2023/05/get-battlenet-ea-epic-games-and-more-on-steam-deck-the-easy-way/">Gaming On Linux</a>. I haven&rsquo;t gotten a chance to try this myself yet, but it certainly looks very much straight forward, albeit not featuring individual game entries in Steam. For your quick Diablo fix, it should hopefully be just fine though.</em></p>
<p>Battle.net is currently having a spring sale and I&rsquo;ve been eyeing Diablo II: Resurrected for a while now, so I jumped on the chance (and while at it also got StarCraft Remastered). But given that these days I primarily game on the Steamdeck, I needed to find a way to install Battle.net on my deck and also install individual launchers for the games.</p>
<h2 id="battlenet">Battle.net</h2>
<p>I first made the mistake of trying my luck with installing the Battle.net launcher directly via Steam Proton. Trust me: Don&rsquo;t. Lots of work, doesn&rsquo;t end up well. Instead, I went with <a href="https://lutris.net/">Lutris</a>. Lutris has been installed for a while, but if that&rsquo;s not yet on your deck, install that first via the Discover app. Then:</p>
<ol>
<li>Enter desktop mode</li>
<li>Navigate to <a href="https://lutris.net/games/battlenet/">https://lutris.net/games/battlenet/</a> and click on &ldquo;Install&rdquo;. That will fire up an install script in your Lutris setup. Follow the steps shown to you by the app.</li>
<li>Once the installer has run its course, log into Battle.net. You should now be able to download stuff.</li>
<li>Right click on Battle.net in Lutris, select &ldquo;Add steam shortcut&rdquo; (if that&rsquo;s not available, but &ldquo;Delete steam shortcut&rdquo; is - nothing to do, the shortcut has already been added). This will become available after Steam has been restarted, don&rsquo;t worry about it now.</li>
</ol>
<h2 id="diablo-ii-resurrected">Diablo II: Resurrected</h2>
<p>This will create a Lutris app that uses the same Wine prefix as your Battle.net install. This is important! In desktop mode:</p>
<ol>
<li>Navigate to <a href="https://lutris.net/games/diablo-2-ressurected/">https://lutris.net/games/diablo-2-ressurected/</a> (not a typo, there <em>is</em> a typo in that slug indeed), click &ldquo;Install&rdquo;. Follow the steps.</li>
<li>If not yet done, launch Battle.net and install Diablo II: Resurrected.</li>
<li>Launch Diablo once via Battle.net, exit as soon as you can.</li>
<li>In Lutris, right click on the Diablo entry, select &ldquo;Configure&rdquo; and go to &ldquo;Game options&rdquo;</li>
<li>Click &ldquo;Browse&rdquo; next to &ldquo;Executable&rdquo;. Change it to to <code>/home/deck/Games/battlenet/drive_c/Program Files (x86)/Diablo II Resurrected/D2R.exe</code> (so, one folder up, into the Diablo folder and there select <code>D2R.exe</code>)</li>
<li>Under Arguments add <code>-launch</code></li>
<li>Save</li>
</ol>
<p>Make sure the Steam shortcut for the app is added.</p>
<h2 id="starcraft">StarCraft</h2>
<p>Just as with Diablo II, it is important that the StarCraft entry uses the same Wine prefix as Battle.net. Either duplicate the existing &ldquo;Diablo II: Resurrected&rdquo; entry or alternatively follow steps 1 and 2 above. Then do the following with your game entry:</p>
<ol>
<li>Launch Battle.net, install Starcraft Remastered.</li>
<li>Right click on the designated game entry (either your duplicate of Diablo II, or the Diablo II entry you don&rsquo;t intend to use), select &ldquo;Configure&rdquo;</li>
<li>Under &ldquo;Game info&rdquo;, change the name to &ldquo;Starcraft Remastered&rdquo; and the identifier to &ldquo;starcraft-remastered&rdquo;</li>
<li>Under &ldquo;Game options&rdquo;, change the executable to <code>/home/deck/Games/battlenet/drive_c/Program Files (x86)/StarCraft/x86_64/StarCraft.exe</code> and add <code>-launch</code> to the Arguments</li>
<li>Save</li>
</ol>
<p>The art in Lutris should update automatically. Make sure the Steam shortcut for the app is added.</p>
<p>Once all of that is done, head back into game mode. Feel free to change the art for the newly created entries, e.g. through something like the <a href="https://github.com/SteamGridDB/decky-steamgriddb">SteamGridDB</a> plugin for <a href="https://deckbrew.xyz/">Decky</a>. I also set up a dedicated &ldquo;Battle.net&rdquo; collection and added Battle.net itself plus both games to it.</p>
<p><img src="https://foosel.net/til/2023-04-15-how-to-add-battle-net-games-to-the-steamdeck/steamdeck-battlenet-1.png" alt="Screenshot from the Steamdeck, showing a &ldquo;Battle.net&rdquo; collection containing Battle.net, Diablo II: Resurrected and StarCraft Remastered shortcuts" loading="lazy">
</p>
<p>You should now be able to launch your games through their individual Steam shortcuts. Note that the way we have set up things, Battle.net will not be fully available, so if you need that (for multiplayer or for unlocking DLCs) you&rsquo;ll need to launch through the Battle.net shortcut instead. In the case of the Cartoon skin for StarCraft Remastered, launching Starcraft once through Battle.net sufficed however ^^</p>
<p><img src="https://foosel.net/til/2023-04-15-how-to-add-battle-net-games-to-the-steamdeck/steamdeck-battlenet-2.png" alt="Screenshot of the cartoon skin for StarCraft Remastered" loading="lazy">
</p>
]]></content:encoded></item><item><title>TIL: How to override the EDID data of a monitor under Linux</title><link>https://foosel.net/til/2023-04-11-how-to-override-the-edid-data-of-a-monitor-under-linux/</link><pubDate>Tue, 11 Apr 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/2023-04-11-how-to-override-the-edid-data-of-a-monitor-under-linux/</guid><description>&lt;p&gt;I&amp;rsquo;m slowly but surely fixing all the issues I had after switching back to Linux as my main OS, so here&amp;rsquo;s another TIL 😉&lt;/p&gt;
&lt;p&gt;My secondary monitor is a 24&amp;quot; DELL with a resolution of 1920x1200, so 16:10, instead of the more common 1080p and 16:9. In order to be able to connect all my three monitors to my laptop, I make use of both the laptop&amp;rsquo;s HDMI port as well as a USB-C dock that has 2 HDMI ports. The 4k main display is connected directly to the laptop&amp;rsquo;s HDMI port, secondary and tertiary display are connected to the dock.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;m slowly but surely fixing all the issues I had after switching back to Linux as my main OS, so here&rsquo;s another TIL 😉</p>
<p>My secondary monitor is a 24&quot; DELL with a resolution of 1920x1200, so 16:10, instead of the more common 1080p and 16:9. In order to be able to connect all my three monitors to my laptop, I make use of both the laptop&rsquo;s HDMI port as well as a USB-C dock that has 2 HDMI ports. The 4k main display is connected directly to the laptop&rsquo;s HDMI port, secondary and tertiary display are connected to the dock.</p>
<p>The problem now was that as long as I had both secondary and tertiary connected, I could only select up to 1080p for the secondary. That would not have been that big of an issue if that wouldn&rsquo;t have caused the monitor to try to scale the 16:9 output to 16:10, stretching it. With only the secondary display attached however, it would detect the 16:10 resolution just fine.</p>
<p>On Windows, with the same hardware setup (albeit a different laptop), this was quickly solved with <a href="https://www.monitortests.com/forum/Thread-Custom-Resolution-Utility-CRU">a third party tool</a> and ran just fine for months. On Linux I was stumped for the past few weeks since switching. Adding <code>video=</code> lines to the kernel parameters - as suggested by various guides - didn&rsquo;t seem to do the trick, and that appears to be the only option these days with Wayland in the mix to do something like this.</p>
<p>Today however I fell over <a href="https://wiki.archlinux.org/title/kernel_mode_setting#Forcing_modes_and_EDID">this helpful section</a> on the ArchLinux wiki, and that gave me an idea. Apparently the EDID information of the secondary is correct when it is connected alone, or I wouldn&rsquo;t be able to select 1920x1200 then. So I should be able to just grab the EDID data from it when working and force that to be used all the time via a kernel parameter.</p>
<p>I disconnected my tertiary display and verified the secondary was now again being detected as supporting 1920x1200. Then I first figured out its port by checking which of the available devices showed as connected (and wasn&rsquo;t the internal laptop screen or the 4k primary):</p>
<pre tabindex="0"><code>$ for p in /sys/class/drm/*/status; do con=${p%/status}; echo -n &#34;${con#*/card?-}: &#34;; cat $p; done
DP-1: disconnected
DP-2: connected
DP-3: disconnected
DP-4: disconnected
DP-5: disconnected
DP-6: connected
DP-7: disconnected
eDP-1: connected
</code></pre><p>In my case that turned out to be <code>DP-6</code><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. Next I quickly dumped the EDID information to a new file <code>/usr/lib/firmware/edid/dell-24-1200p.bin</code>:</p>
<pre tabindex="0"><code>sudo mkdir -p /usr/lib/firmware/edid
sudo cp /sys/class/drm/card1-DP-6/edid /usr/lib/firmware/edid/dell-24-1200p.bin
</code></pre><p>Then I used <code>grubby</code> to add a <code>drm.edid_firmware</code> kernel mode setting to all kernel entries for <code>DP-6</code> that tells the kernel to use this EDID file:</p>
<pre tabindex="0"><code>sudo grubby --update-kernel=ALL --args=&#34;drm.edid_firmware=DP-6:edid/dell-24-1200p.bin&#34;
</code></pre><p>And one reboot later I could finally select 1920x1200 for my display! 🥳</p>
<p><em>Addendum from 2023-05-24</em>*: Recently the display&rsquo;s identifier&rsquo;s started switching between <code>DP-6</code> and <code>DP-8</code>, sometimes even when waking up from sleep. I&rsquo;m not sure why, and I so far did not have time to investigate, but just so I or anyone else stumbling over this knows how to do this in the future, it&rsquo;s easy to set custom edid data on multiple devices as well, in my case:</p>
<pre tabindex="0"><code>sudo grubby --update-kernel=ALL --args=&#34;drm.edid_firmware=DP-6:edid/dell-24-1200p.bin,DP-8:edid/dell-24-1200p.bin&#34;
</code></pre><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><code>DP-2</code> is the primary and <code>eDP-1</code> the laptop&rsquo;s internal display&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>