<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://rubin55.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://rubin55.org/" rel="alternate" type="text/html" /><updated>2026-03-16T01:04:41+01:00</updated><id>https://rubin55.org/feed.xml</id><title type="html">rubin55.org</title><subtitle>Rubin&apos;s internet site on the internet. Ah yes well™</subtitle><author><name>Rubin Simons</name></author><entry><title type="html">What 2025 was and ideas for 2026</title><link href="https://rubin55.org/blog/what-2025-was-and-ideas-for-2026/" rel="alternate" type="text/html" title="What 2025 was and ideas for 2026" /><published>2026-01-01T11:26:00+01:00</published><updated>2026-01-01T11:26:00+01:00</updated><id>https://rubin55.org/blog/what-2025-was-and-ideas-for-2026</id><content type="html" xml:base="https://rubin55.org/blog/what-2025-was-and-ideas-for-2026/"><![CDATA[<h2 id="what-2025-was">What 2025 was</h2>

<p>I am writing this on the first day of the new year, 2026. I’ve mainly been
using this blog/website to host my <a href="/blog/running-arch-linux-on-the-framework-laptop-13">article about my Arch Linux install</a> and
I’ve kept that up-to-date with changes I’ve made to my system in the last two
years (idea being: having a document that describes my setup so I could
reproduce it, because I always forget which modifications I did).</p>

<p>2025 was the first year in my new house. We moved in July of 2024, It’s an old
mansion (built in 1897). Our moving was something that simmered and we decided
to just do it. The house is in good condition. One of the big things we did
this year is to isolate the roof (effectively a new roof) and replace all glass
with more modern isolating glass. I’ve kept track of gas usage so far, and 
early indications seem to be about 30 percent reduction in gas usage compared
to 2024, which is great, because gas is expensive.</p>

<p>I also turned 50 in November which is kind of surreal.. A few days ago I was
re-reading <a href="/blog/reflecting-on-my-2023/#final-thoughts-lost-purpose">my reflections on 2023</a>. It is a bit unsettling that I have to
admit that that feeling of “purpose” that I mentioned there, hasn’t really
emerged. Motivation has been a real struggle in 2025. It’s not for lack of 
doing big new things: new house, new project at work, working in a new 
<a href="https://www.rust-lang.org/">programming language</a>, a big sailing trip to Norway, been to the Carribean
last year.</p>

<p>If I would have to summarize 2025, it would be as: <code class="language-plaintext highlighter-rouge">too much</code>.</p>

<p>The big reasons for that are not the fun things we did, like the vacations, and
the travels, but I think they mostly stem from two things:</p>

<ul>
  <li>Difficulty applying focus on work-related subjects</li>
  <li>A weekly schedule that leaves no room for flex</li>
</ul>

<p>I’ve had more trouble than usual applying focus on work-related tasks. If I
look at how that works, I think it is because of having to do things that
really require focus, but having a schedule that has zero room for flex. My
schedule is so tight that I constantly find myself having to stop what I’m
doing and rush into the next have-to-do task, which can be anything from a
weekly meeting, bookkeeping and administrative work for my company, to picking
up my daughter for school or ballet.</p>

<p>From how 2025 has felt, I have a few ideas about what to do different in 2026..</p>

<h2 id="ideas-for-2026">Ideas for 2026</h2>

<p>So 2026. A new year ahead. I have a few ideas that I will try to do this year:</p>

<ul>
  <li>A more restful/sustainable pace</li>
  <li>Less planning and schedule</li>
  <li>Stop the daily grinding</li>
  <li>Leave time for just normal things</li>
  <li>Like going for a walk in the park</li>
  <li>Or taking time to cook something nice</li>
  <li>Create space to work with focus</li>
  <li>Not all over the place, single subject</li>
  <li>Re-start my bouldering exercises</li>
</ul>

<p>To do the above, means making some choices, specifically about what <em>not</em> to
do, what to leave out, because a schedule can only get less crowded by simply
not doing certain things, consciously.</p>

<p>I also hope to share a little bit more regularly here. I have a few good 
subjects in mind that deserve their own article.</p>

<p>Happy new year to all!</p>]]></content><author><name>Rubin Simons</name></author><category term="blog" /><category term="thoughts" /><summary type="html"><![CDATA[What 2025 was]]></summary></entry><entry><title type="html">Running Arch Linux on the Framework Laptop 13</title><link href="https://rubin55.org/blog/running-arch-linux-on-the-framework-laptop-13/" rel="alternate" type="text/html" title="Running Arch Linux on the Framework Laptop 13" /><published>2025-09-30T11:02:00+02:00</published><updated>2025-09-30T11:02:00+02:00</updated><id>https://rubin55.org/blog/running-arch-linux-on-the-framework-laptop-13</id><content type="html" xml:base="https://rubin55.org/blog/running-arch-linux-on-the-framework-laptop-13/"><![CDATA[<p>This article sums up why and how I run Arch Linux on
<a href="/blog/why-i-am-getting-a-framework/">my Framework Laptop 13</a>, which I received
on the 3rd of July 2023, and am still as of today happily using!</p>

<p>I’m <em>extremely</em> impressed and very happy with this laptop - it is by far one of
the best devices I’ve owned in a long time. It is near-silent, It uses ~5watts
at idle, it’s fast, it’s sturdy and it looks good!</p>

<p>This is going to be quite a long article, so here’s a Table of Contents:</p>

<ul id="markdown-toc">
  <li><a href="#why-arch-linux" id="markdown-toc-why-arch-linux">Why Arch Linux</a></li>
  <li><a href="#bios-settings" id="markdown-toc-bios-settings">BIOS settings</a></li>
  <li><a href="#basic-installation" id="markdown-toc-basic-installation">Basic installation</a>    <ul>
      <li><a href="#additional-kernel-parameters-i-use" id="markdown-toc-additional-kernel-parameters-i-use">Additional kernel parameters I use</a></li>
    </ul>
  </li>
  <li><a href="#packages-i-install" id="markdown-toc-packages-i-install">Packages I install</a>    <ul>
      <li><a href="#additionally-install-when-you-want-to-run-virtual-machines-using-kvm-and-qemu" id="markdown-toc-additionally-install-when-you-want-to-run-virtual-machines-using-kvm-and-qemu">Additionally install when you want to run virtual machines using KVM and Qemu</a></li>
      <li><a href="#additionally-install-when-you-want-dynamic-application-of-power-management-settings" id="markdown-toc-additionally-install-when-you-want-dynamic-application-of-power-management-settings">Additionally install when you want dynamic application of power management settings</a></li>
      <li><a href="#additionally-install-when-you-want-to-use-dracut-instead-of-mkinitcpio" id="markdown-toc-additionally-install-when-you-want-to-use-dracut-instead-of-mkinitcpio">Additionally install when you want to use dracut instead of mkinitcpio</a></li>
      <li><a href="#additionally-install-when-you-use-x11-instead-of-wayland-and-want-gestures" id="markdown-toc-additionally-install-when-you-use-x11-instead-of-wayland-and-want-gestures">Additionally install when you use X11 instead of Wayland and want gestures</a></li>
      <li><a href="#additionally-install-on-devices-with-fingerprint-reader" id="markdown-toc-additionally-install-on-devices-with-fingerprint-reader">Additionally install on devices with fingerprint reader</a></li>
      <li><a href="#additionally-install-on-devices-with-intel-graphics" id="markdown-toc-additionally-install-on-devices-with-intel-graphics">Additionally install on devices with Intel graphics</a></li>
      <li><a href="#additionally-install-on-devices-with-amd-graphics" id="markdown-toc-additionally-install-on-devices-with-amd-graphics">Additionally install on devices with AMD graphics</a></li>
      <li><a href="#additionally-install-on-devices-with-nvidia-graphics" id="markdown-toc-additionally-install-on-devices-with-nvidia-graphics">Additionally install on devices with NVidia graphics</a></li>
      <li><a href="#installing-official-sublime-text-and-sublime-merge-packages" id="markdown-toc-installing-official-sublime-text-and-sublime-merge-packages">Installing official sublime-text and sublime-merge packages</a></li>
      <li><a href="#installing-lib32-package-equivalents-optional" id="markdown-toc-installing-lib32-package-equivalents-optional">Installing lib32 package equivalents (optional)</a></li>
    </ul>
  </li>
  <li><a href="#configure-networking" id="markdown-toc-configure-networking">Configure networking</a>    <ul>
      <li><a href="#configure-iwd" id="markdown-toc-configure-iwd">Configure iwd</a></li>
      <li><a href="#using-networkmanager-iwd-optional" id="markdown-toc-using-networkmanager-iwd-optional">Using networkmanager-iwd (optional)</a></li>
      <li><a href="#using-systemd-networkd-optional" id="markdown-toc-using-systemd-networkd-optional">Using systemd-networkd (optional)</a>        <ul>
          <li><a href="#setting-up-a-single-ethernet-device-with-dhcp" id="markdown-toc-setting-up-a-single-ethernet-device-with-dhcp">Setting up a single ethernet device with DHCP</a></li>
          <li><a href="#setting-up-a-bridge-device-with-dhcp" id="markdown-toc-setting-up-a-bridge-device-with-dhcp">Setting up a bridge device with DHCP</a></li>
          <li><a href="#setting-up-a-wireless-device-with-dhcp" id="markdown-toc-setting-up-a-wireless-device-with-dhcp">Setting up a wireless device with DHCP</a></li>
          <li><a href="#enable-systemd-networkd-and-iwd-services" id="markdown-toc-enable-systemd-networkd-and-iwd-services">Enable systemd-networkd and iwd services</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="#service-configuration" id="markdown-toc-service-configuration">Service configuration</a>    <ul>
      <li><a href="#displaylink" id="markdown-toc-displaylink">DisplayLink</a></li>
      <li><a href="#cpupower" id="markdown-toc-cpupower">CpuPower</a></li>
      <li><a href="#avahi" id="markdown-toc-avahi">Avahi</a></li>
      <li><a href="#bluetooth" id="markdown-toc-bluetooth">Bluetooth</a></li>
      <li><a href="#gdm" id="markdown-toc-gdm">GDM</a></li>
      <li><a href="#ollama" id="markdown-toc-ollama">Ollama</a></li>
      <li><a href="#docker" id="markdown-toc-docker">Docker</a></li>
      <li><a href="#libvirtd" id="markdown-toc-libvirtd">Libvirtd</a></li>
      <li><a href="#openssl" id="markdown-toc-openssl">OpenSSL</a></li>
      <li><a href="#nfsv4" id="markdown-toc-nfsv4">NFSv4</a></li>
      <li><a href="#samba" id="markdown-toc-samba">Samba</a></li>
      <li><a href="#tlp" id="markdown-toc-tlp">TLP</a></li>
      <li><a href="#cups" id="markdown-toc-cups">Cups</a></li>
      <li><a href="#cdemu" id="markdown-toc-cdemu">CDemu</a></li>
      <li><a href="#enabling-user-services" id="markdown-toc-enabling-user-services">Enabling user services</a></li>
    </ul>
  </li>
  <li><a href="#how-i-use-aur" id="markdown-toc-how-i-use-aur">How I use AUR</a>    <ul>
      <li><a href="#setting-up-your-own-custom-local-repository" id="markdown-toc-setting-up-your-own-custom-local-repository">Setting up your own custom local repository</a></li>
      <li><a href="#configuring-for-package-building" id="markdown-toc-configuring-for-package-building">Configuring for package building</a></li>
      <li><a href="#example-interactions-using-aur" id="markdown-toc-example-interactions-using-aur">Example interactions using AUR</a></li>
      <li><a href="#aur-packages-i-build-and-install" id="markdown-toc-aur-packages-i-build-and-install">AUR packages I build and install</a></li>
      <li><a href="#personal-aur-packages" id="markdown-toc-personal-aur-packages">Personal AUR packages</a></li>
    </ul>
  </li>
  <li><a href="#final-thoughts" id="markdown-toc-final-thoughts">Final thoughts</a></li>
</ul>

<h2 id="why-arch-linux">Why Arch Linux</h2>

<p>Prior to my Framework Laptop adventures, I’ve been planning to move to Arch
Linux for a while. I’m a long-time Linux desktop user. I started out with those
Red Hat CD-ROMs you’d buy at your local bookshop (this was around ‘96). I
fooled around with SCO UnixWare, had a whole period of SGI IRIX after that and
then some distro-hopping to Debian, Fedora, Arch Linux (in 2006), Gentoo and
Void Linux, more-or-less in that order.</p>

<p>The last two-ish years I’ve been running on Void Linux, which I still strongly
recommend and love - it’s a really good distribution with a nice balance between
stability and simplicity.</p>

<p>I used the OS package manager for the essentials, like Gnome, Firefox, the
terminal, Wayland and X11, and used <code class="language-plaintext highlighter-rouge">/opt</code> like a sort of <code class="language-plaintext highlighter-rouge">Program Files</code> or
<code class="language-plaintext highlighter-rouge">Applications</code> directory where I had my own programs like IntelliJ, Postman,
PostgreSQL, etc.</p>

<p>This works relatively well: you don’t have a lot of demands on package
availability in the distro itself and you keep things stable - only update your
own stuff when you feel like it and/or when you need to.</p>

<p>At a certain point I had about 70 applications in <code class="language-plaintext highlighter-rouge">/opt</code> which became a burden
to keep up to date, so I set out to find a distribution that packages as much
as possible of the software I use, and where packaging it yourself is as simple
as possible.</p>

<p>I definitely prefer a rolling-release distro. I checked out Nix, Gentoo and Arch
Linux. Nix I found really appealing (hard declarative) but I hated the syntax
(maybe Guix one day? I like Scheme better).</p>

<p>Gentoo did have a comparable set of packaged software available, and it <em>is</em>
one of my favorite distributions, but I had too many issues on my test-build
virtual machine which blocked me from experimenting prior to running it on my
daily driver.</p>

<p>So why move to Arch? Well, in one word: mind-share. The wiki, the amount of
packaged software, sane package standards:</p>

<ul>
  <li>The Arch wiki has essentially become the de-facto standard Linux wiki</li>
  <li>Really huge package collection, fantastic community participation with AUR</li>
  <li>Upstream stable usually means an upstream update is in repos within minutes</li>
  <li>Does not have separate dev/devel packages for headers</li>
</ul>

<p>The above three things means a lot of convenience to a Linux desktop user. On
Arch Linux, 99.9% of the software I ever used on Linux is packaged, most of it
in the official repositories and a few in AUR. Next to that, AUR and PKGBUILD
are so easy to get into, so you can easily package things yourself and share it
with the community.</p>

<p>On most other distros the gap between what’s packaged and what isn’t is quite
a bit larger which means you need alternative ways to get that software and keep
it up-to-date, which in practice becomes error-prone and time-consuming.</p>

<p>On Arch Linux I made the choice to run <em>everything</em> packaged with <code class="language-plaintext highlighter-rouge">pacman</code>. If
I need something that isn’t packaged yet (currently the case for 5 packages of
which I packaged one already), I package it and publish it to AUR.</p>

<p>The rest of this article is essentially a how-to with notes about what I run
and install. Feel free to peruse and/or replay!</p>

<h2 id="bios-settings">BIOS settings</h2>

<p>You can find the <a href="https://community.frame.work/t/bios-guide/4178">BIOS guide</a>
on the Framework community website. The only settings I changed were:</p>

<ul>
  <li>CPU Configuration -&gt; Boot Performance mode: <strong>MAX BATTERY</strong></li>
  <li>CPU Configuration -&gt; Intel Turbo Boost Max Technology 3.0: <strong>DISABLED</strong></li>
  <li>Secure Boot -&gt; Enforce Secure Boot: <strong>DISABLED</strong></li>
</ul>

<p>The above causes the laptop to effectively run in a lower TDP setting. I think
it goes from 28watts to 22watts. This has a dramatic effect on the battery life
and thermals of the device. I don’t want a wild beast that blasts the fans as
soon as I type <code class="language-plaintext highlighter-rouge">ls</code>, so these settings are great for me. Did I mention the
laptop performs really great with these settings?</p>

<p>With the above and the settings I configure in TLP I get ~3watts idle with
screen on normal brightness, Wi-Fi and Bluetooth enabled, and about ~45 celsius
core temperatures.</p>

<h2 id="basic-installation">Basic installation</h2>

<p>Basically, <a href="https://archlinux.org/download/">download</a> the ISO and follow the
<a href="https://wiki.archlinux.org/title/Installation_guide">installation guide</a>. I
opted to use <code class="language-plaintext highlighter-rouge">systemd-boot</code> as boot manager and either <code class="language-plaintext highlighter-rouge">systemd-networkd</code> or
<code class="language-plaintext highlighter-rouge">networkmanager-iwd</code> as my network configuration tooling.</p>

<h3 id="additional-kernel-parameters-i-use">Additional kernel parameters I use</h3>

<p>Whichever boot manager you use, you might want to set a few extra kernel
parameters. I found the following additionals handle a bunch of stuff nicely
on my Framework Laptop 13:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acpi_mask_gpe=0x1A acpi_osi="!Windows 2020" libata.allow_tpm=1 mem_sleep_default=deep net.ifnames=0 nvme.noacpi=1 nvme_core.default_ps_max_latency_us=0 root=LABEL=LINUX rtc_cmos.use_acpi_alarm=1 rw split_lock_detect=off tpm_tis.interrupts=0
</code></pre></div></div>

<h2 id="packages-i-install">Packages I install</h2>

<p>Next to the default <code class="language-plaintext highlighter-rouge">core</code> and <code class="language-plaintext highlighter-rouge">extra</code> repositories, I enable <code class="language-plaintext highlighter-rouge">multilib</code> in
<code class="language-plaintext highlighter-rouge">pacman.conf</code> before installing. Additionally, I blacklist <code class="language-plaintext highlighter-rouge">pam_systemd_home.so</code>
because I don’t use <code class="language-plaintext highlighter-rouge">systemd-homed</code> and it spams the journal on any login or
auth action:</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- pacman.conf.orig    2023-08-06 12:09:44.849855338 +0300
</span><span class="gi">+++ pacman.conf 2023-08-06 12:01:30.261984035 +0300
</span><span class="p">@@ -26,7 +26,7 @@</span>
 #IgnoreGroup =

 #NoUpgrade   =
<span class="gd">-#NoExtract   =
</span><span class="gi">+NoExtract    = usr/lib/security/pam_systemd_home.so
</span>
 # Misc options
 #UseSyslog
<span class="p">@@ -87,12 +87,11 @@</span>
 #[multilib-testing]
 #Include = /etc/pacman.d/mirrorlist

-#[multilib]
<span class="gd">-#Include = /etc/pacman.d/mirrorlist
</span><span class="gi">+[multilib]
+Include = /etc/pacman.d/mirrorlist
</span></code></pre></div></div>

<p>You can install the following packages right after your system comes up first
boot, or you could do it during install with <code class="language-plaintext highlighter-rouge">pacstrap</code> (it doesn’t really
matter, but in any case, make sure <code class="language-plaintext highlighter-rouge">core</code>, <code class="language-plaintext highlighter-rouge">contrib</code> and <code class="language-plaintext highlighter-rouge">multilib</code> are enabled
in <code class="language-plaintext highlighter-rouge">/etc/pacman.conf</code> first):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> acpi acpica acpi_call-dkms acpid alacritty alsa-firmware alsa-tools alsa-ucm-conf alsa-utils ansible-language-server ansible-lint ant antlr4 ardour aribb25 arj autoconf automake aws-cli base-devel bash bash-language-server bc bear <span class="nb">bind </span>biome bison blender bower btop bubblewrap bun busted bustle calibre cameractrls carla cdemu-client cdemu-daemon cdrdao cdrtools chawan chntpw cifs-utils clang clinfo clojure cmake corkscrew cpio cppcheck cpupower ctags cue cups curl dagger dash dconf-editor dcraw ddcutil debugedit delve deno desmume devtools direnv distrobox dive dmidecode dmraid dnsmasq docker docker-buildx docker-compose dool dos2unix dosfstools doxygen d-spy dvd+rw-tools dvisvgm editorconfig-checker editorconfig-core-c efibootmgr elixir emacs-wayland erlang eslint ethtool exfatprogs extra-cmake-modules fakeroot fastfetch fd fdupes file file-roller fio firefox flex fltk1.3 fontforge foomatic-db-engine foomatic-db-nonfree-ppds foomatic-db-ppds fractal freetype2-demos fs-uae fs-uae-launcher furnace fwupd fzf gamemode gamescope gcc gdb gdm gemini-cli ghidra gimp git git-filter-repo github-cli git-lfs glab gnome-backgrounds gnome-browser-connector gnome-calculator gnome-characters gnome-control-center gnome-disk-utility gnome-logs gnome-session gnome-settings-daemon gnome-shell gnome-shell-extension-appindicator gnome-shell-extension-desktop-icons-ng gnome-shell-extensions gnome-system-monitor gnome-themes-extra gnome-tweaks gnupg gnuplot go gopls go-tools gparted gperf gradle groovy gtksourceview3 gtkwave guile gvfs gvfs-gphoto2 gvfs-mtp gvfs-nfs gvfs-smb handbrake harfbuzz-cairo hdparm helix helm hplip htop hunspell hunspell-de hunspell-en_gb hunspell-en_us hunspell-es_es hunspell-fr hunspell-nl i2c-tools ifuse img2pdf inetutils inkscape iperf3 iptables-nft irssi iverilog iwd jekyll jfsutils jq jupyterlab jupyterlab-lsp jupyter-lsp jupyter-notebook just k9s kafka kddockwidgets kotlin kubeconform kubectl kubeseal leiningen lhasa libblockdev-crypto libblockdev-dm libblockdev-fs libblockdev-loop libblockdev-lvm libblockdev-mdraid libblockdev-mpath libblockdev-nvme libblockdev-part libblockdev-swap libebur128 libgoom2 libindicator-gtk3 librecad libreoffice-still libretro-beetle-pce libretro-beetle-psx-hw libretro-blastem libretro-core-info libretro-desmume libretro-dolphin libretro-flycast libretro-mame libretro-mgba libretro-mupen64plus-next libretro-nestopia libretro-picodrive libretro-ppsspp libretro-sameboy libretro-scummvm libretro-snes9x libtiger libva-mesa-driver libva-utils libvirt libwebp-utils libxcrypt-compat linux-firmware-bnx2x linux-firmware-liquidio linux-firmware-mellanox linux-firmware-nfp linux-firmware-qlogic linux-headers live-media lld lldb lm_sensors loupe lshw lsof lsscsi ltrace lua-language-server make mame mame-tools man-db mangohud man-pages mattermost-desktop maven mbedtls2 mednafen mesa-demos mesa-utils meson mgba-qt minikube mitmproxy mono mono-msbuild moreutils mpv mtools multipath-tools mupdf-tools mupen64plus mutter nasm nautilus nbd neovide neovim netbeans networkmanager-openvpn networkmanager-vpn-plugin-openvpn net-tools nfs-utils ninja nmap nodejs noto-fonts-emoji npm ntfs-3g nuget nvchecker nvme-cli nvtop ollama openai-codex openbsd-netcat opencl-clhpp opencl-headers opencode openldap openssh openvpn osv-scanner p7zip pacman-contrib pacutils papers papirus-icon-theme patch patchelf pciutils pdfarranger perf perl perl-lwp-protocol-https perl-net-dbus perl-x11-protocol perl-yaml pinentry piper pipewire pipewire-alsa pipewire-jack pipewire-libcamera pipewire-pulse pipewire-v4l2 pkgconf postgresql powertop ppsspp prettier projectm protonmail-bridge psutils python python-jsbeautifier python-jwcrypto python-kubernetes python-ldap python-lsp-server python-nose python-numpy python-opengl python-patch-ng python-pip python-pycryptodomex python-pylint python-pyopenssl python-pytest python-rope python-setuptools python-sphinx python-sphinx-autobuild python-sympy python-websockets python-wheel qbittorrent qjackctl qpwgraph qt5ct qt5-declarative qt5-tools qt5-wayland qt6ct qt6-multimedia-ffmpeg qt6-tools qt6-wayland quodlibet rabbitmq racket ranger realtime-privileges rebuild-detector recode retroarch retroarch-assets-glui retroarch-assets-ozone ripgrep rlwrap rsync ruby ruby-base64 ruby-bigdecimal ruby-csv ruby-default-gems ruby-irb ruby-rake-compiler rustup samba sane sbt scons screen scummvm sdcc sdl2_mixer seahorse seatd shfmt signal-desktop simple-scan smartmontools smbclient snapshot snes9x-gtk sof-firmware sox speedtest-cli squashfs-tools steam step-ca step-cli stern strace s-tui stylelint <span class="nb">sudo </span>syncthing sysdig sysprof sysstat tailwindcss-language-server taplo-cli <span class="nb">tar </span>terminus-font texinfo texlab texlive-basic texlive-bin texlive-fontsrecommended texlive-latex texlive-latexextra texlive-latexrecommended texlive-pictures the_silver_searcher thunderbird tidy tinyxxd tmux tokei traceroute tracker3-miners tree tree-sitter-cli tree-sitter-grammars ttf-ibm-plex ttf-ubuntu-font-family turbostat twine typescript typescript-language-server udftools udisks2-lvm2 uncrustify unixodbc unzip urlwatch usbutils util-linux uucp valgrind valkey vdpauinfo vhba-module-dkms vkd3d vscode-css-languageserver vscode-html-languageserver vscode-json-languageserver vue-language-server vulkan-tools w3m wayland-utils wgetpaste whois wimlib wine wine-mono wireless-regdb wireless_tools wireplumber wireshark-cli wireshark-qt wl-clipboard wmctrl wol xcb-util-errors xchm xclip xdelta3 xdg-desktop-portal-gnome xdg-user-dirs-gtk xdg-utils xdotool xfsprogs xmlstarlet xorg-fonts-100dpi xorg-fonts-misc xorg-font-util xorg-mkfontscale xorg-server xorg-server-devel xorg-xauth xorg-xdpyinfo xorg-xdriinfo xorg-xev xorg-xfontsel xorg-xhost xorg-xinit xorg-xinput xorg-xkill xorg-xlsclients xorg-xprop xorg-xrandr xorg-xrdb xorg-xset xorg-xsetroot xorg-xvinfo xorg-xwayland xorg-xwininfo yarn yasm yq yt-dlp zig zip zls zstd
</code></pre></div></div>

<h3 id="additionally-install-when-you-want-to-run-virtual-machines-using-kvm-and-qemu">Additionally install when you want to run virtual machines using KVM and Qemu</h3>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> qemu-full libvirt virt-manager
</code></pre></div></div>

<p>Note that the <code class="language-plaintext highlighter-rouge">qemu-full</code> package depends on <code class="language-plaintext highlighter-rouge">qemu-chardev-baum</code> which in turn
pulls in <code class="language-plaintext highlighter-rouge">brltty</code>, a braille (virtual?) keyboard service. If you don’t need 
that:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-R</span> qemu-chardev-baum qemu-full brltty
userdel brltty
</code></pre></div></div>

<p>Later on in this guide we’ll set up <code class="language-plaintext highlighter-rouge">libvirt</code> so you can use <code class="language-plaintext highlighter-rouge">virt-manager</code>
comfortably.</p>

<h3 id="additionally-install-when-you-want-dynamic-application-of-power-management-settings">Additionally install when you want dynamic application of power management settings</h3>

<p>You can install <code class="language-plaintext highlighter-rouge">tlp</code> to enable dynamically applying power management settings,
based on if your power connector is connected or if you’re on battery. We also
install <code class="language-plaintext highlighter-rouge">tlp-pd</code> which is the TLP project’s DBUS interface compatible
implementation of <code class="language-plaintext highlighter-rouge">power-profile-daemon</code> (which itself conflicts with <code class="language-plaintext highlighter-rouge">tlp</code>).
Installing <code class="language-plaintext highlighter-rouge">tlp-pd</code> Makes it possible to control TLP from things like Gnome,
Cosmic, KDE, etc.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> tlp tlp-pd
systemctl <span class="nb">enable</span> <span class="nt">--now</span> tlp-pd
</code></pre></div></div>

<h3 id="additionally-install-when-you-want-to-use-dracut-instead-of-mkinitcpio">Additionally install when you want to use dracut instead of mkinitcpio</h3>

<p>I use <code class="language-plaintext highlighter-rouge">dracut</code> on my desktop computer, because I need working LVM RAID mirrors
there. I couldn’t get that to work with <code class="language-plaintext highlighter-rouge">mkinitcpio</code> based initrd.</p>

<p>If you want to use <code class="language-plaintext highlighter-rouge">dracut</code> instead of <code class="language-plaintext highlighter-rouge">mkinitcpio</code> to generate initrd images,
you need to install it and remove the default initrd tooling:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> dracut
pacman <span class="nt">-R</span> mkinitcpio mkinitcpio-busybox
</code></pre></div></div>

<p>Note that there are no hooks by default for rebuilding dracut-based initrd
images, so you’d need to do that manually after <code class="language-plaintext highlighter-rouge">linux</code> kernel package updates.
For example:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Kernel version in package contains dot, on-disk it contains dash, hence the sed.</span>
<span class="nb">export </span><span class="nv">KERNEL_VERSION</span><span class="o">=</span><span class="si">$(</span>pacman <span class="nt">-Q</span> linux | <span class="nb">awk</span> <span class="s1">'{print $2}'</span> | <span class="nb">sed</span> <span class="s1">'s|\.arch|-arch|g'</span><span class="si">)</span>
<span class="nb">cp</span> /lib/modules/<span class="nv">$KERNEL_VERSION</span>/vmlinuz /boot/vmlinuz-linux
dracut <span class="nt">--kver</span> <span class="nv">$KERNEL_VERSION</span> <span class="nt">--force</span> /boot/initramfs-linux-fallback.img
dracut <span class="nt">--hostonly</span> <span class="nt">--no-hostonly-cmdline</span> <span class="nt">--kver</span> <span class="nv">$KERNEL_VERSION</span> <span class="nt">--force</span> /boot/initramfs-linux.img
</code></pre></div></div>

<h3 id="additionally-install-when-you-use-x11-instead-of-wayland-and-want-gestures">Additionally install when you use X11 instead of Wayland and want gestures</h3>

<p>Wayland provides working gestures on Gnome out of the box, and Wayland is the
default on Arch Linux. If, however, you have some reason to use X11 instead of
Wayland by default and you want gestures to work, you can install Touchégg:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> touchegg
</code></pre></div></div>

<p>Make sure you enable the service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> touchegg
</code></pre></div></div>

<p>And also install the required Gnome <a href="https://github.com/JoseExposito/gnome-shell-extension-x11gestures">extension</a>.</p>

<h3 id="additionally-install-on-devices-with-fingerprint-reader">Additionally install on devices with fingerprint reader</h3>

<p>Devices like the Framework Laptop 13 have a fingerprint reader. If you want to
use it, make sure to install the following packages:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> libfprint fprintd
</code></pre></div></div>

<p>And make sure you enable the service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> fprintd
</code></pre></div></div>

<p>To configure the fingerprint reader, I needed to upgrade the firmware. Version
<code class="language-plaintext highlighter-rouge">01000320</code> is known to not work with Linux. In my case, I had to use an older
version of <code class="language-plaintext highlighter-rouge">fwupd</code> (version 1.9.5 to be specific) - 1.9.10 did not work, but
I’ve had a report recently (thanks, Jan Schoone) that <code class="language-plaintext highlighter-rouge">fwupd</code> version 1.9.13
and possibly higher, does actually work these days (your milage may vary, etc).</p>

<p>In any case, I followed the instructions <a href="https://knowledgebase.frame.work/en_us/updating-fingerprint-reader-firmware-on-linux-for-13th-gen-and-amd-ryzen-7040-series-laptops-HJrvxv_za">here</a>
to update to the required firmware version <code class="language-plaintext highlighter-rouge">01000330</code> to make the fingerprint
reader work with Linux. Instructions below are based on the linked document:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># First downgrade fwupd...</span>
wget <span class="nt">--continue</span> https://archive.archlinux.org/packages/f/fwupd/fwupd-1.9.5-2-x86_64.pkg.tar.zst <span class="nt">--output</span> fwupd-1.9.5-2-x86_64.pkg.tar.zst
pacman <span class="nt">-U</span> fwupd-1.9.5-2-x86_64.pkg.tar.zst
<span class="c"># Get firmware file and install...</span>
wget <span class="nt">--continue</span> https://github.com/FrameworkComputer/linux-docs/raw/main/goodix-moc-609c-v01000330.cab <span class="nt">--output</span> goodix-moc-609c-v01000330.cab
fwupdtool <span class="nb">install</span> <span class="nt">--allow-reinstall</span> <span class="nt">--allow-older</span> goodix-moc-609c-v01000330.cab
</code></pre></div></div>

<p>Note: There might be a transfer error mentioned at the end. This can be safely
ignored. Reboot and start a fresh terminal and show the device:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fwupdmgr get-devices 1e8c8470-a49c-571a-82fd-19c9fa32b8c3
</code></pre></div></div>

<p>Note: The above command sometimes times out the first time it’s run. Just run it
again and you’ll see some details about the fingerprint reader. Notably, the
version should now be: <code class="language-plaintext highlighter-rouge">01000330</code>. You can now enroll fingerprints.</p>

<p>If your fingerprint reader is working, you can continue to follow the steps
<a href="https://wiki.archlinux.org/title/Fprint">here</a> to set it up for usage.</p>

<h3 id="additionally-install-on-devices-with-intel-graphics">Additionally install on devices with Intel graphics</h3>

<p>My Framework Laptop 13 is intel-based, so I install these packages additionally:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> intel-gpu-tools vulkan-intel intel-media-driver libvdpau-va-gl intel-graphics-compiler intel-compute-runtime gst-plugin-va opencv python-opencv
</code></pre></div></div>

<p>Also, from AUR, I install these, making sure their version is synced with the
above mentioned 64-bit versions, These make it possible for 32-bit apps to also
use VAAPI-based hardware acceleration:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lib32-intel-gmmlib
lib32-intel-media-driver
</code></pre></div></div>

<h3 id="additionally-install-on-devices-with-amd-graphics">Additionally install on devices with AMD graphics</h3>

<p>If you have an AMD device instead, you might want these ones:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> radeontop vulkan-radeon gst-plugin-va ollama-rocm opencv python-opencv
</code></pre></div></div>

<h3 id="additionally-install-on-devices-with-nvidia-graphics">Additionally install on devices with NVidia graphics</h3>

<p>If you have an NVidia device instead, you might want these ones:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-S</span> <span class="nt">--needed</span> cuda ffnvcodec-headers libva-nvidia-driver nvidia-cg-toolkit nvidia-settings nvidia-utils nvidia-open-dkms nvtop opencl-nvidia openssl-1.1 gst-plugins-bad ollama-cuda opencv-cuda python-opencv-cuda nsight-compute nsight-systems
</code></pre></div></div>

<p>Note: The <code class="language-plaintext highlighter-rouge">openssl-1.1</code> package is a (missing) dependency for
<code class="language-plaintext highlighter-rouge">libnvidia-pkcs11.so</code> contained in <code class="language-plaintext highlighter-rouge">nvidia-utils</code>.</p>

<p>Note 2: The <code class="language-plaintext highlighter-rouge">opencv-cuda</code> and <code class="language-plaintext highlighter-rouge">python-opencv-cuda</code> packages replace the <code class="language-plaintext highlighter-rouge">opencv</code>
and <code class="language-plaintext highlighter-rouge">python-opencv</code> packages installed previously.</p>

<h3 id="installing-official-sublime-text-and-sublime-merge-packages">Installing official sublime-text and sublime-merge packages</h3>

<p><a href="https://www.sublimetext.com/">Sublime Text</a> has an official Arch linux
repository for its <code class="language-plaintext highlighter-rouge">sublime-text</code> and <code class="language-plaintext highlighter-rouge">sublime-merge</code> packages. If you want to
use those, do the following (as root):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install and sign the sublimehq pubkey.</span>
curl <span class="nt">-O</span> https://download.sublimetext.com/sublimehq-pub.gpg
pacman-key <span class="nt">--add</span> sublimehq-pub.gpg
pacman-key <span class="nt">--lsign-key</span> 8A8F901A
<span class="nb">rm </span>sublimehq-pub.gpg

<span class="c"># Add sublime-text package repository to pacman.conf.</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt;&gt; "/etc/pacman.conf"
# Official Sublime Text and Sublime Merge repository.
[sublime-text]
SigLevel = Required DatabaseRequired TrustedOnly
Server = https://download.sublimetext.com/arch/stable/x86_64
</span><span class="no">EOF

</span><span class="c"># Update local pacman databases and install.</span>
pacman <span class="nt">-Syu</span> sublime-text sublime-merge
</code></pre></div></div>

<p>The above is based on <a href="https://www.sublimetext.com/docs/linux_repositories.html#pacman">these instructions</a>.</p>

<h3 id="installing-lib32-package-equivalents-optional">Installing lib32 package equivalents (optional)</h3>

<p>I like to install the lib32-* package equivalents of packages I installed. There
isn’t an easy way to do this and it is a bit messy, but here’s how I do it:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Clean beginnings.</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> ~/Desktop
<span class="nb">rm</span> ~/Desktop/lib32-candidates ~/Desktop/lib32-notfound

<span class="c"># Append a list of possible lib32-* package names by prepending to package name.</span>
<span class="k">for </span>p <span class="k">in</span> <span class="sb">`</span>pacman <span class="nt">-Qq</span> | <span class="nb">grep</span> <span class="nt">-v</span> lib32<span class="sb">`</span><span class="p">;</span> <span class="k">do </span><span class="nb">echo </span>lib32-<span class="nv">$p</span> <span class="o">&gt;&gt;</span> ~/Desktop/lib32-candidates<span class="p">;</span> <span class="k">done</span>

<span class="c"># Append a list of possible lib32-* package names which consist of lib32-firstnamepart.</span>
<span class="k">for </span>p <span class="k">in</span> <span class="sb">`</span>pacman <span class="nt">-Qq</span> | <span class="nb">grep</span> <span class="nt">-v</span> lib32 | <span class="nb">cut</span> <span class="nt">-d-</span> <span class="nt">-f1</span> | <span class="nb">sort</span> <span class="nt">-u</span><span class="sb">`</span><span class="p">;</span> <span class="k">do </span><span class="nb">echo </span>lib32-<span class="nv">$p</span> <span class="o">&gt;&gt;</span> ~/Desktop/lib32-candidates<span class="p">;</span> <span class="k">done</span>

<span class="c"># Remove known-not-working elements and make sure the output file is sorted and unique.</span>
<span class="nb">cat</span> ~/Desktop/lib32-candidates | <span class="nb">grep</span> <span class="nt">-v</span> rustup | <span class="nb">grep</span> <span class="nt">-v</span> openssl-1.1 | <span class="nb">grep</span> <span class="nt">-v</span> mesa-amber | <span class="nb">grep</span> <span class="nt">-v</span> mesa-demos | <span class="nb">sort</span> <span class="nt">-u</span> <span class="nt">-o</span> ~/Desktop/lib32-candidates

<span class="c"># Abuse pacman -S to obtain invalid package names.</span>
pacman <span class="nt">-S</span> <span class="nt">--needed</span> <span class="sb">`</span><span class="nb">cat</span> ~/Desktop/lib32-candidates | <span class="nb">sort</span> <span class="nt">-u</span><span class="sb">`</span> 2&gt;&amp;1 | <span class="nb">grep</span> <span class="s1">'error: target not found'</span> | <span class="nb">awk</span> <span class="s1">'{print $5}'</span> <span class="o">&gt;</span> ~/Desktop/lib32-notfound

<span class="c"># Make sure that's sorted and unique too.</span>
<span class="nb">sort</span> <span class="nt">-o</span> ~/Desktop/lib32-notfound ~/Desktop/lib32-notfound

<span class="c"># Use comm to diff the lists and only feed valid package names to pacman -S.</span>
pacman <span class="nt">-S</span> <span class="nt">--needed</span> <span class="sb">`</span><span class="nb">comm</span> <span class="nt">-23</span> ~/Desktop/lib32-candidates ~/Desktop/lib32-notfound<span class="sb">`</span>
</code></pre></div></div>

<h2 id="configure-networking">Configure networking</h2>

<p>You can configure networking in all kinds of ways, but the two I document are
<code class="language-plaintext highlighter-rouge">networkmanager-iwd</code> and <code class="language-plaintext highlighter-rouge">systemd-networkd</code>.</p>

<p>I specifically chose <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code>, because I have had extensive
problems with <code class="language-plaintext highlighter-rouge">wpa_supplicant</code> in combination with high performance network
requirements, like when you need to stream a 4K desktop at 60fps. Due to how
<code class="language-plaintext highlighter-rouge">wpa_supplicant</code> is instrumented by NetworkManager, that kind of use-case is
virtually impossible to get right. <code class="language-plaintext highlighter-rouge">iwd</code> seems to handle this use-case much
better and so I opt to use that in combination with <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code>.</p>

<p>Note that <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code> is an AUR package that uses <code class="language-plaintext highlighter-rouge">iwd</code> exclusively
and does <em>not</em> require or depend on <code class="language-plaintext highlighter-rouge">wpa_supplicant</code> in any way.</p>

<h3 id="configure-iwd">Configure iwd</h3>

<p>First configure <code class="language-plaintext highlighter-rouge">iwd</code> defaults:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> /etc/iwd
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/iwd/main.conf"
[General]
RoamThreshold=-80
RoamThreshold5G=-80
CriticalRoamThreshold=-90
CriticalRoamThreshold5G=-90

[Network]
EnableIPv6=true
NameResolvingService=systemd

[Scan]
DisablePeriodicScan=true
DisableRoamingScan=true
MaximumPeriodicScanInterval=3600

[DriverQuirks]
PowerSaveDisable=iwlwifi
</span><span class="no">EOF
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">iwd</code> can be configured using <code class="language-plaintext highlighter-rouge">iwctl</code>, or it is managed completely by
<code class="language-plaintext highlighter-rouge">networkmanager-iwd</code>. See the <a href="https://wiki.archlinux.org/title/Iwd">iwd</a> page
on the Arch wiki for more details about <code class="language-plaintext highlighter-rouge">iwd</code>.</p>

<h3 id="using-networkmanager-iwd-optional">Using networkmanager-iwd (optional)</h3>

<p>I’ve opted to use <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code> from AUR to manage my networking needs
because as it stands, it integrates much nicelier with graphical environments
like Gnome, Cosmic and KDE. To use <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code>, you first need to
build the <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code> package. See the section about how to
<a href="#configuring-for-package-building">configure for package building</a> for more
information about how do that.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl disable <span class="nt">--now</span> systemd-networkd <span class="c"># systemd-networkd needs to be off</span>
systemctl disable <span class="nt">--now</span> iwd <span class="c"># iwd is managed by networkmanager itself</span>
systemctl <span class="nb">enable</span> <span class="nt">--now</span> NetworkManager <span class="c"># enable networkmanager</span>
</code></pre></div></div>

<p>See the <a href="https://wiki.archlinux.org/title/NetworkManager">NetworkManager</a> page
on the Arch Wiki for details about how to use and configure NetworkManager. In
practice, you’ll find it’s pretty straight-forward and that it can usually be
configured graphically through your desktop environment of choice.</p>

<h3 id="using-systemd-networkd-optional">Using systemd-networkd (optional)</h3>

<p>As an alternative to <code class="language-plaintext highlighter-rouge">networkmanager-iwd</code>, you can use <code class="language-plaintext highlighter-rouge">systemd-networkd</code> to
configure your network. This comes down to placing configuration files in
<code class="language-plaintext highlighter-rouge">/etc/systemd/network</code>. and enabling the <code class="language-plaintext highlighter-rouge">systemd-networkd</code> services.</p>

<h4 id="setting-up-a-single-ethernet-device-with-dhcp">Setting up a single ethernet device with DHCP</h4>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/systemd/network/10-ethernet.network"
[Match]
Name=eth0

[Link]
RequiredForOnline=routable

[Network]
DHCP=yes
IgnoreCarrierLoss=10s
UseDomains=false

[DHCPv4]
RouteMetric=700
UseNTP=no
UseDNS=no
UseGateway=yes
UseRoutes=no

[IPv6AcceptRA]
RouteMetric=700
</span><span class="no">EOF
</span></code></pre></div></div>

<h4 id="setting-up-a-bridge-device-with-dhcp">Setting up a bridge device with DHCP</h4>

<p>Note that this is an alternative to the single ethernet configuration shown
previously. Let’s first create the physical device bind config:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/systemd/network/10-bind.network"
[Match]
Name=eth0 eth1

[Network]
Bridge=bridge0
</span><span class="no">
EOF
</span></code></pre></div></div>

<p>Create the virtual bridge device:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/systemd/network/10-bridge.netdev"
[NetDev]
Name=bridge0
Kind=bridge
MACAddress=52:41:41:46:00:0b
</span><span class="no">EOF
</span></code></pre></div></div>

<p>And finally, the bridge network, configured by DHCP:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/systemd/network/10-bridge.network"
[Match]
Name=bridge0

[Link]
RequiredForOnline=routable

[Network]
DHCP=yes
IgnoreCarrierLoss=10s
UseDomains=false

[DHCPv4]
RouteMetric=700
UseNTP=no
UseDNS=no
UseGateway=yes
UseRoutes=no

[IPv6AcceptRA]
RouteMetric=700
</span><span class="no">EOF
</span></code></pre></div></div>

<h4 id="setting-up-a-wireless-device-with-dhcp">Setting up a wireless device with DHCP</h4>

<p>Note that you first need to configure <code class="language-plaintext highlighter-rouge">iwd</code> to authenticate and connect to your
wireless network. After that, tell <code class="language-plaintext highlighter-rouge">systemd-networkd</code> about it:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/systemd/network/10-wireless.network"
[Match]
Name=wlan0

[Link]
RequiredForOnline=routable

[Network]
DHCP=yes
IgnoreCarrierLoss=10s
UseDomains=true

[DHCPv4]
RouteMetric=600

[IPv6AcceptRA]
RouteMetric=600
</span><span class="no">EOF
</span></code></pre></div></div>

<h4 id="enable-systemd-networkd-and-iwd-services">Enable systemd-networkd and iwd services</h4>

<p>Enable <code class="language-plaintext highlighter-rouge">systemd-networkd</code> and <code class="language-plaintext highlighter-rouge">iwd </code>with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl disable <span class="nt">--now</span> NetworkManager <span class="c"># networkmanager needs to be off</span>
systemctl <span class="nb">enable</span> <span class="nt">--now</span> iwd.service <span class="c"># iwd is not managed by systemd-networkd</span>
systemctl <span class="nb">enable</span> <span class="nt">--now</span> systemd-networkd.service <span class="c"># enable systemd-networkd</span>
systemctl disable <span class="nt">--now</span> systemd-networkd-wait-online.service <span class="c"># not this one</span>
</code></pre></div></div>

<p>Note that we disable the waiting service, since we want to continue booting
even if there is no network. If you would like to know more about how you can
configure <code class="language-plaintext highlighter-rouge">systemd-networkd</code>, be sure to read the
<a href="https://wiki.archlinux.org/title/Systemd-networkd">systemd-networkd</a> page on
the Arch wiki.</p>

<h2 id="service-configuration">Service configuration</h2>

<p>I use and customize a bunch of services on my device. So I don’t forget what
I customized and why, let me document it.</p>

<h3 id="displaylink">DisplayLink</h3>

<p>The <code class="language-plaintext highlighter-rouge">displaylink</code> service is used, together with the <code class="language-plaintext highlighter-rouge">evdi</code> driver, to handle
externally connected displays, which connect through a dock or other type of
USB3 or Thunderbolt connection. Enable it as follows:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> displaylink
</code></pre></div></div>

<p>Additionally, I’ve observed that the <code class="language-plaintext highlighter-rouge">displaylink</code> service consumes an
inordinate amount of CPU time after a suspend/resume cycle. A quick restart of
the service works around that. To do that automatically, we can create a systemd
unit file and enable it:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Write the systemd unit file for restarting displaylink on resume:</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/systemd/system/displaylink-restart.service"
[Unit]
Description=Restart DisplayLink after resume
After=suspend.target

[Service]
Type=simple
ExecStart=/bin/systemctl --no-block restart displaylink.service

[Install]
WantedBy=suspend.target
</span><span class="no">EOF

</span><span class="c"># Enable and start the automatic displaylink restart service:</span>
systemctl <span class="nb">enable</span> <span class="nt">--now</span> displaylink-restart
</code></pre></div></div>

<h3 id="cpupower">CpuPower</h3>

<p>The <code class="language-plaintext highlighter-rouge">cpupower</code> service reads from <code class="language-plaintext highlighter-rouge">/etc/default/cpupower</code> and configures the
default scheduler. Edit that file to set the default scheduler to <code class="language-plaintext highlighter-rouge">powersave</code> or
<code class="language-plaintext highlighter-rouge">performance </code>and then enable it:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> cpupower.service
</code></pre></div></div>

<h3 id="avahi">Avahi</h3>

<p>I don’t want any service auto-configuring stuff on my system, especially things
like printers for example. Therefore I disable the Avahi zeroconf service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl mask avahi-daemon.service
systemctl mask avahi-daemon.socket
systemctl mask avahi-dnsconfd.service
</code></pre></div></div>

<p>Note that a side-effect of this, is that when you use something like <code class="language-plaintext highlighter-rouge">xsane</code> or
<code class="language-plaintext highlighter-rouge">simplescan</code>, you will get a password prompt dialog every time you start the
scanning tool. This is because, apparently, these tools use <code class="language-plaintext highlighter-rouge">avahi</code> somehow,
which then has to be invoked, which is then done through <code class="language-plaintext highlighter-rouge">polkit</code>, which raises
the password dialog so the <code class="language-plaintext highlighter-rouge">avahi</code> service can be started. Yeah.</p>

<h3 id="bluetooth">Bluetooth</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">bluetooth</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> bluetooth.service
</code></pre></div></div>

<p>Bluetooth mostly just works out of the box, except for my XBox Series X|S
Wireless Game Controller. To get this to run, I use the <code class="language-plaintext highlighter-rouge">xpadneo-dkms</code> AUR
package. Additionally, I need to configure a few settings in
<code class="language-plaintext highlighter-rouge">/etc/bluetooth/main.conf</code> (add or set these settings yourself, or use <code class="language-plaintext highlighter-rouge">patch</code>
to apply the settings to your <code class="language-plaintext highlighter-rouge">main.conf</code>):</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- main.conf.orig  2023-07-31 19:01:29.473651656 +0300
</span><span class="gi">+++ main.conf 2023-08-01 23:39:23.294653784 +0300
</span><span class="p">@@ -49,7 +49,7 @@</span>
 # Restricts all controllers to the specified transport. Default value
 # is "dual", i.e. both BR/EDR and LE enabled (when supported by the HW).
 # Possible values: "dual", "bredr", "le"
<span class="gd">-#ControllerMode = dual
</span><span class="gi">+ControllerMode = dual
</span>
 # Maximum number of controllers allowed to be exposed to the system.
 # Default=0 (unlimited)
<span class="p">@@ -100,7 +100,7 @@</span>
 # Specify the policy to the JUST-WORKS repairing initiated by peer
 # Possible values: "never", "confirm", "always"
 # Defaults to "never"
<span class="gd">-#JustWorksRepairing = never
</span><span class="gi">+JustWorksRepairing = confirm
</span>
 # How long to keep temporary devices around
 # The value is in seconds. Default is 30.
<span class="p">@@ -212,9 +212,9 @@</span>

 # LE default connection parameters.  These values are superceeded by any
 # specific values provided via the Load Connection Parameters interface
<span class="gd">-#MinConnectionInterval=
-#MaxConnectionInterval=
-#ConnectionLatency=
</span><span class="gi">+MinConnectionInterval=7
+MaxConnectionInterval=9
+ConnectionLatency=0
</span> #ConnectionSupervisionTimeout=
 #Autoconnecttimeout=

@@ -318,7 +318,7 @@
 # AutoEnable defines option to enable all controllers when they are found.
 # This includes adapters present on start as well as adapters that are plugged
 # in later on. Defaults to 'true'.
<span class="gd">-#AutoEnable=true
</span><span class="gi">+AutoEnable=false
</span>
 # Audio devices that were disconnected due to suspend will be reconnected on
 # resume. ResumeDelay determines the delay between when the controller
</code></pre></div></div>

<p>After changes, restart the service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart bluetooth.service
</code></pre></div></div>

<h3 id="gdm">GDM</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">gdm</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> gdm.service
</code></pre></div></div>

<p>I prefer auto-login on some of my devices (no on laptop, yes on desktop). Add
the two lines or apply the below diff to <code class="language-plaintext highlighter-rouge">/etc/gdm/custom.conf</code> using <code class="language-plaintext highlighter-rouge">patch</code>
if you would like your user to allow GDM to automatically login (don’t forget
to replace <code class="language-plaintext highlighter-rouge">$USER</code> with your user name):</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- custom.conf.orig  2023-07-31 19:08:35.307832755 +0300
</span><span class="gi">+++ custom.conf 2023-07-31 19:08:25.741219958 +0300
</span><span class="p">@@ -1,6 +1,8 @@</span>
 # GDM configuration storage

 [daemon]
<span class="gi">+AutomaticLogin=$USER
+AutomaticLoginEnable=True
</span> # Uncomment the line below to force the login screen to use Xorg
 #WaylandEnable=false
</code></pre></div></div>

<p>Reboot for the above to take effect.</p>

<h3 id="ollama">Ollama</h3>

<p>The <code class="language-plaintext highlighter-rouge">ollama</code> service makes it possible to easily run AI models locally using
<code class="language-plaintext highlighter-rouge">llama-cpp</code>. Just like docker, this runs as a service and you use the <code class="language-plaintext highlighter-rouge">ollama</code>
command line utility to interact with it.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> ollama.service
</code></pre></div></div>

<p>Remember to install <code class="language-plaintext highlighter-rouge">ollama-cuda</code> or <code class="language-plaintext highlighter-rouge">ollama-rocm</code> if you are using NVIDIA or
AMD devices respectively (see earlier chapter about that).</p>

<p>After the service is enabled and running, you can run a model as follows (we’re
using the <code class="language-plaintext highlighter-rouge">deepcoder</code> model here as an example):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ollama run deepcoder
</code></pre></div></div>

<p>This will download the model and start an interactive prompt.</p>

<h3 id="docker">Docker</h3>

<p>First make sure <code class="language-plaintext highlighter-rouge">containerd</code> (a dependency for <code class="language-plaintext highlighter-rouge">docker</code>) does not load plugins
which are not relevant for this setup (these plugins cause loading errors in a
default setup like we’re building - this does not break, but it does cause a
lot of regular error messages in <code class="language-plaintext highlighter-rouge">journalctl</code>):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> /etc/containerd
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/containerd/config.toml"

version = 3
disabled_plugins = ["io.containerd.snapshotter.v1.blockfile", "io.containerd.snapshotter.v1.btrfs", "io.containerd.snapshotter.v1.devmapper", "io.containerd.snapshotter.v1.erofs", "io.containerd.snapshotter.v1.zfs", "io.containerd.differ.v1.erofs", "io.containerd.tracing.processor.v1.otlp", "io.containerd.internal.v1.tracing", "io.containerd.grpc.v1.cri"]
</span><span class="no">EOF
</span></code></pre></div></div>

<p>Now we configure Docker to use a specific IP range for the default network (the
<code class="language-plaintext highlighter-rouge">bip</code> setting) and a bunch of range-reservations for custom created networks
(the <code class="language-plaintext highlighter-rouge">default-address-pools</code> setting). Additionally, we use <code class="language-plaintext highlighter-rouge">libvirtd</code>’s
<code class="language-plaintext highlighter-rouge">dnsmasq</code> instance to resolve DNS (see next section):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> /etc/docker
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/docker/daemon.json"
{
  "bip":"10.10.12.1/24",
  "dns" : [ "10.10.12.1" ],
  "default-address-pools": [
    { "base": "10.10.13.0/24", "size": 24 },
    { "base": "10.10.14.0/24", "size": 24 },
    { "base": "10.10.15.0/24", "size": 24 },
    { "base": "10.10.16.0/24", "size": 24 },
    { "base": "10.10.17.0/24", "size": 24 },
    { "base": "10.10.18.0/24", "size": 24 },
    { "base": "10.10.19.0/24", "size": 24 }
  ]
}
</span><span class="no">EOF
</span></code></pre></div></div>

<p>Enable docker with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> docker.service
</code></pre></div></div>

<p>I use docker without any further adjustments.</p>

<h3 id="libvirtd">Libvirtd</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">libvirtd</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> libvirtd.service virtnetworkd.socket virtnetworkd-ro.socket virtnetworkd-admin.socket
</code></pre></div></div>

<p>The extra <code class="language-plaintext highlighter-rouge">virtnetworkd</code> socket enables are because I noticed that only 
enabling <code class="language-plaintext highlighter-rouge">libvirtd.service</code> does not enable those, and they are needed when
you interact with network settings, like when doing <code class="language-plaintext highlighter-rouge">virsh net-info default</code>.</p>

<p>Now add your user to the <code class="language-plaintext highlighter-rouge">libvirt</code> group, so it can interact with the service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>usermod <span class="nt">-aG</span> libvirt <span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
</code></pre></div></div>

<p>Note that Arch Linux defaults to consider anybody in the <code class="language-plaintext highlighter-rouge">wheel</code> group as a 
<code class="language-plaintext highlighter-rouge">libvirtd</code> administrator, so add yourself to that too if you aren’t already.</p>

<p>Then you should add <code class="language-plaintext highlighter-rouge">libvirt_guest</code> to the <code class="language-plaintext highlighter-rouge">hosts:</code> line in <code class="language-plaintext highlighter-rouge">/etc/nsswitch.conf</code>
so you can always resolve the names of guests. It should usually appear just
before <code class="language-plaintext highlighter-rouge">dns</code>. For example, here is mine:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hosts: mymachines resolve [!UNAVAIL=return] files myhostname libvirt_guest dns
</code></pre></div></div>

<p>Furthermore, I configure the <code class="language-plaintext highlighter-rouge">virt0</code> interface of the <code class="language-plaintext highlighter-rouge">default</code> NAT-enabled
network to have a specific IP address (10.10.11.1) and range (note: needs to
be run after starting/restarting libvirtd, and after configuring Docker; if
you look closely, you’ll notice that this network configuration makes sure
that the <code class="language-plaintext highlighter-rouge">dnsmasq</code> service generated and spawned by <code class="language-plaintext highlighter-rouge">libvirtd</code> additionally
binds to the <code class="language-plaintext highlighter-rouge">docker0</code> network interface, which is an added convenience that
enables Docker containers in the default network to use this <code class="language-plaintext highlighter-rouge">dnsmasq</code> instance
to resolve DNS, as opposed to having to manage a separate/manual <code class="language-plaintext highlighter-rouge">dnsmasq</code>
instance for Docker):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">UUID</span><span class="o">=</span><span class="si">$(</span>uuidgen<span class="si">)</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/tmp/net-default.xml"
&lt;network xmlns:dnsmasq="http://libvirt.org/schemas/network/dnsmasq/1.0"&gt;
  &lt;name&gt;default&lt;/name&gt;
  &lt;uuid&gt;</span><span class="nv">$UUID</span><span class="sh">&lt;/uuid&gt;
  &lt;forward mode='nat'&gt;
    &lt;nat&gt;
      &lt;port start='1024' end='65535'/&gt;
    &lt;/nat&gt;
  &lt;/forward&gt;
  &lt;bridge name='virt0' stp='off' delay='0'/&gt;
  &lt;ip address='10.10.11.1' netmask='255.255.255.0'&gt;
    &lt;dhcp&gt;
      &lt;range start='10.10.11.2' end='10.10.11.254'/&gt;
    &lt;/dhcp&gt;
  &lt;/ip&gt;
  &lt;dnsmasq:options&gt;
    &lt;dnsmasq:option value="interface=docker0"/&gt;
  &lt;/dnsmasq:options&gt;
&lt;/network&gt;
</span><span class="no">EOF

</span>virsh net-destroy default
virsh net-undefine default
virsh net-define /tmp/net-default.xml
virsh net-autostart default
virsh net-start default
<span class="nb">rm</span> <span class="nt">-qf</span> /tmp/net-default.xml
</code></pre></div></div>

<h3 id="openssl">OpenSSL</h3>

<p>I did run into an issue connecting with older VPN environments related
to OpenSSL 3.x disabling various legacy encapsulation and connection modes by
default. The error you would see in such a case is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Jul 31 20:26:38 FRAME openvpn[58956]: OpenSSL: error:11800071:PKCS12 routines::mac verify failure
Jul 31 20:26:38 FRAME openvpn[58956]: OpenSSL: error:0308010C:digital envelope routines::unsupported
Jul 31 20:26:38 FRAME openvpn[58956]: Decoding PKCS12 failed. Probably wrong password or unsupported/legacy encryption
</code></pre></div></div>

<p>Furthermore, when you are behind corporate proxies, you might also have
difficulties passing through the corporate proxy without the settings
<code class="language-plaintext highlighter-rouge">UnsafeLegacyRenegotiation</code> and <code class="language-plaintext highlighter-rouge">UnsafeLegacyServerConnect</code> (which were allowed
by default on OpenSSL 1.x).</p>

<p>To work-around these issues, I place a custom  <code class="language-plaintext highlighter-rouge">/etc/ssl/openssl.cnf</code>:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> <span class="nt">-n</span> <span class="s2">"/etc/ssl/openssl.cnf"</span> <span class="s2">"/etc/ssl/openssl.cnf.orig"</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/ssl/openssl.cnf"
HOME = .
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect
ssl_conf = ssl_sect

[provider_sect]
default = default_sect
legacy = legacy_sect

[default_sect]
activate = 1

[legacy_sect]
activate = 1

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Options = UnsafeLegacyRenegotiation,UnsafeLegacyServerConnect
</span><span class="no">EOF
</span></code></pre></div></div>

<p class="notice--warning">Note that I would only do the above if you need to interact with some old
legacy VPN stuff, or if you’re behind moron-grade SSL-terminating proxies.</p>

<h3 id="nfsv4">NFSv4</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">nfsv4</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> nfsv4-server.service
</code></pre></div></div>

<p class="notice--warning">Quick note: the above start may fail if you updated the <code class="language-plaintext highlighter-rouge">linux</code> package but did
not reboot yet, you’ll see an error about a dependency failure.</p>

<p>I use NFS only on internal interfaces, specifically the <code class="language-plaintext highlighter-rouge">virt0</code> interface of
the <code class="language-plaintext highlighter-rouge">default</code> network (remember that ip address 10.10.11.1?). This allows me
to work with shared storage on other operating systems that I fool around with
on Qemu/KVM (Note that you have much better options for modern Linux systems -
there you can use <code class="language-plaintext highlighter-rouge">enable shared memory</code> and a <code class="language-plaintext highlighter-rouge">virtiofs</code> device to essentially
loop-mount a memory block device which is a directory on the host).</p>

<p>Since we’re only doing NFSv4, and we’re not interested in user/group ID mapping,
let’s stop and mask a couple of RPC services first:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl stop rpcbind.service
systemctl mask rpcbind.service
systemctl stop nfs-blkmap
systemctl mask nfs-blkmap
systemctl stop nfs-idmapd
systemctl mask nfs-idmapd
systemctl stop nfs-mountd
systemctl mask nfs-mountd
</code></pre></div></div>

<p>To make NFSv4 only listen on a specific interface, and to disable version 3 of
the protocol explicitly, we patch <code class="language-plaintext highlighter-rouge">/etc/nfs.conf</code> (use <code class="language-plaintext highlighter-rouge">patch</code> or add the
<code class="language-plaintext highlighter-rouge">host=</code>, <code class="language-plaintext highlighter-rouge">vers3=</code> and <code class="language-plaintext highlighter-rouge">vers4=</code> elements by hand under <code class="language-plaintext highlighter-rouge">[nfsd]</code>:</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- nfs.conf.orig       2023-07-31 21:16:20.438028044 +0300
</span><span class="gi">+++ nfs.conf    2023-08-03 09:01:05.586457300 +0300
</span><span class="p">@@ -67,13 +67,14 @@</span>
 # debug=0
 # threads=8
<span class="gd">-# host=
</span><span class="gi">+host=10.10.11.1
</span> # port=0
 # grace-time=90
 # lease-time=90
 # udp=n
 # tcp=y
<span class="gd">-# vers3=y
-# vers4=y
</span><span class="gi">+vers3=n
+vers4=y
</span> # vers4.0=y
 # vers4.1=y
 # vers4.2=y
</code></pre></div></div>

<p>Create an exports for /home:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> <span class="nt">-n</span> <span class="s2">"/etc/exports.d/home.exports"</span> <span class="s2">"/etc/exports.d/home.exports.orig"</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/exports.d/home.exports"
/home   10.10.11.0/24(rw,sync,crossmnt,no_subtree_check)
</span><span class="no">EOF
</span></code></pre></div></div>

<p>After the above changes, restart the service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart nfsv4-server.service
</code></pre></div></div>

<h3 id="samba">Samba</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">smbd</code> and <code class="language-plaintext highlighter-rouge">nmbd</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> nmb.service smb.service
</code></pre></div></div>

<p>I use Samba for the same reasons as I use NFS, that is to have shared storage
on various older virtual machines (like Windows NT 4.0). Let’s create an
<code class="language-plaintext highlighter-rouge">smb.conf</code> file:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/samba/smb.conf"
[global]
   workgroup = WORKGROUP
   netbios name = </span><span class="si">$(</span><span class="nb">hostname</span> | <span class="nb">tr</span> <span class="s1">'a-z'</span> <span class="s1">'A-Z'</span> | <span class="nb">cut</span> <span class="nt">-d</span><span class="nb">.</span> <span class="nt">-f1</span><span class="si">)</span><span class="sh">
   server string =
   server role = standalone server
   server min protocol = NT1
   ntlm auth = yes
   lanman auth = yes
   hosts allow = 10.10.11.
   log file = /var/log/samba/log.smbd
   max log size = 100
   interfaces = 10.10.11.1/24
   bind interfaces only = yes
   dns proxy = yes
   wins proxy = yes
   wins support = yes
   local master = yes
   domain master = yes
   preferred master = yes
   os level = 33

[homes]
   comment = Home Directories
   acl allow execute always = True
   browsable = yes
   writable = yes
   valid users = %U
   create mask = 0644
   directory mask = 0755
</span><span class="no">EOF
</span></code></pre></div></div>

<p>Finally, we are going to adjust the <code class="language-plaintext highlighter-rouge">systemd</code> unit files for <code class="language-plaintext highlighter-rouge">smb</code> and <code class="language-plaintext highlighter-rouge">nmb</code>
So they wait for the necessary network interface(s) to come up:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl edit smb
systemctl edit nmb
</code></pre></div></div>

<p>You’ll be presented with a file with some comment lines above and below. Add
the below verbatim:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Unit]
After=
After=libvirtd.service

[Service]
ExecStartPre=timeout 10s bash -c 'until ping -c1 10.10.11.1 &amp;&gt; /dev/null; do sleep 1; done'
</code></pre></div></div>

<p>Note the <code class="language-plaintext highlighter-rouge">ExecStartPre</code> line; this bash one-liner makes the service wait for
the necessary network interfaces to be up. This is necessary because we have
configured our <code class="language-plaintext highlighter-rouge">smb.conf</code> to listen on a specific subnet (<code class="language-plaintext highlighter-rouge">10.10.11.0/24</code> in
our case). If the interface serving that network is not up, <code class="language-plaintext highlighter-rouge">smb</code> and <code class="language-plaintext highlighter-rouge">nmb</code>
can’t bind to it and fail to start.</p>

<p>Also note that you can add multiple <code class="language-plaintext highlighter-rouge">ExecStartPre</code> lines, one for each network
interface you wish to wait for to become available.</p>

<p>After creating or changing <code class="language-plaintext highlighter-rouge">smb.conf</code>, restart the services:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart nmb.service smb.service
</code></pre></div></div>

<h3 id="tlp">TLP</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">tlp</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> tlp.service
</code></pre></div></div>

<p>TLP is used to manage power-saving modes of various hardware. It is usually
configured to enable power-saving when not connected to AC, and to disable it
when connected to AC. It does that for all kinds of things, like Wi-Fi, USB,
PCIe, Bluetooth, the CPU scheduler, etc.</p>

<p>I’ve made a custom TLP configuration for my Framework Laptop 13 which you can
install as follows:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/tlp.d/01-custom.conf"
CPU_SCALING_GOVERNOR_ON_AC=powersave
CPU_SCALING_GOVERNOR_ON_BAT=powersave

CPU_BOOST_ON_AC=0
CPU_BOOST_ON_BAT=0

PCIE_ASPM_ON_BAT=powersupersave

PLATFORM_PROFILE_ON_AC=balanced
PLATFORM_PROFILE_ON_BAT=low-power

USB_ALLOWLIST=32ac:0002
USB_EXCLUDE_BTUSB=1
USB_EXCLUDE_PRINTER=0

WIFI_PWR_ON_AC=off
WIFI_PWR_ON_BAT=off

WOL_DISABLE=N
</span><span class="no">EOF
</span></code></pre></div></div>

<p>After the above, you need to restart the service:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart tlp.service
</code></pre></div></div>

<h3 id="cups">Cups</h3>

<p>Enable <code class="language-plaintext highlighter-rouge">cups</code> with:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> cups.socket
</code></pre></div></div>

<p>I also don’t want cups via <code class="language-plaintext highlighter-rouge">cups-browsed</code> to be able to auto-add printers, so I
patch <code class="language-plaintext highlighter-rouge">/etc/cups/cups-browsed.conf</code> as follows:</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- cups-browsed.conf.default	2023-08-29 09:57:47.157250003 +0200
</span><span class="gi">+++ cups-browsed.conf	2023-08-29 09:58:45.054108764 +0200
</span><span class="p">@@ -53,7 +53,7 @@</span>
 # BrowseLocalProtocols.
 # Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither.

-# BrowseProtocols none
<span class="gi">+BrowseProtocols none
</span>

 # Only browse remote printers (via DNS-SD or CUPS browsing) from
</code></pre></div></div>

<h3 id="cdemu">CDemu</h3>

<p>I  use <code class="language-plaintext highlighter-rouge">cdemu</code> and related <code class="language-plaintext highlighter-rouge">vhba</code> kernel module to emulate optical drives for
use with emulation stuff. If you’d like to run CDemu, make sure the required
modules are loaded at boot:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Load modules at boot.</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "/etc/modules-load.d/cdemu.conf"
sg
sr_mod
vhba
</span><span class="no">EOF

</span><span class="c"># Do it now too.</span>
modprobe <span class="nt">-a</span> sg sr_mod vhba

</code></pre></div></div>

<h3 id="enabling-user-services">Enabling user services</h3>

<p>I use the following user-level services (do as logged in user):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>u <span class="k">in </span>syncthing.service wireplumber.service pipewire.socket pipewire-pulse.socket<span class="p">;</span> <span class="k">do </span>systemctl <span class="nb">enable</span> <span class="nt">--now</span> <span class="nt">--user</span> <span class="nv">$u</span><span class="p">;</span> <span class="k">done</span>
</code></pre></div></div>

<h2 id="how-i-use-aur">How I use AUR</h2>

<p>All the hip young things are running <code class="language-plaintext highlighter-rouge">yay</code> these days, but I like to do it the
bare-hands way. That way I have more feeling with what’s going on with AUR
packages.</p>

<h3 id="setting-up-your-own-custom-local-repository">Setting up your own custom local repository</h3>

<p>First, let’s create a <code class="language-plaintext highlighter-rouge">custom</code> repository source for pacman. Note that I sign
my packages using my GnuPG key, so the following assumes that. If you don’t
want to sign your own packages, you need to change the <code class="language-plaintext highlighter-rouge">SigLevel</code> setting in
<code class="language-plaintext highlighter-rouge">/etc/pacman.conf</code> for your <code class="language-plaintext highlighter-rouge">custom</code> repository and you need to tell <code class="language-plaintext highlighter-rouge">makepkg</code>
not to sign your built package.</p>

<p>Also note that my package build root location is specific to my needs;
feel free to change it to anything you like.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Set package build root location.</span>
<span class="nb">export </span><span class="nv">PKG_ROOT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/Packaging/Arch"</span>

<span class="c"># Create a directory structure for Arch packaging.</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">"</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">"</span>
<span class="nb">install</span> <span class="nt">-d</span> Build Repository <span class="s1">'Source Packages'</span> Sources <span class="nt">-o</span> <span class="nv">$USER</span>

<span class="c"># Create a repository database.</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Repository"</span>
repo-add <span class="nt">-s</span> custom.db.tar.gz

<span class="c"># Add entry to /etc/pacman.conf.</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt;&gt; "/etc/pacman.conf"
[custom]
SigLevel = Required DatabaseRequired TrustedOnly
Server = file://</span><span class="nv">$PKG_ROOT</span><span class="sh">/Repository
</span><span class="no">EOF

</span><span class="c"># Add your public key to pacman keychain and set trust (assuming key matches $USER).</span>
gpg <span class="nt">--export</span> <span class="nt">--armor</span> <span class="nv">$USER</span> <span class="o">&gt;</span> your.key
pacman-key <span class="nt">--add</span> your.key
pacman-key <span class="nt">--lsign-key</span> <span class="nv">$USER</span>
<span class="nb">rm</span> <span class="nt">-qf</span> your.key


<span class="c"># Run update for db and files, you should see custom being referenced.</span>
pacman <span class="nt">-Syu</span>
pacman <span class="nt">-Fy</span>

<span class="c"># Unset variables.</span>
<span class="nb">unset </span>PKG_ROOT
</code></pre></div></div>

<h3 id="configuring-for-package-building">Configuring for package building</h3>

<p>Now we configure <code class="language-plaintext highlighter-rouge">makepkg</code> defaults. Make sure you configure the PKG_ROOT,
GPG_PUBKEY and PACKAGER environment variables to your specific likings:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Set package build root location, gpgpubkey-id and packager string.</span>
<span class="nb">export </span><span class="nv">PKG_ROOT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/Packaging/Arch"</span>
<span class="nb">export </span><span class="nv">GPG_PUBKEY</span><span class="o">=</span><span class="s1">'14B189C4E877C9CAEA7F99C7ED3BDDB83BDD2604'</span>
<span class="nb">export </span><span class="nv">PACKAGER</span><span class="o">=</span><span class="s1">'Rubin Simons &lt;me@rubin55.org&gt;'</span>

<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; "</span><span class="nv">$HOME</span><span class="sh">/.makepkg.conf"
# ~/.makepkg.conf.
MAKEFLAGS="-j</span><span class="si">$(</span><span class="nb">nproc</span><span class="si">)</span><span class="sh">"
BUILDENV=(!distcc color !ccache check sign)
BUILDDIR="</span><span class="nv">$PKG_ROOT</span><span class="sh">/Build"
PKGDEST="</span><span class="nv">$PKG_ROOT</span><span class="sh">/Repository"
SRCDEST="</span><span class="nv">$PKG_ROOT</span><span class="sh">/Sources"
SRCPKGDEST="</span><span class="nv">$PKG_ROOT</span><span class="sh">/Source Packages"
GPGKEY="</span><span class="nv">$GPG_PUBKEY</span><span class="sh">"
PACKAGER="</span><span class="nv">$PACKAGER</span><span class="sh">"
</span><span class="no">EOF

</span><span class="c"># Unset variables.</span>
<span class="nb">unset </span>PKG_ROOT GPG_PUBKEY PACKAGER
</code></pre></div></div>

<h3 id="example-interactions-using-aur">Example interactions using AUR</h3>

<p>Here are a few example interactions with package fetching, building, repository
updating and package removal to get you started:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Set package build root location.</span>
<span class="nb">export </span><span class="nv">PKG_ROOT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/Packaging/Arch"</span>

<span class="c"># Get an AUR package.</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Build"</span>
git clone https://aur.archlinux.org/aurutils.git

<span class="c"># Build an AUR package.</span>
<span class="nb">cd </span>aurutils
makepkg <span class="nt">-cCs</span>
<span class="nb">ls</span> ../../Repository/aurutils<span class="k">*</span>

<span class="c"># Show information about a built package.</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Repository"</span>
pacman <span class="nt">-Qpi</span> aurutils-<span class="k">*</span><span class="nt">-any</span>.pkg.tar.zst

<span class="c"># Build a source package.</span>
<span class="nb">cd </span>aurutils
makepkg <span class="nt">-cCsS</span>
<span class="nb">ls</span> ../../Source<span class="se">\ </span>Packages

<span class="c"># Update local repository (adds new packages, removes older ones).</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Repository"</span>
repo-add <span class="nt">-s</span> <span class="nt">-n</span> <span class="nt">-R</span> custom.db.tar.gz <span class="k">*</span>.zst

<span class="c"># Remove a specific AUR package from local repository</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Repository"</span>
repo-remove <span class="nt">-s</span> custom.db.tar.gz aurutils
</code></pre></div></div>

<h3 id="aur-packages-i-build-and-install">AUR packages I build and install</h3>

<p>So now to fill that <code class="language-plaintext highlighter-rouge">$PKG_ROOT/Build</code> directory with packages from AUR so we
can build some stuff and put it in our own repository:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Set package build root location.</span>
<span class="nb">export </span><span class="nv">PKG_ROOT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/Packaging"</span>

<span class="c"># Git clone them all.</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Build"</span>
<span class="nb">export </span><span class="nv">GITREPOS</span><span class="o">=</span><span class="s2">"adwaita-qt-git aic94xx-firmware akku alsacap alsa-hdspeconf amitools android-studio ares-emu aseprite asm-lsp ast-firmware astrojs-language-server astrojs-ts-plugin audacious-gtk3 audacious-plugins-gtk3 aurutils azahar-git battop-bin blastem-hg bluez-hcitool bottles brscan4 bundletool cartridges-git cdesktopenv-git chez-scheme claude-code clojure-lsp-bin cmake-format cmake-language-server codechecker conan cpp-jwt crush cubeb davinci-resolve debtap dev-proxy-bin diagnostic-languageserver displaylink djmount dockerfile-language-server dolphin-emu-git dosbox-x-git dotool drawio-desktop-bin dumpasn1 earthly eclipse-platform elixir-ls erlang_ls evcxr_jupyter evdi-dkms-git exercism figma-linux-bin flow-bin flutterup flycast-git fmt9 fsautocomplete-bin ghcup-hs-bin github-copilot github-desktop gnome-shell-extension-auto-accent-color gnome-shell-extension-dash-to-dock-git gnome-shell-extension-stealmyfocus-git gnome-shell-extension-tiling-shell-git godot-mono-git google-cloud-cli google-earth-pro groovy-language-server-git gtk2 helm-ls ibmcloud-cli icaclient icoextract imhex infer-bin jdk25-openj9-bin jdtls kotlin-lsp-bin kubelogin lagrange leanux lemminx lib32-gperftools lib32-gtk2 lib32-intel-gmmlib lib32-intel-media-driver lib32-libpng12 libbacktrace-git libchdr-git libpng12 librashader libretro-beetle-cygne-git libretro-beetle-lynx-git libretro-beetle-ngp-git libretro-beetle-pcfx-git libretro-beetle-saturn-git libretro-bluemsx-git libretro-dosbox-pure-git libretro-lrps2-git libretro-swanstation-git libretro-uae-git libspng-git libwireplumber-4.0-compat license-wtfpl logisim-evolution-bin m64py marksman-git marsdev-git mednaffe mei-amt-check-git metals mistral-vibe mkinitcpio-firmware mksh mongodb-bin mongosh-bin moonlight-qt-git ms-sys nand2tetris nbdkit ncurses5-compat-libs neo4j-community neovim-symlinks nestopia netcoredbg networkmanager-iwd nvidia-patch-git ocenaudio-bin omnisharp-roslyn-bin openmsx openshift-client-bin openshift-developer-bin openshift-pipelines-bin openvpn-update-systemd-resolved pandoc-bin papirus-folders passmark-performancetest-bin patool pcsx2-git pcsx-redux-git pegasus-frontend-git perlnavigator plutosvg plutovg postman-bin powercap powershell-bin powershell-editor-services pragmatapro-fonts prek prettier-plugin-xml protonplus protontricks-git ps3-disc-dumper-bin pupdate-bin pvsneslib-git pwvucontrol python-agent-client-protocol python-asgi-lifespan python-async-timeout python-backoff python-dataclasses-json python-eval-type-backport python-fvs python-httpx-sse python-m3u8 python-machine68k python-mcp python-mistralai python-opencensus python-opentelemetry python-opentype-feature-freezer python-orjson-git python-pathvalidate python-pluginbase python-pyqtdarktheme-fork python-pysdl2 python-python-ffmpeg python-setuptools-reproducible python-sse-starlette python-steamgriddb python-tree-sitter python-tree-sitter-bash python-uuid7 python-uv-dynamic-versioning qt5-gamepad qt5-webchannel qt5-webengine qt5-websockets rabtap rapidyaml rcu-bin regionset rpcs3-git rtcqs ruby-backport ruby-e2mmap ruby-jaro_winkler ruby-jekyll-include-cache ruby-jekyll-redirect-from ruby-jekyll-sitemap ruby-just-the-docs ruby-reverse_markdown ruby-solargraph ruby-yard-activesupport-concern ruby-yard-solargraph rusty-psn-bin ryujinx sameboy sbom-tool-bin scala-dotty scheme-langserver-bin sedutil shellcheck-bin sigtop-git skyscraper-git snd-hdspe-dkms-git soapui softhsm-git stc-syncthing-git sunshine-git svelte-language-server-git swift-bin systemd-suspend-modules tidal-dl-ng tla-toolbox tonearm townsemu-git ttf-b612 ungoogled-chromium-bin upd72020x-fw usbtop uxplay v4l-utils-git vacuum vala-language-server vasm visual-studio-code-bin vita3k-git vkbasalt-cli vlink vmware-keymaps vmware-workstation vtsls vulkan-memory-allocator wd719x-firmware winetricks-git witr xcursor-dmz xdg-terminal-exec-git xpadneo-dkms yaml-language-server-git y-cruncher zeal-git"</span>
<span class="k">for </span>p <span class="k">in</span> <span class="nv">$GITREPOS</span><span class="p">;</span> <span class="k">do </span>git clone https://aur.archlinux.org/<span class="nv">$p</span>.git<span class="p">;</span> <span class="k">done</span>

<span class="c"># And my own version of openshift-codeready-bin/crc.</span>
git clone https://github.com/rubin55/openshift-codeready-bin.git

<span class="c"># Build all (I wouldn't do this, I would initially enter one-by-one and do</span>
<span class="c"># git log ; makepkg -cCs manually). Will result in packages under $PKG_ROOT/Repository.</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Build"</span>
<span class="k">for </span>p <span class="k">in</span> <span class="k">*</span><span class="p">;</span> <span class="k">do </span><span class="nb">cd</span> <span class="nv">$p</span><span class="p">;</span> makepkg <span class="nt">-cCs</span><span class="p">;</span> <span class="k">if</span> <span class="o">[[</span> <span class="nv">$?</span> <span class="nt">-ne</span> 0 <span class="o">&amp;&amp;</span> <span class="nv">$?</span> <span class="nt">-ne</span> 13 <span class="o">]]</span><span class="p">;</span> <span class="k">then </span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$p</span><span class="s2"> did not go well, please fix..."</span><span class="p">;</span> <span class="nb">break</span><span class="p">;</span> <span class="k">fi</span><span class="p">;</span> <span class="nb">cd</span> - <span class="o">&gt;</span> /dev/null<span class="p">;</span> <span class="k">done</span>

<span class="c"># Update custom repository.</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PKG_ROOT</span><span class="s2">/Repository"</span>
repo-add <span class="nt">-s</span> <span class="nt">-n</span> <span class="nt">-R</span> custom.db.tar.gz <span class="k">*</span>.zst

<span class="c"># Update pacman databases.</span>
pacman <span class="nt">-Syu</span>

<span class="c"># List all packages pacman sees in custom repository.</span>
pacman <span class="nt">-Sl</span> custom

<span class="c"># Install all not-installed packages from custom repository.</span>
pacman <span class="nt">-S</span> <span class="nt">--needed</span> <span class="si">$(</span>pacman <span class="nt">-Sl</span> custom | <span class="nb">grep</span> <span class="nt">-v</span> installed | <span class="nb">awk</span> <span class="s1">'{print $2}'</span><span class="si">)</span>
</code></pre></div></div>

<h3 id="personal-aur-packages">Personal AUR packages</h3>

<p>I maintain these packages (all on AUR, except for <code class="language-plaintext highlighter-rouge">openshift-codeready-bin</code>):</p>

<ul>
  <li><a href="https://aur.archlinux.org/packages/cdesktopenv-git">cdesktopenv-git</a></li>
  <li><a href="https://aur.archlinux.org/packages/dev-proxy-bin">dev-proxy-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/fsautocomplete-bin">fsautocomplete-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/gnome-shell-extension-tiling-shell-git">gnome-shell-extension-tiling-shell-git</a></li>
  <li><a href="https://aur.archlinux.org/packages/infer-bin">infer-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/jdk25-openj9-bin">jdk25-openj9-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/leanux">leanux</a></li>
  <li><a href="https://aur.archlinux.org/packages/marksman-git">marksman-git</a></li>
  <li><a href="https://aur.archlinux.org/packages/marsdev-git">marsdev-git</a></li>
  <li><a href="https://aur.archlinux.org/packages/mistral-vibe">mistral-vibe</a></li>
  <li><a href="https://github.com/rubin55/openshift-codeready-bin">openshift-codeready-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/openshift-developer-bin">openshift-developer-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/openshift-pipelines-bin">openshift-pipelines-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/passmark-performancetest-bin">passmark-performancetest-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/pragmatapro-fonts">pragmatapro-fonts</a></li>
  <li><a href="https://aur.archlinux.org/packages/pupdate-bin">pupdate-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/pvsneslib-git">pvsneslib-git</a></li>
  <li><a href="https://aur.archlinux.org/packages/python-agent-client-protocol">python-agent-client-protocol</a></li>
  <li><a href="https://aur.archlinux.org/packages/rcu-bin">rcu-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/rusty-psn-bin">rusty-psn-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/ruby-solargraph">ruby-solargraph</a></li>
  <li><a href="https://aur.archlinux.org/packages/ruby-yard-solargraph">ruby-yard-solargraph</a></li>
  <li><a href="https://aur.archlinux.org/packages/ruby-yard-activesupport-concern">ruby-yard-activesupport-concern</a></li>
  <li><a href="https://aur.archlinux.org/packages/sbom-tool-bin">sbom-tool-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/scheme-langserver-bin">scheme-langserver-bin</a></li>
  <li><a href="https://aur.archlinux.org/packages/svelte-language-server-git">svelte-language-server-git</a></li>
  <li><a href="https://aur.archlinux.org/packages/tidal-dl-ng">tidal-dl-ng</a></li>
  <li><a href="https://aur.archlinux.org/packages/yaml-language-server-git">yaml-language-server-git</a></li>
</ul>

<p>These are a few open source softwares I want to create AUR packages for:</p>

<ul>
  <li><a href="https://artemis.apache.org/">apache-artemis</a></li>
  <li><a href="https://sourceforge.net/projects/winexe/">winexe</a></li>
  <li><a href="http://www.compilers.de/vbcc.html">vbcc</a></li>
</ul>

<p>And I also want to create AUR packages for these commercial packages:</p>

<ul>
  <li><a href="https://www.graebert.com/us/cad-software/ares-commander/">ares-commander</a></li>
  <li><a href="https://www.tvpaint.com/">tvpaint-professional</a></li>
</ul>

<p>And these development kits / toolchains:</p>

<ul>
  <li><a href="https://github.com/gbdk-2020/gbdk-2020">gbdk-2020-git</a></li>
  <li><a href="https://github.com/devkitPro/buildscripts">devkitPro-git</a></li>
  <li><a href="https://github.com/KallistiOS/KallistiOS">kallistios-git</a></li>
  <li><a href="https://github.com/johannes-fetz/joengine">jo-engine</a></li>
  <li><a href="https://github.com/DragonMinded/libdragon">libdragon-git</a></li>
  <li><a href="https://github.com/AmigaPorts/m68k-amigaos-gcc">m68k-amigaos-gcc</a></li>
  <li><a href="https://github.com/ps2dev/ps2dev">ps2dev-git</a></li>
  <li><a href="https://github.com/ps3dev/ps3toolchain">ps3toolchain-git</a></li>
  <li><a href="https://github.com/Lameguy64/PSn00bSDK">psn00bsdk-git</a></li>
  <li><a href="https://github.com/willll/Saturn-SDK-GCC-SH2">saturn-sdk-gcc-sh2</a></li>
</ul>

<h2 id="final-thoughts">Final thoughts</h2>

<p>After you’ve done (most of) the above, a <code class="language-plaintext highlighter-rouge">reboot</code> is in order; the system should
come up cleanly, without errors or stalls.</p>

<p>I’ve been using this setup for the last two years and it has been consistently
great. I get good battery life, The fan almost never comes on, sleep and resume
work reliably, bluetooth works with mouse, gamepad and headphones. I’ve bought a
1TB USB SSD for one of the slots on which I installed Arch Linux; I then use the
internal NVME for <code class="language-plaintext highlighter-rouge">/home</code>.</p>]]></content><author><name>Rubin Simons</name></author><category term="blog" /><category term="computers" /><category term="linux" /><summary type="html"><![CDATA[This article sums up why and how I run Arch Linux on my Framework Laptop 13, which I received on the 3rd of July 2023, and am still as of today happily using!]]></summary></entry><entry><title type="html">Uninterupted desktop streaming vs. NetworkManager</title><link href="https://rubin55.org/blog/uninterupted-desktop-streaming-vs-network-manager/" rel="alternate" type="text/html" title="Uninterupted desktop streaming vs. NetworkManager" /><published>2024-02-29T11:59:00+01:00</published><updated>2024-02-29T14:27:00+01:00</updated><id>https://rubin55.org/blog/uninterupted-desktop-streaming-vs-network-manager</id><content type="html" xml:base="https://rubin55.org/blog/uninterupted-desktop-streaming-vs-network-manager/"><![CDATA[<p>For maybe more than a year (maybe two) I’ve been struggling with getting desktop
streaming (i.e., from a Linux desktop client to a Windows or Linux host system)
working flawlessly. I mean, without interruptions in video frame speed (60fps)
or audio drop-outs.</p>

<ul id="markdown-toc">
  <li><a href="#uninterupted-desktop-streaming-vs-networkmanager" id="markdown-toc-uninterupted-desktop-streaming-vs-networkmanager">Uninterupted desktop streaming vs. NetworkManager</a>    <ul>
      <li><a href="#the-cause-networkmanager-ap-rescan" id="markdown-toc-the-cause-networkmanager-ap-rescan">The cause: NetworkManager AP (re)scan</a></li>
      <li><a href="#the-solution-systemd-networkd-and-iwd" id="markdown-toc-the-solution-systemd-networkd-and-iwd">The solution: systemd-networkd and iwd</a></li>
      <li><a href="#quick-guide-to-do-this-yourself" id="markdown-toc-quick-guide-to-do-this-yourself">Quick guide to do this yourself</a>        <ul>
          <li><a href="#install-iwd" id="markdown-toc-install-iwd">Install <code class="language-plaintext highlighter-rouge">iwd</code></a></li>
          <li><a href="#turn-off-and-disable-networkmanager-and-wpa_supplicant" id="markdown-toc-turn-off-and-disable-networkmanager-and-wpa_supplicant">Turn off and disable NetworkManager and <code class="language-plaintext highlighter-rouge">wpa_supplicant</code></a></li>
          <li><a href="#create-systemd-networkd-configuration-for-device-wlan0" id="markdown-toc-create-systemd-networkd-configuration-for-device-wlan0">Create <code class="language-plaintext highlighter-rouge">systemd-networkd</code> configuration for device <code class="language-plaintext highlighter-rouge">wlan0</code></a></li>
          <li><a href="#create-iwd-configuration" id="markdown-toc-create-iwd-configuration">Create <code class="language-plaintext highlighter-rouge">iwd</code> configuration</a></li>
          <li><a href="#turn-on-and-enable-systemd-networkd-and-iwd" id="markdown-toc-turn-on-and-enable-systemd-networkd-and-iwd">Turn on and enable <code class="language-plaintext highlighter-rouge">systemd-networkd</code> and <code class="language-plaintext highlighter-rouge">iwd</code></a></li>
          <li><a href="#connect-to-a-wireless-network" id="markdown-toc-connect-to-a-wireless-network">Connect to a wireless network</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h2 id="uninterupted-desktop-streaming-vs-networkmanager">Uninterupted desktop streaming vs. NetworkManager</h2>

<p>Let me begin by describing the experience:</p>

<ul>
  <li>Android TV Moonlight or Parsec client to Windows or Linux host: <strong>flawless</strong></li>
  <li>Windows Moonlight or Parsec client to Windows or Linux host: <strong>flawless</strong></li>
  <li>macOS Moonlight or Parsec client to Windows or Linux host: <strong>flawless</strong></li>
  <li><strong>Linux desktop</strong> using either Moonlight or Parsec: <strong>stuttering, audio and video drop-outs</strong></li>
</ul>

<p>I’m streaming 4K at 60fps. I use this for remote desktop work and for gaming.
I observed the above experience starting about two years ago, but I didn’t mind
too much because I was still using a MacBook, and a Surface Pro X at the time.</p>

<p>These days I’m fully on Linux, on both my desktops at work and home and on my
laptop, so the issue became unavoidable. Things I’ve tried and observed:</p>

<ul>
  <li>
    <p>Initially I thought that it had to do with Wi-Fi hardware - I tested with
cards from Intel, MediaTek, RealTek, even an old Atheros. No dice, stutter
galore.</p>
  </li>
  <li>
    <p>Any ethernet card, even an 100mbit one, would work flawlessly.</p>
  </li>
  <li>
    <p>I tried different Linux distributions: Pop!_OS, Gentoo, Fedora, Arch Linux.
No matter, more or less identically configured, all the same behaviour.</p>
  </li>
  <li>
    <p>In <code class="language-plaintext highlighter-rouge">dmesg</code> you would see a message indicating that either you the client or
the AP disconnected, and you’d see a reconnection attempt. This aligned with
when the stuttering was experienced.</p>
  </li>
</ul>

<h3 id="the-cause-networkmanager-ap-rescan">The cause: NetworkManager AP (re)scan</h3>

<p>It turns out that NetworkManager (re)scans for APs. I’m not sure if it does that
only for APs serving the same SSID as the network you’re on, or more generally
to see if there are other networks available which it might want to connect to,
but I suspect only the former.</p>

<p>In any case, to do that, it needs to drop the connection for a short while, scan
and “quickly” reconnect. In practice this can take more than a second. When you
are streaming 60fps video and audio, that is extremely noticable. On top of that
NetworkManager does this every 20 or 40 seconds or so.</p>

<p>A “workaround” that floats around on the internets is to specify the BSSID field
in the wireless configuration profile within NetworkManager. In my experience
this does not actually work well. If I’d need to quantify it, instead of
experiencing interrupts every minute, it became every 3 or 4 minutes. As I
understand it, NetworkManager parameterizes <code class="language-plaintext highlighter-rouge">wpa_supplicant</code> in a way that is
essentially not configurable. and instructs it to disconnect, rescan and then
reconnect.</p>

<h3 id="the-solution-systemd-networkd-and-iwd">The solution: systemd-networkd and iwd</h3>

<p>Even though I like the convenience of the GUI that NetworkManager enables, Its
shortcomings with regards to stability and performance of the wireless network
connection are too extreme for my use-case.</p>

<p>Since I’m currently on Arch Linux, which uses <code class="language-plaintext highlighter-rouge">systemd</code>, I opted to forego any
graphical Networking setup and use <code class="language-plaintext highlighter-rouge">systemd-networkd</code> as a replacement for
NetworkManager and <code class="language-plaintext highlighter-rouge">iwd</code> as a replacement for <code class="language-plaintext highlighter-rouge">wpa_supplicant</code>.</p>

<p>I’ve been using this setup for about a week now, and since then I have zero
network connection interruption issues and can stream 4K at 60fps without issue.</p>

<h3 id="quick-guide-to-do-this-yourself">Quick guide to do this yourself</h3>

<h4 id="install-iwd">Install <code class="language-plaintext highlighter-rouge">iwd</code></h4>

<p>(<code class="language-plaintext highlighter-rouge">systemd-networkd</code> is a part of the <code class="language-plaintext highlighter-rouge">systemd</code> package).</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># pacman -S iwd</span>
</code></pre></div></div>

<h4 id="turn-off-and-disable-networkmanager-and-wpa_supplicant">Turn off and disable NetworkManager and <code class="language-plaintext highlighter-rouge">wpa_supplicant</code></h4>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># systemctl disable --now NetworkManager</span>
<span class="c"># systemctl disable --now wpa_supplicant</span>
</code></pre></div></div>

<h4 id="create-systemd-networkd-configuration-for-device-wlan0">Create <code class="language-plaintext highlighter-rouge">systemd-networkd</code> configuration for device <code class="language-plaintext highlighter-rouge">wlan0</code></h4>

<p>(your device might be named differently).</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># mkdir -p /etc/systemd/network</span>
<span class="c"># cat &lt;&lt;EOF &gt; "/etc/systemd/network/10-wireless.network"</span>
<span class="o">[</span>Match]
<span class="nv">Name</span><span class="o">=</span>wlan0

<span class="o">[</span>Network]
<span class="nv">DHCP</span><span class="o">=</span><span class="nb">yes
</span><span class="nv">IgnoreCarrierLoss</span><span class="o">=</span>10s
EOF
</code></pre></div></div>

<h4 id="create-iwd-configuration">Create <code class="language-plaintext highlighter-rouge">iwd</code> configuration</h4>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># mkdir -p /etc/iwd</span>
<span class="c"># cat &lt;&lt;EOF &gt; "/etc/iwd/main.conf"</span>
<span class="o">[</span>General]
<span class="nv">RoamThreshold</span><span class="o">=</span><span class="nt">-75</span>
<span class="nv">RoamThreshold5G</span><span class="o">=</span><span class="nt">-80</span>

<span class="o">[</span>Network]
<span class="nv">EnableIPv6</span><span class="o">=</span><span class="nb">false
</span><span class="nv">NameResolvingService</span><span class="o">=</span>systemd

<span class="o">[</span>Scan]
<span class="nv">DisablePeriodicScan</span><span class="o">=</span><span class="nb">true
</span>EOF
</code></pre></div></div>

<h4 id="turn-on-and-enable-systemd-networkd-and-iwd">Turn on and enable <code class="language-plaintext highlighter-rouge">systemd-networkd</code> and <code class="language-plaintext highlighter-rouge">iwd</code></h4>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># systemctl enable --now systemd-networkd</span>
<span class="c"># systemctl enable --now iwd</span>
</code></pre></div></div>

<h4 id="connect-to-a-wireless-network">Connect to a wireless network</h4>

<p>(using device <code class="language-plaintext highlighter-rouge">wlan0</code> - yours might be named differently).</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># iwctl</span>
<span class="o">[</span>iwd]# station wlan0 scan
<span class="o">[</span>iwd]# station wlan0 connect MY_NETWORK
<span class="c"># (fill in passphrase)</span>
&lt;ctrl-D&gt;
</code></pre></div></div>]]></content><author><name>Rubin Simons</name></author><category term="blog" /><category term="computers" /><category term="linux" /><summary type="html"><![CDATA[For maybe more than a year (maybe two) I’ve been struggling with getting desktop streaming (i.e., from a Linux desktop client to a Windows or Linux host system) working flawlessly. I mean, without interruptions in video frame speed (60fps) or audio drop-outs.]]></summary></entry><entry><title type="html">Plans and ideas for 2024</title><link href="https://rubin55.org/blog/plans-and-ideas-for-2024/" rel="alternate" type="text/html" title="Plans and ideas for 2024" /><published>2024-01-07T08:39:00+01:00</published><updated>2024-01-07T21:47:00+01:00</updated><id>https://rubin55.org/blog/plans-and-ideas-for-2024</id><content type="html" xml:base="https://rubin55.org/blog/plans-and-ideas-for-2024/"><![CDATA[<p>A follow-up to <a href="/blog/reflecting-on-my-2023/">my reflections on 2023</a>, my plans
and ideas for 2024.</p>

<ul id="markdown-toc">
  <li><a href="#plans-and-ideas-for-2024" id="markdown-toc-plans-and-ideas-for-2024">Plans and ideas for 2024</a>    <ul>
      <li><a href="#keep-exercising-get-stronger" id="markdown-toc-keep-exercising-get-stronger">Keep exercising, get stronger</a></li>
      <li><a href="#more-software-engineering-less-devops" id="markdown-toc-more-software-engineering-less-devops">More software engineering, less DevOps</a></li>
      <li><a href="#the-great-sailing-adventure-to-norway" id="markdown-toc-the-great-sailing-adventure-to-norway">The great sailing adventure to Norway</a></li>
      <li><a href="#explore-the-creation-of-a-sailing-company" id="markdown-toc-explore-the-creation-of-a-sailing-company">Explore the creation of a sailing company</a></li>
      <li><a href="#organize-the-family-get-together-this-year" id="markdown-toc-organize-the-family-get-together-this-year">Organize the family get-together this year</a></li>
    </ul>
  </li>
  <li><a href="#final-thoughts-just-do" id="markdown-toc-final-thoughts-just-do">Final thoughts, just do</a></li>
</ul>

<h2 id="plans-and-ideas-for-2024">Plans and ideas for 2024</h2>

<p>In a <a href="/blog/reflecting-on-my-2023/">previous post</a> I reflected on what 2023 was
like for us. 2023 has been a year with ups and downs (as many of them are). For
2024 I have a few hopes, plans, and ideas that I would like to write down, hence
this post today.</p>

<p>To clarify, these things haven’t happened yet, but the idea is to explore, and
if a positive outcome is anticipated, to make them happen.</p>

<h3 id="keep-exercising-get-stronger">Keep exercising, get stronger</h3>

<p>Last year I started exercising with my good friend Peter in earnest. It’s been
only three months, but I do notice a great improvement in my mood, focus, and
general fitness + strength.</p>

<p>The idea is to keep that up this year and increase the intensity a little bit.</p>

<h3 id="more-software-engineering-less-devops">More software engineering, less DevOps</h3>

<p>In May 2020 I joined a great software engineering team, working on a new
messaging and notification platform. Around mid-2021 I became the lead engineer.</p>

<p>The work was a mix of software engineering and DevOps tasks, but due to the
nature of the target environment, and the skill-mix of the team, the DevOps part
started to dominate (I would say 25/75 in favor of DevOps work).</p>

<p>Now, there’s nothing wrong with DevOps work, but the way DevOps was meant to
be (not a role but a way of doing things together in a team) versus what it is
in practice (“Who’s the DevOps Engineer? Can you fix this Kubernetes issue?”) is
just a sad state of affairs. Before you can say <strong>“repeat after me, DevOps is
not a role”</strong>, you’re neck-deep into infrastructure and operational issues that
take away from the software engineering part of the job.</p>

<p>I guess I do enjoy both aspects, i.e., the infrastructural part (performance and
how you use hardware resources, make CI/CD really work nice, predictable, and
fast, troubleshooting), and the software creation part (writing code, figuring
out an elegant model to implement things, performance and consistency, etc), but
when you’re dealing with an unstable target environment, DevOps will quickly
become  the majority of your work, at the expense of writing actual code
(meaning: actual code for your product, implementing features, fixing bugs).</p>

<p>The software and infrastructure we created went live last November, and we’re
now in the process of transfering to a new operations team who will be
maintaining the product. This will last until about May of this year.</p>

<p>For my new role I will definitely look for something that brings software
engineering more to the forefront, preferably in a language I get excited about
(i.e., Scala, Elixir, Rust), although I do enjoy the more mainstream languages
too (Java, C#, Python).</p>

<p>So mid-2024: new software engineering role, don’t care about lead, don’t know
where yet!</p>

<h3 id="the-great-sailing-adventure-to-norway">The great sailing adventure to Norway</h3>

<p>Since August last year, I’ve been planning a rather huge sailing trip, together
with my father-in-law, my best friend Freek and his girlfriend Jitske. This year
around June/July, we’re going to sail from my home-town (Scheveningen in The
Netherlands) all the way to Norway.</p>

<p>It will be a three-week adventure approximately, with 6 crew in total (counting
ourselves and the two owners of the vessel). The whole project started as a
birthday present for my father-in-law due to our many conversations about life
at sea but it has become a bit more than that, maybe an exploration too of a
different kind of life, what things could be.. So:</p>

<h3 id="explore-the-creation-of-a-sailing-company">Explore the creation of a sailing company</h3>

<p>I currently have a moderately succesful software engineering company and I do
software engineering projects together with my colleagues for various clients.</p>

<p>In a <a href="/blog/reflecting-on-my-2023/">previous post</a> I shared a bit about how I
feel like I lost my enthousiasm for what I’m doing, feeling out of touch,
without a real sense of purpose. Definitely not unhappy, but maybe critical of
where I am and where I (think I) want to be.</p>

<p>In my life up til now I’ve had various companies, amongst which a record
company called Grond which released records around 1999-2004 and 2014-2016, an
alternative computer-hardware store called VT100, and my current software
engineering company called RAAF.</p>

<p>Next to (hopefully) being profitable, these companies where also the culmination
of ideas, executed enthousiastically; challenges met and mostly overcome; they
were the background to life, a platform for experiencing things, meeting people
and making friends.</p>

<p>My father-in-law was a captain on really large ships. When I am visiting in
Bulgaria, we always talk about ships, about sailing, about teaching and
certifications that are required on various types of vessels, about tourism.</p>

<p>This last christmas, we also played with an idea: <em>“what if we would have a
serious sailing vessel, how could we build a modest company for tourism,
training and (small-scale) import/export around that?”</em></p>

<p>So this year I am doing that: Figuring out what kind of investment would be
required and what the inflow + outflow of money would look like in such a
company, the required aspects of it regarding certificates, maintenance,
harboring, etc.</p>

<h3 id="organize-the-family-get-together-this-year">Organize the family get-together this year</h3>

<p>My mother’s side of the family is partly Belgian. They organise an annual
family get-together which is always a happy affair that we enjoy going to.</p>

<p>At the last get-together, I offered to organise this years’ get-together.
This will be around September of this year. I am planning to arrange a
really nice eating-together at a great place that’s run by my best friend
Freek’s girlfriend, Jitske. Nothing certain yet, because it’s still a
while away, but that’s the plan.</p>

<h2 id="final-thoughts-just-do">Final thoughts, just do</h2>

<p>I think the overall idea for this year is: stay healthy, get stronger, and
explore a few avenues. Do great things with family and try to make it so that
everyone is a little bit better off at the end of the year. I hope we won’t
have more instability in the world at large (although I can’t really control
that anyway) and in general, a bit less cynical takes.</p>

<p>I think many of the above subjects will receive their own blog-posts, so stay
tuned (yeesh).</p>]]></content><author><name>Rubin Simons</name></author><category term="blog" /><category term="thoughts" /><summary type="html"><![CDATA[A follow-up to my reflections on 2023, my plans and ideas for 2024.]]></summary></entry><entry><title type="html">Reflecting on my 2023</title><link href="https://rubin55.org/blog/reflecting-on-my-2023/" rel="alternate" type="text/html" title="Reflecting on my 2023" /><published>2023-12-31T16:05:00+01:00</published><updated>2024-01-07T10:05:00+01:00</updated><id>https://rubin55.org/blog/reflecting-on-my-2023</id><content type="html" xml:base="https://rubin55.org/blog/reflecting-on-my-2023/"><![CDATA[<p class="notice--info">Update: On the 2nd of January, Marina’s best friend, Eli who was fighting
cancer, passed away. We went to the funeral on the 3rd. She will be greatly
missed by us, and by many, many, friends and loved ones.</p>

<p>I figured I’d write a post about this last year, maybe to crystalize thoughts
I’ve been having, and to help figure some things out for the times ahead.</p>

<p>It’s a bit more personal than my previous writing, but I guess no less useful
to share. I’ve added a table of contents to try and keep it organized:</p>

<ul id="markdown-toc">
  <li><a href="#events-of-2023" id="markdown-toc-events-of-2023">Events of 2023</a>    <ul>
      <li><a href="#started-seeing-an-orthodontist" id="markdown-toc-started-seeing-an-orthodontist">Started seeing an orthodontist</a></li>
      <li><a href="#financial-security" id="markdown-toc-financial-security">Financial security</a></li>
      <li><a href="#more-vacations" id="markdown-toc-more-vacations">More vacations</a></li>
      <li><a href="#started-blogging" id="markdown-toc-started-blogging">Started blogging</a></li>
      <li><a href="#started-exercising" id="markdown-toc-started-exercising">Started exercising</a></li>
      <li><a href="#death" id="markdown-toc-death">Death</a></li>
      <li><a href="#end-of-project" id="markdown-toc-end-of-project">End of project</a></li>
    </ul>
  </li>
  <li><a href="#final-thoughts-lost-purpose" id="markdown-toc-final-thoughts-lost-purpose">Final thoughts, lost purpose</a></li>
</ul>

<h2 id="events-of-2023">Events of 2023</h2>

<p>2023 has been an eventful year for me. I effected a bunch of positive changes,
but also, bad and sad things happened. I’ll go over them in a roughly
chronological order.</p>

<h3 id="started-seeing-an-orthodontist">Started seeing an orthodontist</h3>

<p>When I was young (between around age 14 and 17 or so) I had braces. It fixed a
few stubborn teeth at the time, nothing dramatic, but over the years since, they
slowly reverted to their previous somewhat crooked stance.</p>

<p>I went to the orthodontist and started a program with Invisalign braces that I
still have today. I think I will be “done” just before summer ‘24.</p>

<p>The results are pretty dramatic and I’m very happy so far. Just one tooth still
has to come down a little and then everything is straight again.</p>

<p>I’m also happy that my adventures with braces this year inspired a colleague
(or maybe two) at work to do the same! Yay for great dental health.</p>

<h3 id="financial-security">Financial security</h3>

<p>The year began with a big change on the financial front: I paid off my mortgage
and my house is now mortgage-free.</p>

<p>I’ve been working towards this conciously for the last nine years. The idea was
to minimize monthly expenses and simultaneously corner an important aspect of
future security (to own a house). The effect on monthly expenses is as you’d
expect: I can (much) more easily save money now, vacations are much less of a
financial problem.</p>

<p>Before I got here (i.e., to own a house and be mortgage-free), I thought that it
would impact me much more positively and I was fantasizing about how much this
would help me to feel less worried about the future. I must admit though, that
this effect is much less so. I’m certain that on a non-psychological level, I
<em>am</em> much safer financially than I was before, but I don’t really feel it as
much as I hoped I would..</p>

<p>I guess I was hoping for a relief of sorts. Don’t get me wrong, I’m super happy
I achieved this, but it didn’t make me feel more secure (yet?). It might even
have made me feel a bit lost, a sense of lost purpose? (more on that later).</p>

<h3 id="more-vacations">More vacations</h3>

<p>This year we’ve made the concious choice to have vacation more often. We’ve had
quite a period where we had only the minimum of vacations, focusing on work, and
the regular chores and joys of raising our daughter, Eline.</p>

<p>Early in the year we went on wintersports, to a small place close to Innsbruck,
close to the Italian border. We ski’ed! I hadn’t done so since I was about 6 so
it was a lot of snow-balling downhill, but I eventually got the nack of it.</p>

<p>In the spring we went to both the north of Italy, at lake Como and to the
eastern side of Sicily. I really loved this vacation. Lake Como was beautiful
and where we were staying, it was not really busy yet. Make no mistake, the
area is super touristic, but end-of-april, you’re fine.</p>

<p>Sicily was really super great. For me end-of-april is the best time to visit,
because it’s not crazy-hot yet but nice (think 22 to 25 degrees celsius). For
most tourists and other Italians, this is still cold, so the beaches are empty
which I particulary appreciated. I really felt we experienced a personal Sicily.</p>

<p>For the summer we went to Bulgaria, where Marina, my partner comes from. We do
this most years, visiting Marina’s parents. It’s great for Eline, but it <em>was</em>
a bit of a uneventful vacation for us (which is not bad from time to time).</p>

<h3 id="started-blogging">Started blogging</h3>

<p>This year I started blogging. I didn’t write as much as I would’ve liked, but
you’re reading it, I have it hosted on GitHub pages, and am using Jekyll.</p>

<p>I appreciate how blogging helps you reflect on things, or share things with the
world. I shared my previous articles on Hacker News and really enjoyed the
various opinions, good and bad, on stuff I wrote.</p>

<h3 id="started-exercising">Started exercising</h3>

<p>In September of this year I started exercising with my great friend Peter. We go
to the gym two times a week to execute a regimen of horror for about 2.5 hours.</p>

<p>It’s now about three months on and I do feel much better, more awake. Physically
it is also making more and more of a difference. The plan is to just keep at it
and so far so good. It has definitely helped with feeling more positive,
although I keep struggling with a sense of lost purpose (more on that later).</p>

<h3 id="death">Death</h3>

<p>This year also had its share of death.</p>

<p>Around this summer, Mac, the partner of my mother got news that he had
metastasized cancer all over the place. It was very aggressive and unexpected.
Mac was 73 years old when he died last November. He opted for euthanasia.</p>

<p>In the last week of his life, I was there most every day. We talked about life
and death. I also was there when he chose to die. I admired his bravery and
resolution - he drank the cup (made a joke about Socrates) and peacefully went
to the eternal hunting grounds in less than 90 seconds. He’ll be missed dearly
by us. Eline was very fond of him and it was her first death that was closer to
home (her great-grandfather in bulgaria died in 2022).</p>

<p>As I write this, Marina’s best friend is fighting a losing battle against cancer
too. It is heavily advanced. She’s been fighting this demon for five years. The
last 18 months have been “given” by a relatively new drug called Trodelvy - she
would have been gone 18 months ago if it weren’t for this drug.</p>

<p>It’s a matter of hours, days at best for her now.. Just some bad luck with a
specific gene that doesn’t matter from an evolutionary standpoint.. Live is
really horrible and unfair sometimes.</p>

<h3 id="end-of-project">End of project</h3>

<p>This year a big project I’ve been working on went live. It’s the backend for a
large-scale notification system that me and my team have been working on for the
last three years.</p>

<p>I’m currently working to transition the software development and operations to
a new team that will be maintaining it, which will be concluded by april of next
year.</p>

<p>It’s a strange mix of feelings. The team I’ve been a part of the last three
years is definitely one of the most balanced and positive ones I’ve had the
privilege to be a part of, and I’m going to miss that. At the same time I’m
happy the software is working, live, and to have a sense of conclusion there.</p>

<h2 id="final-thoughts-lost-purpose">Final thoughts, lost purpose</h2>

<p>This article intended to give an overview of just a life (mine) in 2023, I’m
not yet sure how others would experience it (negatively or positively or both)
but it did feel good to write down.</p>

<p>Wit regards to a lost sense of purpose: I feel a bit as if I’m “flying” over all
these events, as an observer. Important things happened. Bad ones, happy ones,
necessary ones.. There’s a feeling of unavoidability.</p>

<p>I’ve been thinking a lot about the “why” of things, also about motivation, about
what should be next. And I find myself unable to answer with determination - I
lost a sense of purpose, a goal and I’m not sure how to (re)find it.</p>

<p>I wouldn’t write this down if it was just a momentary thing - it has been in the
undercurrents of my thoughts for the better part of this last year..</p>

<p>I think “ungrounded” captures it best. I go through the motions, am happy even,
but at the same time I feel detached. It’s hard to put into writing.</p>

<p>I suspect I will be tackling with this next year too, although I hope to find
some constructive way of getting to a place where I am either at peace with
where I am now or re-find my purpose.</p>

<hr />

<p>My next blog post will be about my ideas and resolutions for 2024, which I hope
to write next week somewhere.</p>]]></content><author><name>Rubin Simons</name></author><category term="blog" /><category term="thoughts" /><summary type="html"><![CDATA[Update: On the 2nd of January, Marina’s best friend, Eli who was fighting cancer, passed away. We went to the funeral on the 3rd. She will be greatly missed by us, and by many, many, friends and loved ones.]]></summary></entry><entry><title type="html">Why I am getting a Framework</title><link href="https://rubin55.org/blog/why-i-am-getting-a-framework/" rel="alternate" type="text/html" title="Why I am getting a Framework" /><published>2023-06-01T14:28:00+02:00</published><updated>2023-06-02T19:15:00+02:00</updated><id>https://rubin55.org/blog/why-i-am-getting-a-framework</id><content type="html" xml:base="https://rubin55.org/blog/why-i-am-getting-a-framework/"><![CDATA[<p class="notice--info">Update: I kid you not, my 4th Surface type cover just died this morning. Also
corrected Macbook Pro 14 2017 to 13 inch (silly mistake). I also noticed some
folks thought I used a lot of computers. I guess I do? I don’t know really.
Some of those systems are desktops, some laptops, some were used during
approximately the same time periods, some were aquired for my office, some for
personal use, some as an experiment and sold again.</p>

<p>First things first. This is my first post to my newish personal website, which
I’m hosting on GitHub Pages. It has all kinds of bells and whistles like
<a href="https://letsencrypt.org/">LetsEncrypt</a> for SSL/TLS, pagination, and is fully statically generated
thanks to <a href="https://jekyllrb.com/">Jekyll</a>. Big shout-out to <a href="https://mademistakes.com/about/">Michael Rose</a> for a really nice
template I’m using called <a href="https://mmistakes.github.io/minimal-mistakes/">Minimal Mistakes</a>! Thanks a bunch.</p>

<p>I used to have a personal website back in the day to share ideas and thoughts,
and I figured I should pick that up again.. so here we are..</p>

<h2 id="some-background">Some background</h2>

<p>Anyways, I’ve been on a quest for a new personal computing device for a while
now. I use a beefy desktop at home and at my office, but when I’m out and about
I usually have a laptop with me to hack around on.</p>

<p>Historically I’ve used ThinkPads (T43, X220, X230, W520, T14s), Macs (PowerBook
G4, Apple Cube, G5, MacBook Pro 13 2017), and even a few Surface devices (Surface
Pro 4, Surface Pro X).</p>

<h2 id="thinkpads-nowadays">ThinkPads nowadays</h2>

<p>I’m really not happy about the slow deterioration of build quality in ThinkPads.
It’s been a slow ride downwards essentially since Lenovo took over the ThinkPad
line from IBM back in 2005ish.</p>

<p>Fast forward to today and it’s a plasticky, flimsy shadow of its former self.
Next to that, configurations as stated in <a href="https://psref.lenovo.com/">PSREF</a> are not available in all
regions and you have to jump through hoops to get a configuration you like/need.</p>

<p>My most recent ThinkPad, a <a href="https://www.lenovo.com/us/en/p/laptops/thinkpad/thinkpadt/thinkpad-t14s-gen-3-(14-inch-amd)/len101t0015">T14s AMD gen3</a> is great feature-wise: It has
32GiB of RAM, a fast processor, 2TiB of storage and a 4K screen. But the build
quality is horrible - it squeeks when you lift it from the edges, the screen has
at least 5 dead pixels (within the year!) and the sound quality (which,
admittedly, has historically been bad with ThinkPads) is below average.</p>

<h2 id="apple-stuff">Apple stuff</h2>

<p>I’ve had a couple of Macs and the experience has mostly been great. Up till
about a little more than a year ago, I used a <a href="https://support.apple.com/kb/SP754">MacBook Pro 13 2017</a> and I
was really happy with it. It was becoming a bit slow though.</p>

<p>I absolutely <em>adore</em> Apple build quality. It’s really another dimension
compared to other manufacturers. Next to that, recent developments with regards
to the introduction of the M1 and M2 processors are astoundingly great too.
My only gripe with Apple is the slowly-but-surely dumbing-down of macOS, the
in-my-opinion-uneccessary removal of 32-bit support (which Mojave still had)
and a general feeling of uneasiness I have with the App Store being pushed more
and more as the only “safe” way of installing software (in general, a feeling
of being vendor-locked in).</p>

<p>I have been following <a href="https://asahilinux.org/">Asahi Linux</a> with much interest. I’m amazed how far
the project has come in such a short time! I don’t think it is fully ready yet
for daily-driving, but as soon as it is, I would definitely hop aboard.</p>

<h2 id="the-surfaces">The surfaces</h2>

<p>I really love the 2-in-1 setup of the Surface Pro product line. I read a lot,
usually digitally, and the fact that you can use one device as a tablet and as
a computer is really nice.</p>

<p>Last year I’ve been using a <a href="https://www.microsoft.com/en-us/d/surface-pro-x/8xtmb6c575md">Surface Pro X</a> and it really is a cool little
device. Most applications nowadays have Windows-on-ARM native binaries, like
JetBrains, Python, Java, Node.js, etc, so, while not super-fast, it has been
fast enough. At night I use it to read books, comics and magazines.</p>

<p>The problem with Microsoft is not so much build quality as a whole, but
component quality. The build quality of Microsoft Surface devices is really
nice, no argument there. But they can’t stand the test of time. After about 18
months issues start to appear, which turn out to be really common. I had the
following issues on both my Surface devices:</p>

<ul>
  <li>Kick-stand loosening due to regular wear</li>
  <li>White/lighter spots on display due to normal handling</li>
  <li>Type-cover stops working due to folding</li>
</ul>

<p>The first issue is arguably understandable. Issues two and three are really
design and quality control issues. It is totally unacceptable for a tablet
device to develop screen pressure damage from simply holding the device. And
before you go and think this must be me, go do a search and see how many people
are suffering from this issue.</p>

<p>I’ve had three (3!) type covers in 2 years time, both broke in the same way
(the fold corner contains wires that go to the magnetic connector, which break
eventually due to wear-and-tear).</p>

<h2 id="the-framework">The Framework</h2>

<p>Ever since I’ve first heard of <a href="https://frame.work/">Framework</a>, I wanted to get one. First they
didn’t sell in the Netherlands, where I’m at, and initially there were quite a
few growing pains, bugs, and little issues especially when running Linux
(according to brave early-adopters in the Framework forums at least). Nowadays
most of these issues are fixed and for common grievances fixes and workarounds
seem to be readily available.</p>

<p>Framework has recently opened pre-order for their 3rd generation devices and so
I bit the bullet and ordered an Intel 13th gen variant with 64Gib RAM and an
8TiB NVME (ordered seperately).</p>

<p>Actually, as I’m typing this, I just got a message in the mail telling me they
are preparing my batch!</p>

<p class="notice--info">By the way, you might be asking yourself why not the Ryzen variant? I love AMD,
their Linux support is super good, especially amdgpu in the Linux kernel is very
good. But since the last generation, AMD has built in support for the Microsoft
<a href="https://learn.microsoft.com/en-us/windows/security/information-protection/pluton/microsoft-pluton-security-processor">Pluton</a> platform, which I find a bit too much customer-as-adversary for my
tastes. Pluton is woefully under-documented, but the best source for
understanding it is <a href="https://www.youtube.com/watch?v=U7VwtOrwceo">a talk</a> from Tony Chen about Xbox One security, which
is the predecessor of Pluton.</p>

<p>So I guess the biggest reason for me to go with Framework is the openness of the
platform, consequent repairability, and overal positive reviews with regards to
build quality. I think this might just be the ultimate Linux device for me!</p>

<p>I’ll be running <a href="https://archlinux.org/">Arch Linux</a> on mine. In a future post, I’ll share how the
experience has been so far.</p>]]></content><author><name>Rubin Simons</name></author><category term="blog" /><category term="computers" /><summary type="html"><![CDATA[Update: I kid you not, my 4th Surface type cover just died this morning. Also corrected Macbook Pro 14 2017 to 13 inch (silly mistake). I also noticed some folks thought I used a lot of computers. I guess I do? I don’t know really. Some of those systems are desktops, some laptops, some were used during approximately the same time periods, some were aquired for my office, some for personal use, some as an experiment and sold again.]]></summary></entry></feed>