<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Articles on j6s</title>
    <link>https://thej6s.com/</link>
    <description>Recent content in Articles on j6s</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>hello@thej6s.com (Johannes Hertenstein)</managingEditor>
    <webMaster>hello@thej6s.com (Johannes Hertenstein)</webMaster>
    <lastBuildDate>Sun, 05 Jun 2022 00:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://thej6s.com/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Installing Linux on ZFS</title>
      <link>https://thej6s.com/articles/2022-06-05__installing-linux-on-zfs/</link>
      <pubDate>Sun, 05 Jun 2022 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2022-06-05__installing-linux-on-zfs/</guid>
      <description>&lt;p&gt;ZFS is a fascinating filesystem that is packed with features. It is mainly geared towards data storage use cases such as
NAS or Datacenter usage. One feature however intrigued me for workstation usage: The ability to not only take incremental
snapshots, but also transfer those over the network to another ZFS filesystem. This feature could solve a lot of my current
backup woes - so I set out on a journey to install Linux on ZFS.&lt;/p&gt;
&lt;p&gt;I quickly learned, that guides about this topic are very cargocult-y, repeating things guides before them have said without
questioning &lt;strong&gt;why&lt;/strong&gt; those things were said. This leads to a situation where these guides are needlessly complicated and often
fail to address the few important pieces of information. This is where this series of blog posts starts: My goal is to provide
a &lt;strong&gt;simple&lt;/strong&gt; guide to running Linux on ZFS written largely from scratch. I will try to leave no stone unturned and nothing implied
so readers can get a feel for which parts of the guide are important for a running system and which are down to my personal
preferences.&lt;/p&gt;
&lt;p&gt;To start things off, let&amp;rsquo;s install archlinux on ZFS. I will be using Arch Linux for these guides as it&amp;rsquo;s installation process (and
its lack of automation) lend itself very well towards this kind of systems exploration: If you have to do everything yourself
you have no choice but to learn how things work.&lt;/p&gt;
&lt;h2 id=&#34;0-assumptions&#34;&gt;0. Assumptions&lt;/h2&gt;
&lt;p&gt;This guide makes a couple of assumptions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You area installing this on a UEFI based system. This should be true for all modern PCs but if you are trying this in a virtual machine, you may have to explicitly configure it that way &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;No dual-booting is required&lt;/li&gt;
&lt;li&gt;We are installing on a 64bit intel based system&lt;/li&gt;
&lt;li&gt;We are going to use grub&lt;/li&gt;
&lt;li&gt;We are not using ZFS encryption. In order to use encryption on ANY dataset in the root pool, the &lt;code&gt;/boot&lt;/code&gt; directory must be located on a different partition similar to LUKS setups. I will create a follow-up article explaining how Linux on encrypted ZFS works.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;1-build-a-live-iso-that-contains-zfs&#34;&gt;1. Build a Live ISO that contains ZFS&lt;/h2&gt;
&lt;p&gt;Like a lot of distributions, archlinux live environments do not ship with ZFS. This is mainly due to the licensing disagreement &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
that comes up a lot when talking about ZFS in linux environments. For archlinux, one can use the &lt;code&gt;archzfs&lt;/code&gt; repository &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. In order to
have ZFS included in an archlinux live environment, one has to build their own archiso including the arch packages.&lt;/p&gt;
&lt;p&gt;I will skip over this fairly quickly, for more information check out the archwiki page on ZFS &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;, the one on archiso &lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt; and my
repository containing the building blocks described here &lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;archiso&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a new archiso profile by copying &lt;code&gt;/usr/share/archiso/configs/releng/&lt;/code&gt; into a directory of your own (e.g. &lt;code&gt;./archlive&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Trust the pacman key and add the archzfs repository to the &lt;code&gt;pacman.conf&lt;/code&gt; file in your archiso directory&lt;/li&gt;
&lt;li&gt;Append &lt;code&gt;linux-headers&lt;/code&gt;, &lt;code&gt;zfs-dkms&lt;/code&gt;, &lt;code&gt;zfs-utils&lt;/code&gt; to the list of packages that will be installed in the live environment located in &lt;code&gt;packages.x86_64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Optional: In order to save yourself the tedious job of manually typing the pacman key later on, create a file containing it in &lt;code&gt;airrootfs&lt;/code&gt;. If you are using my repository, then there will be &lt;code&gt;/zfs-key.sh&lt;/code&gt; with a script to add the key and &lt;code&gt;/zfs-pacman.conf&lt;/code&gt; with the pacman configuration.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;2-booting-the-live-environment&#34;&gt;2. Booting the Live environment&lt;/h2&gt;
&lt;p&gt;After booting into the live environment, we&amp;rsquo;ll have to check a couple of things before we start:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;loadkeys&lt;/code&gt; in order to load a different keymap if you don&amp;rsquo;t use QWERTY (e.g. &lt;code&gt;loadkeys de&lt;/code&gt; or &lt;code&gt;loadkeys colemak&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;ping 1.1.1.1&lt;/code&gt; to check if we have internet connectivity. Networking should work out of the box for wired networks. Wireless networking can be setup using &lt;code&gt;iwctl&lt;/code&gt; &lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Ensure, that the &lt;code&gt;zfs&lt;/code&gt; and &lt;code&gt;zpool&lt;/code&gt; commands exist&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;3-partitioning-your-drive&#34;&gt;3. Partitioning your drive&lt;/h2&gt;
&lt;p&gt;At this point, we can begin preparing our drive. First, identify the device you want to use as your bootdrive by using &lt;code&gt;lsblk&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ lsblk
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NAME  MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loop0   7:0    &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; 784.6M  &lt;span style=&#34;color:#099&#34;&gt;1&lt;/span&gt; loop /run/archiso/airootfs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sr0    11:0    &lt;span style=&#34;color:#099&#34;&gt;1&lt;/span&gt; 943.3M  &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; rom  /run/archiso/bootmnt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sda   254:0    &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;    50G  &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; disk 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example, I am going to use &lt;code&gt;/dev/sda&lt;/code&gt; as my boot drive. If your system boots off of an NVMe drive, then this will likely
be &lt;code&gt;/dev/nvme0n1&lt;/code&gt; or similar for you. We are going to use &lt;code&gt;cgdisk&lt;/code&gt; in order to partition the drive (WARNING: This will delete
the data that is currently on that drive):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create one partition of 500M in size. This will be the EFI partition that your System uses for booting. Use the type &lt;code&gt;EF00&lt;/code&gt; to indicate the pact that this is a EFI partition&lt;/li&gt;
&lt;li&gt;Create a secondary partition that spans the rest of your drive. The type for this drive is not really important.  Popular choices are &lt;code&gt;bf00&lt;/code&gt; (Solaris root, Solaris being the &amp;lsquo;original&amp;rsquo; ZFS supporting OS), &lt;code&gt;8300&lt;/code&gt; (Linux Filesystem) or &lt;code&gt;8304&lt;/code&gt; (Linux root) &lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;                            cgdisk 1.0.9 

                        Disk Drive: /dev/vda
                      Size: 104857600, 50.0 GiB

 Part. #     Size        Partition Type            Partition Name
 ----------------------------------------------------------------
             1007.0 KiB  free space
    1        500.0 MiB   EFI system partition      EFI
    2        49.5 GiB    Linux filesystem          zroot
             1007.5 KiB  free space
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Partition setup inside cgdisk &lt;sup id=&#34;fnref:9&#34;&gt;&lt;a href=&#34;#fn:9&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Write the partition and exit &lt;code&gt;cgdisk&lt;/code&gt; . Now, &lt;code&gt;lsblk&lt;/code&gt; should indicate 2 drives: &lt;code&gt;/dev/sda1&lt;/code&gt; (will be EFI) and &lt;code&gt;/dev/sda2&lt;/code&gt; (will be ZFS).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ lsblk         
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loop0    7:0    &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; 784.6M  &lt;span style=&#34;color:#099&#34;&gt;1&lt;/span&gt; loop /run/archiso/airootfs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sr0     11:0    &lt;span style=&#34;color:#099&#34;&gt;1&lt;/span&gt; 943.3M  &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; rom  /run/archiso/bootmnt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sda    254:0    &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;    50G  &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; disk 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├─sda1 254:1    &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;   500M  &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; part 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └─sda2 254:2    &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;  49.5G  &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt; part 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a final step during the partitioning phase, we will use &lt;code&gt;mkfs.vfat /etc/sda1&lt;/code&gt; in order to initialize a FAT filesystem for the EFI drive.
Unfortunately, FAT is all EFI supports &lt;sup id=&#34;fnref:10&#34;&gt;&lt;a href=&#34;#fn:10&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;10&lt;/a&gt;&lt;/sup&gt; - this limitation applies to all filesystems however. Even for default ext4 Linux systems, a FAT system
is always involved in booting. This fact doesn&amp;rsquo;t matter however, because the EFI partition only contains reltaively volatile data: It can be
recreated from the data in the system at any point in time (In case of data loss &amp;amp; reinstallation, be sure to recreate the EFI data using the &lt;code&gt;grub-install&lt;/code&gt; command).&lt;/p&gt;
&lt;h2 id=&#34;4-setup-zfs&#34;&gt;4. Setup ZFS&lt;/h2&gt;
&lt;p&gt;After all of this preparation, it is finally time to start with the interesting part: Actually setting up the ZFS zpool and datasets. In this part I will assume
that you are at least faintly familiar with the concepts behind ZFS, but will do my best to describe them as we go. To skip ahead a bit, the following is
the dataset setup we are setting up:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NAME                USED  AVAIL     REFER  MOUNTPOINT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot              1.01M  48.0G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/DATA          288K  48.0G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/DATA/docker    96K  48.0G       96K  /var/lib/docker
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/DATA/home      96K  48.0G       96K  /home
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/ROOT           96K  48.0G       96K  /
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Under our root dataset, there are 2 &amp;rsquo;logical&amp;rsquo; datasets which are not mounted but used to logically separate the data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ROOT&lt;/code&gt; will contain our system root&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DATA&lt;/code&gt; will contain datasets for userdata (e.g. home directory, docker files, &amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This distinction is done because snapshots are created on a per-dataset basis. By separating system data and user data well, we will be able to roll back
a failed system upgrade in the future without compromising our user data. For alternative dataset configurations, check &amp;ldquo;4.2 Aside: Alternative dataset
configurations&amp;rdquo;&lt;/p&gt;
&lt;p&gt;We are going to start out creating a zpool, which describes an array of one or more physical disks that are handled as a single unit by ZFS. When using
multiple disks, ZFS can arrange them in multiple RAID configurations, but for this simple guide we are going to assume that a single drive is being used.
A zpool then contains datasets: You can think of these as a cross between directories and partitions. Creating a zpool will always also create a dataset
with the same name.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ zpool create &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    zroot &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -o &lt;span style=&#34;color:#008080&#34;&gt;ashift&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;12&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -O &lt;span style=&#34;color:#008080&#34;&gt;acltype&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;posixacl &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -O &lt;span style=&#34;color:#008080&#34;&gt;relatime&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;on &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -O &lt;span style=&#34;color:#008080&#34;&gt;xattr&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;sa &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -O &lt;span style=&#34;color:#008080&#34;&gt;mountpoint&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;none &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -O &lt;span style=&#34;color:#008080&#34;&gt;canmount&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;off &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -R /mnt &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    /dev/sda2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that&amp;rsquo;s a lot of options. Options set with &lt;code&gt;-o&lt;/code&gt; are options we are setting on the zpool while options set with &lt;code&gt;-O&lt;/code&gt; are those we are setting on the dataset.
Let&amp;rsquo;s go through these options 1 by 1 and explain what each one does. I will also include information if the option is strictly necessary (as in, this option is
required for booting) or recommended (as in, you should probably set the option for optimal performance and compatibility)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;zroot&lt;/code&gt; is the name of the zpool we are creating. You are free to call it whatever you want, but it seems that for this use case &lt;code&gt;zroot&lt;/code&gt; has been agreed upon as a convention.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-o ashift=12&lt;/code&gt; sets the pools blocksizes to 4K (2 ^ 12 bytes). This should match the sectorsize of modern hard drives and can be only set once when creating the pool. This value is sometimes incorrectly detected as 9, making the pools performance less than suboptimal. &lt;sup id=&#34;fnref:11&#34;&gt;&lt;a href=&#34;#fn:11&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-O acltype=posixacl&lt;/code&gt; instructs ZFS to use POSIX compatible ACLs (Access Control Lists). This option is not strictly required on the root partition for the whole system - but at least &lt;code&gt;/var/log/journal&lt;/code&gt; needs it to be set. &lt;sup id=&#34;fnref:12&#34;&gt;&lt;a href=&#34;#fn:12&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;12&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-O xattr=sa&lt;/code&gt; Sets the storage mechanism for extended attributes. Some applications and use cases (including the ACLs mentioned above) add additional metadata to files and ZFS has multiple mechanisms of storing it. &lt;code&gt;xattr=sa&lt;/code&gt; will instruct ZFS to save the metadata on the files inode itself. This means that reading metadata does not cause another read operation, making reading and writing metadata more performant &lt;sup id=&#34;fnref:13&#34;&gt;&lt;a href=&#34;#fn:13&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;13&lt;/a&gt;&lt;/sup&gt;. This comes at the cost of compatibility, however: At the time of writing, only ZFS on Linux and supposedly OpenZFS on macOS support this xattr storage (Although I haven&amp;rsquo;t tested the latter. Check the openzfs wiki &lt;sup id=&#34;fnref:14&#34;&gt;&lt;a href=&#34;#fn:14&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;14&lt;/a&gt;&lt;/sup&gt; for more information). Your ZFS dataset will still be mountable and accessible on FreeBSD, but extended attributes will be lost. Since this dataset is meant to be used exclusively with Linux, the lack of compatibility is ok.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-O relatime=on&lt;/code&gt; by default, most filesystems will save file access timestamps for files. This however means, that file metadata has to be refreshed every single time a file is accessed, making a read equal to a read and a write. This behaviour can be disabled by &lt;code&gt;atime=off&lt;/code&gt; in order to disable tracking of accesstime completely. &lt;code&gt;relatime&lt;/code&gt; is a compromise between atime tracking and no atime tracking, saving the timestamp only when the file is updated or if the last access is more than 24h in the past, making it not write for every read operation&lt;sup id=&#34;fnref:15&#34;&gt;&lt;a href=&#34;#fn:15&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;15&lt;/a&gt;&lt;/sup&gt;. It is said, that for maximum compatibility, &lt;code&gt;relatime&lt;/code&gt; should be used on systems - I for my part have run ext4 based systems &lt;code&gt;noatime&lt;/code&gt; (equivalent of ZFS &lt;code&gt;atime=off&lt;/code&gt;) for more than 10 years at this point and haven&amp;rsquo;t had an issue so far. So if you want to be safe, use &lt;code&gt;relatime=on&lt;/code&gt; - if you want things to be more efficient, use &lt;code&gt;atime=off&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-O mountpoint=none&lt;/code&gt; &amp;amp; &lt;code&gt;-O canmount=off&lt;/code&gt; Tells ZFS that this dataset is not mountable. It will only exist as a way to structure the rest of our datasets.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-R /mnt&lt;/code&gt; Is not an option for the zpool itself, but instructs ZFS to mount our datasets relative to &lt;code&gt;/mnt&lt;/code&gt;. This means our root dataset with &lt;code&gt;mountpoint=/&lt;/code&gt; will be mounted at &lt;code&gt;/mnt&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/dev/sda2&lt;/code&gt; Is the identifier of the blockdevice we want to use for our zpool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point we can start adding datasets to our pool:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs create -o &lt;span style=&#34;color:#008080&#34;&gt;mountpoint&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/ -o &lt;span style=&#34;color:#008080&#34;&gt;canmount&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;noauto zroot/ROOT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs create zroot/DATA
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs create -o &lt;span style=&#34;color:#008080&#34;&gt;mountpoint&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/home zroot/home
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs create -o &lt;span style=&#34;color:#008080&#34;&gt;mountpoint&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/var/lib/docker zroot/DATA/docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A couple of additional notes about the datasets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;-o mountpoint=...&lt;/code&gt; to set the mountpoint of the dataset if the parent does not have a mountpoint&lt;/li&gt;
&lt;li&gt;The dataset for the system-root (&lt;code&gt;zroot/ROOT&lt;/code&gt;) has to have &lt;code&gt;canmount=noauto&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;By default, when importing a zpool, ZFS will automatically mount all datasets on it. &lt;code&gt;canmount=noauto&lt;/code&gt; tells ZFS that while this dataset is mountable, it should not be mounted automatically. Then booting, initramfs automatically mounts the root dataset, so ZFS will not have to mount it later on &lt;sup id=&#34;fnref:16&#34;&gt;&lt;a href=&#34;#fn:16&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;16&lt;/a&gt;&lt;/sup&gt;. In live environments this means that we&amp;rsquo;ll have to mount it manually using &lt;code&gt;zfs mount {DATASET_NAME}&lt;/code&gt;. Setting &lt;code&gt;canmount=noauto&lt;/code&gt; is required for the root dataset.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To double check, that a) the pool is setup correctly and b) all datasets are mounted correctly we are going to export and reimport the pool (ZFS calls the process of removing a pool from the
system &amp;ldquo;exporting&amp;rdquo; and adding it &amp;ldquo;importing&amp;rdquo;. Think of it as ejecting and inserting a thumb drive).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zpool &lt;span style=&#34;color:#0086b3&#34;&gt;export&lt;/span&gt; zroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zpool import -R /mnt -N zroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs mount zroot/ROOT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs mount -a 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A couple of notes about this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We are using &lt;code&gt;-R /mnt&lt;/code&gt; and &lt;code&gt;-N&lt;/code&gt; for &lt;code&gt;zpool import&lt;/code&gt;. We have used &lt;code&gt;-R /mnt&lt;/code&gt; before when creating the pool: It causes the datasets to be mounted relative to &lt;code&gt;/mnt&lt;/code&gt;. &lt;code&gt;-N&lt;/code&gt; causes no datasets to be mounted by default. This is important because our root dataset has &lt;code&gt;canmount=noauto&lt;/code&gt; set and mounting other datasets automatically would cause them to be mounted in the wrong order&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zfs mount -a&lt;/code&gt; mounts all datasets that are automatically mountable&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;41-aside-device-identifier&#34;&gt;4.1 Aside: Device identifier&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Usually the recommendation with ZFS is to use /dev/disk/by-id/&amp;hellip; instead of /dev/&amp;hellip; device IDs since they are more stable&lt;/li&gt;
&lt;li&gt;With this kind of use case however, I opted for the more unstable /dev/&amp;hellip; identifier in order to make switching physical hard drives easier&lt;/li&gt;
&lt;li&gt;If you use /dev/disk/by-id/&amp;hellip; you have to set the environment variable &lt;code&gt;ZPOOL_VDEV_NAME_PATH&lt;/code&gt; in order for grub to be installable correctly &lt;sup id=&#34;fnref:17&#34;&gt;&lt;a href=&#34;#fn:17&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;17&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;42-aside-alternative-dataset-configurations&#34;&gt;4.2 Aside: Alternative dataset configurations&lt;/h3&gt;
&lt;p&gt;There are multiple alternative ways of structuring your datasets that mostly come down to personal preference. The main rules (&lt;code&gt;/&lt;/code&gt; having to have &lt;code&gt;canmount=noauto&lt;/code&gt;)
are the same for all of them - they just differ in the dataset layout.&lt;/p&gt;
&lt;h4 id=&#34;421-multiple-roots&#34;&gt;4.2.1 Multiple roots&lt;/h4&gt;
&lt;p&gt;Some guides place the system root in &lt;code&gt;zroot/ROOT/default&lt;/code&gt; in order to add support for multiple systems booting from the same pool with the same data directories.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs list 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NAME                 USED  AVAIL     REFER  MOUNTPOINT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot               1.11M  48.0G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/DATA           288K  48.0G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/DATA/docker     96K  48.0G       96K  /var/lib/docker
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/DATA/home       96K  48.0G       96K  /home
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/ROOT           192K  48.0G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/ROOT/default    96K  48.0G       96K  /
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;422-not-separating-root--data&#34;&gt;4.2.2 Not separating ROOT &amp;amp; DATA&lt;/h4&gt;
&lt;p&gt;The simplest setup would be to use the root-dataset as the system root mounted at &lt;code&gt;/&lt;/code&gt; and children datasets for data. Since by default datasets define a directory tree as
well, you will have to be careful to set &lt;code&gt;canmount=off&lt;/code&gt; on parent-datasets of your data-directories in order to have all system data in the root dataset instead of scattered
across multiple ones.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs list                          
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NAME                   USED  AVAIL     REFER  MOUNTPOINT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot                 1.18M  48.0G       96K  /
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/home              96K  48.0G       96K  /home
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/var              288K  48.0G       96K  /var
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/var/lib          192K  48.0G       96K  /var/lib
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/var/lib/docker    96K  48.0G       96K  /var/lib/docker
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zfs get canmount                  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NAME                  PROPERTY  VALUE     SOURCE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot                 canmount  noauto    &lt;span style=&#34;color:#0086b3&#34;&gt;local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/home            canmount  on        &lt;span style=&#34;color:#0086b3&#34;&gt;local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/var             canmount  off       &lt;span style=&#34;color:#0086b3&#34;&gt;local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/var/lib         canmount  off       &lt;span style=&#34;color:#0086b3&#34;&gt;local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zroot/var/lib/docker  canmount  on        &lt;span style=&#34;color:#0086b3&#34;&gt;local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;5-bootstrap-system&#34;&gt;5. Bootstrap System&lt;/h2&gt;
&lt;p&gt;At this, we can bootstrap an arch system using &lt;code&gt;pacstrap&lt;/code&gt; as we would with regular systems.
For more detailed information, check the arch installation guide &lt;sup id=&#34;fnref:18&#34;&gt;&lt;a href=&#34;#fn:18&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;18&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Before we start, we will have to mount our EFI partition as &lt;code&gt;/mnt/boot/efi&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ mkdir -p /mnt/boot/efi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ mount /dev/sda1 /mnt/boot/efi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ pacstrap /mnt base base-devel linux linux-firmware linux-headers dkms efibootmgr grub neovim
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the inclusion of &lt;code&gt;linux-headers&lt;/code&gt; and &lt;code&gt;dkms&lt;/code&gt; - these packages will be required a bit later on when installing zfs inside the bootstrapped system. I also installed
&lt;code&gt;neovim&lt;/code&gt; here as it is my preferred text editor. If you prefer a different text editor, then install a different one - you&amp;rsquo;ll just need &lt;em&gt;something&lt;/em&gt; to edit files in a second.&lt;/p&gt;
&lt;p&gt;In preparation for a later step, we can also generate a &lt;code&gt;/etc/fstab&lt;/code&gt; file for our new system and immediately edit it: The script will include all mount points, however
most of them are handled by zfs and don&amp;rsquo;t need to be in &lt;code&gt;/etc/fstab&lt;/code&gt;. Only the non-zfs (in this case only the EFI-partition) need to be in the file. Comment out all
ZFS datasets in the resulting &lt;code&gt;/mnt/etc/fstab&lt;/code&gt; and save the file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ genfstab -U /mnt &amp;gt;&amp;gt; /mnt/etc/fstab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;6-install-zfs&#34;&gt;6. Install ZFS&lt;/h2&gt;
&lt;p&gt;At this point we have a bootstrapped archlinux system in &lt;code&gt;/mnt&lt;/code&gt; but that system a) does not know about zfs and b) is not bootable. First, we are going to tackle the
first point: Install zfs inside the new system.&lt;/p&gt;
&lt;p&gt;ZFS can save data about a zpool in a cachefile. In a later step, the &lt;code&gt;zfs&lt;/code&gt; hook will copy the cachefile into the initramfs in order for our booting kernel to know where
to find the pool. This however is where a bit of weirdness comes in: The zpool cache is generated by the ZFS kernel module in the main system hosting the kernel.
This means we will have to first create the cache and then copy it into the new system by hand.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ mkdir -p /mnt/etc/zfs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ zpool &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;cachefile&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/etc/zfs/zpool.cache zroot 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: You are not free to choose any path. &lt;code&gt;/etc/zfs/zpool.cache&lt;/code&gt; is hardcoded in the initramfs hook for zfs.
This surprised me, but you can check for yourself in  &lt;code&gt;/usr/lib/initcpio/install/zfs&lt;/code&gt; &lt;sup id=&#34;fnref:19&#34;&gt;&lt;a href=&#34;#fn:19&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;19&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;At this point, it is time to use &lt;code&gt;arch-chroot&lt;/code&gt; in order to change into our newly installed system in order to continue the installation process. We will continue by adding
the archzfs pacman repository and keys as we did earlier while creating the ISO.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ arch-chroot /mnt                  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ &lt;span style=&#34;color:#0086b3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;\n[archzfs]\nServer = https://archzfs.com/\$repo/\$arch\n&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/pacman.conf 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ pacman-key -r DDF7DB817396A49B2A2723F7403BD972F75D9D76
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Especially adding the keys can be a bit awkward on real hardware as it includes transcribing a hash from another screen.
In case you are using the archiso I built (see Step 1), you can make this step easier by using scripts I have built in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ cat /zfs-pacman.conf &amp;gt;&amp;gt; /mnt/etc/pacman.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ cp /zfs-key.sh /mnt/zfs-key.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@archiso ~ $ arch-chroot /mnt              
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ /zfs-key.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can install ZFS by installing the &lt;code&gt;zfs-dkms&lt;/code&gt; and &lt;code&gt;zfs-utils&lt;/code&gt; packages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ pacman -Sy zfs-dkms zfs-utils
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, ZFS should be installed. We can confirm this by using the &lt;code&gt;zfs&lt;/code&gt; and &lt;code&gt;zpool&lt;/code&gt; commands.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ zpool list 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zroot  49.5G  2.48G  47.0G        -         -     0%     5%  1.00x    ONLINE  /mnt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ zfs list 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAME                USED  AVAIL     REFER  MOUNTPOINT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zroot              2.45G  45.5G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zroot/DATA          288K  45.5G       96K  none
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zroot/DATA/docker    96K  45.5G       96K  /mnt/var/lib/docker
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zroot/DATA/home      96K  45.5G       96K  /mnt/home
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zroot/ROOT         2.45G  45.5G     2.45G  /mnt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point we can activate the following systemd services to ensure that ZFS will be initialized correctly upon boot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;systemctl enable zfs.target&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;systemctl enable zfs-import-cache.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;systemctl enable zfs-mount.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;systemctl enable zfs-import.target&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;61-aside-zfs-linux-vs-zfs-dkms&#34;&gt;6.1 Aside: zfs-linux vs zfs-dkms&lt;/h3&gt;
&lt;p&gt;The archzfs repository contains 2 different ways of installing ZFS &lt;sup id=&#34;fnref:20&#34;&gt;&lt;a href=&#34;#fn:20&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;20&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;zfs-linux&lt;/code&gt; (or &lt;code&gt;archzfs-linux-lts&lt;/code&gt;, &lt;code&gt;archzfs-linux-zen&lt;/code&gt;, &amp;hellip;) packages provides the kernel modules specific to these kernels&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;zfs-dkms&lt;/code&gt; uses dkms &lt;sup id=&#34;fnref:21&#34;&gt;&lt;a href=&#34;#fn:21&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;21&lt;/a&gt;&lt;/sup&gt; in order to be compatible with all kernel versions. This comes at a cost of having to rebuild the kernel module every time you switch or upgrade the kernel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am opting to use the latter for 2 reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It reduces the mental load of having to install the correct package for your kernel&lt;/li&gt;
&lt;li&gt;I have been running into version incompatibilities between the kernel package and the zfs package due to the archlinux kernel being more recent than the archzfs repository anticipated&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;7-configure-bootloader--kernel-images&#34;&gt;7. Configure bootloader &amp;amp; kernel images&lt;/h2&gt;
&lt;p&gt;With our system bootstrapped and ZFS installed in it, it is time to get it into a bootable state. Mainly this means configuring initramfs to mount ZFS datasets and installing grub
as a bootloader.&lt;/p&gt;
&lt;p&gt;The high-level overview of how a linux system usually boots is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The mainboards EFI is configured to start a bootloader (in our case grub)&lt;/li&gt;
&lt;li&gt;The bootloader then loads an image (the so called initramfs), which contains the kernel and the minimum set of applications in order to start the rest of the system. The bootloader also passes certain configuration to that initramfs image.&lt;/li&gt;
&lt;li&gt;initramfs is responsible for is tasked with bringing the system into a running state. This mainly includes mounting the system root partition (or dataset) as &lt;code&gt;/&lt;/code&gt;. If the system partition is encrypted, then initramfs is also responsible for decrypting the partition (e.g. by prompting the user for a password)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To add ZFS support to this whole chain of events, first we&amp;rsquo;ll have to add the &lt;code&gt;zfs&lt;/code&gt; hook to &lt;code&gt;/etc/mkinitcpio.conf&lt;/code&gt;. The hook should be added before &lt;code&gt;filesystems&lt;/code&gt; and &lt;code&gt;keyboard&lt;/code&gt; should be added before &lt;code&gt;zfs&lt;/code&gt;. &lt;code&gt;fsck&lt;/code&gt; is specific to journaling filesystems, so it is not important for zfs. As such, the resulting line should look as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HOOKS=(base udev autodetect modconf block keyboard zfs filesystems)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save the file and use &lt;code&gt;mkinitcpio&lt;/code&gt; to regenerate the initramfs images:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ mkinitcpio -P
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we&amp;rsquo;ll have to configure grub to pass down the correct bootdevice configuration to the initramfs image. To do this, edit &lt;code&gt;/etc/default/grub&lt;/code&gt; and adjust the &lt;code&gt;GRUB_CMDLINE_LINUX=&lt;/code&gt; variable.
Add &lt;code&gt;root=zfs&lt;/code&gt; and &lt;code&gt;zfs={ROOT_DATASET_NAME}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GRUB_CMDLINE_LINUX=&amp;quot;root=zfs zfs=zroot/ROOT&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lastly, we&amp;rsquo;ll need to install grub as a EFI boot option and generate its config:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ grub-install --target&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;x86_64-efi --efi-directory&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/boot/efi --bootloader-id&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;arch-zfs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ grub-mkconfig -o /boot/grub/grub.cfg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notes about this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--bootloader-id&lt;/code&gt; can be any string. It is what will show up in your EFI configuration&lt;/li&gt;
&lt;li&gt;If you have setup your zpool using a disk id in place of the disk path (e.g. &lt;code&gt;/dev/disk/by-id/...&lt;/code&gt; instead of &lt;code&gt;/dev/...&lt;/code&gt;), then &lt;code&gt;grub-mkconfig&lt;/code&gt; will likely fail with &lt;code&gt;grub-install: error: failed to get canonical path of `/dev/bus-Your_Disk_ID-part#&lt;/code&gt;&amp;rsquo;. In this case you will have to set the environment variable &lt;code&gt;ZPOOL_VDEV_NAME_PATH=1&lt;/code&gt; &lt;sup id=&#34;fnref:17&#34;&gt;&lt;a href=&#34;#fn:17&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;17&lt;/a&gt;&lt;/sup&gt;. To set it globally for future grub config updates, add it to &amp;lsquo;&amp;rsquo;/etc/profile&amp;rsquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;71-aside-bootfs&#34;&gt;7.1 Aside: bootfs&lt;/h3&gt;
&lt;p&gt;An alternative approach to setting the dataset that should be used for booting is setting the &lt;code&gt;bootfs&lt;/code&gt; parameter on the pool.
This way the dataset name can be changed much more easily without having to go through grub config.&lt;/p&gt;
&lt;p&gt;To do so, use &lt;code&gt;root=zfs zfs=bootfs&lt;/code&gt; in &lt;code&gt;/etc/default/grub&lt;/code&gt; and set the &lt;code&gt;bootfs&lt;/code&gt; option on the zpool:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ zpool &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;bootfs&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;zroot/ROOT zroot 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This method can be interesting in order to more easily boot off of a snapshot of your system. I personally prefer the simplicity of
setting the dataset name directly in the grub config. If a system upgrade goes wrong, I will more likely completely rollback the
dataset to the last snapshot instead of booting off of the snapshot itself.&lt;/p&gt;
&lt;h3 id=&#34;72-aside-grub-root-format&#34;&gt;7.2 Aside: Grub root= format&lt;/h3&gt;
&lt;p&gt;There are 2 formats to specify the &lt;code&gt;root=...&lt;/code&gt; string in &lt;code&gt;/etc/default/grub&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;root=zfs zfs={DATASET_NAME}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;root=ZFS={DATASET_NAME}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both do the same thing - when researching the topic, you will see some guides use one format and others use the other.
If you are curious about more details as well as additional options, check out the mkinitcpio install script &lt;sup id=&#34;fnref:22&#34;&gt;&lt;a href=&#34;#fn:22&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;22&lt;/a&gt;&lt;/sup&gt;
as well as the script that will be embedded in the initramfs &lt;sup id=&#34;fnref:23&#34;&gt;&lt;a href=&#34;#fn:23&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;23&lt;/a&gt;&lt;/sup&gt;. There&amp;rsquo;s much less magic in there than you might think.&lt;/p&gt;
&lt;h2 id=&#34;8-configure-rest-of-the-system&#34;&gt;8. Configure Rest of the System&lt;/h2&gt;
&lt;p&gt;At this point, all ZFS specific configuration has been done, and we&amp;rsquo;ll have to finish configuring the system. This is not ZFS specific, so I will glaze over this. If you want more
information about this step, check out the arch installation guide &lt;sup id=&#34;fnref:24&#34;&gt;&lt;a href=&#34;#fn:24&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;24&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ hwclock --systohc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ nvim /etc/locale.gen
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ locale-gen
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Generating locales...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    de_DE.UTF-8... &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    en_DK.UTF-8... &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    en_US.UTF-8... &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Generation complete.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ &lt;span style=&#34;color:#0086b3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;LANG=en_US.UTF-8\nLV_TIME=en_DK.UTF-8&amp;#34;&lt;/span&gt; &amp;gt; /etc/locale.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ &lt;span style=&#34;color:#0086b3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;KEYMAP=colemak&amp;#39;&lt;/span&gt; &amp;gt; /etc/vconsole.conf    $ Or your preferred keyboard layout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ &lt;span style=&#34;color:#0086b3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;arch-zfs-testmachine&amp;#39;&lt;/span&gt; &amp;gt; /etc/hostname
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;root@archiso /&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;$ passwd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you need to connect to Wi-Fi or have your IP address configured via DHCP, you should also install &lt;code&gt;iwd&lt;/code&gt; and &lt;code&gt;dhcpcd&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;9-reboot&#34;&gt;9. Reboot&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;exit&lt;/code&gt; to exit the chroot environment and &lt;code&gt;reboot&lt;/code&gt; to reboot your system. You should now boot into your newly installed archlinux system running on ZFS.&lt;/p&gt;
&lt;p&gt;    &lt;figure&gt;
        &lt;a href=&#34;https://thej6s.com/article-images/zfs-done.png&#34; target=&#34;_blank&#34;&gt;
            &lt;img src=&#34;https://thej6s.com/article-images/zfs-done.png&#34; alt=&#34;A freshly booted ArchLinux installation running on top of ZFS&#34;&gt;
        &lt;/a&gt;

        
        &lt;figcaption&gt;A freshly booted ArchLinux installation running on top of ZFS&lt;/figcaption&gt;
        
    &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;10-honorable-mentions&#34;&gt;10. Honorable mentions&lt;/h2&gt;
&lt;p&gt;There are a couple of guides on installing ZFS on archlinux:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The official OpenZFS documentation contains a section named &amp;ldquo;Root on ZFS&amp;rdquo; &lt;sup id=&#34;fnref:25&#34;&gt;&lt;a href=&#34;#fn:25&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;25&lt;/a&gt;&lt;/sup&gt;. This is the most complete guide, but it guides you through an extremely complicated setup. I don&amp;rsquo;t recommend using this guide directly - but it is very helpful as a reference&lt;/li&gt;
&lt;li&gt;Arch-Wiki contains a page on installing arch on ZFS &lt;sup id=&#34;fnref:26&#34;&gt;&lt;a href=&#34;#fn:26&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;26&lt;/a&gt;&lt;/sup&gt;. It is not as complicated as the official guide, but does not explain a lot of things&lt;/li&gt;
&lt;li&gt;The YouTube channel &amp;ldquo;Stephens Tech Talks&amp;rdquo; has a video guide &lt;sup id=&#34;fnref:27&#34;&gt;&lt;a href=&#34;#fn:27&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;27&lt;/a&gt;&lt;/sup&gt; which is the simplest guide so far, showing a full runthrough of the whole thing. Mostly mirrors the arch guide, but guides you through a &amp;lsquo;golden path&amp;rsquo;. Really, this was the first guide I had found that made me understand what was going on.&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;BIOS-boot systems should work similarly but without the EFI Partition and with a different &lt;code&gt;grub-install&lt;/code&gt; command. I haven&amp;rsquo;t tried it though, so I can&amp;rsquo;t vouch for it&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://openzfs.github.io/openzfs-docs/License.html&#34; target=&#34;_blank&#34;&gt;https://openzfs.github.io/openzfs-docs/License.html&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/archzfs/archzfs/wiki&#34; target=&#34;_blank&#34;&gt;https://github.com/archzfs/archzfs/wiki&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/ZFS#Create_an_Archiso_image_with_ZFS_support&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/ZFS#Create_an_Archiso_image_with_ZFS_support&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Archiso&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/Archiso&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/j6s/archiso-zfs&#34; target=&#34;_blank&#34;&gt;https://github.com/j6s/archiso-zfs&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Iwd#Connect_to_a_network&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/Iwd#Connect_to_a_network&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://zfsonlinux.topicbox.com/groups/zfs-discuss/T5177f234d7c777ab-M68f3f3eee18142560b193538/proper-partition-type-linux&#34; target=&#34;_blank&#34;&gt;https://zfsonlinux.topicbox.com/groups/zfs-discuss/T5177f234d7c777ab-M68f3f3eee18142560b193538/proper-partition-type-linux&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:9&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Depending on the size and layout of your disk, free space may be inserted automatically. This is normal.&amp;#160;&lt;a href=&#34;#fnref:9&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:10&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/EFI_system_partition&#34; target=&#34;_blank&#34;&gt;https://en.wikipedia.org/wiki/EFI_system_partition&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:10&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:11&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://openzfs.github.io/openzfs-docs/Performance%20and%20Tuning/Workload%20Tuning.html#alignment-shift-ashift&#34; target=&#34;_blank&#34;&gt;https://openzfs.github.io/openzfs-docs/Performance%20and%20Tuning/Workload%20Tuning.html#alignment-shift-ashift&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:11&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:12&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://askubuntu.com/questions/970886/journalctl-says-failed-to-search-journal-acl-operation-not-supported&#34; target=&#34;_blank&#34;&gt;https://askubuntu.com/questions/970886/journalctl-says-failed-to-search-journal-acl-operation-not-supported&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:12&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:13&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/openzfs/zfs/commit/82a37189aac955c81a59a5ecc3400475adb56355&#34; target=&#34;_blank&#34;&gt;https://github.com/openzfs/zfs/commit/82a37189aac955c81a59a5ecc3400475adb56355&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:13&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:14&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://openzfs.org/wiki/Features#SA_based_xattrs&#34; target=&#34;_blank&#34;&gt;https://openzfs.org/wiki/Features#SA_based_xattrs&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:14&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:15&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.confirm.ch/mount-options-atime-vs-relatime/&#34; target=&#34;_blank&#34;&gt;https://blog.confirm.ch/mount-options-atime-vs-relatime/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:15&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:16&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.hook#L110&#34; target=&#34;_blank&#34;&gt;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.hook#L110&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:16&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:17&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS/5-bootloader.html&#34; target=&#34;_blank&#34;&gt;https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS/5-bootloader.html&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:17&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:18&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Installation_guide#Installation&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/Installation_guide#Installation&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:18&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:19&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.install#L44&#34; target=&#34;_blank&#34;&gt;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.install#L44&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:19&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:20&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/archzfs/archzfs/wiki#included-package-groups&#34; target=&#34;_blank&#34;&gt;https://github.com/archzfs/archzfs/wiki#included-package-groups&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:20&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:21&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Dynamic_Kernel_Module_Support&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/Dynamic_Kernel_Module_Support&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:21&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:22&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.install&#34; target=&#34;_blank&#34;&gt;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.install&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:22&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:23&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.hook&#34; target=&#34;_blank&#34;&gt;https://github.com/archzfs/zfs-utils/blob/f6e3a5e93796bbb4919ff611d22b55ae692c67e8/zfs-utils.initcpio.hook&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:23&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:24&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Installation_guide#Configure_the_system&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/Installation_guide#Configure_the_system&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:24&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:25&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS/0-overview.html&#34; target=&#34;_blank&#34;&gt;https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS/0-overview.html&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:25&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:26&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Install_Arch_Linux_on_ZFS&#34; target=&#34;_blank&#34;&gt;https://wiki.archlinux.org/title/Install_Arch_Linux_on_ZFS&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:26&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:27&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=CcSjnqreUcQ&#34; target=&#34;_blank&#34;&gt;https://www.youtube.com/watch?v=CcSjnqreUcQ&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:27&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Replacing invalid UTF-8 octets</title>
      <link>https://thej6s.com/articles/2019-07-10__replacing-invalid-utf8-octets/</link>
      <pubDate>Wed, 10 Jul 2019 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2019-07-10__replacing-invalid-utf8-octets/</guid>
      <description>&lt;h3 id=&#34;why&#34;&gt;Why?&lt;/h3&gt;
&lt;p&gt;Ever since unicode has become common between systems encoding related problems have largely gone away.
Every now and then you receive some UTF-8 encoded strings that have some unexpected code points (e.g. control characters) in them,
but that&amp;rsquo;s fairly easy to solve - You don&amp;rsquo;t even have to do it yourself, you can use ready made libararies such as &lt;a href=&#34;https://packagist.org/packages/patchwork/utf8&#34; target=&#34;_blank&#34;&gt;&amp;lt;code&amp;gt;patchwork/utf8&amp;lt;/code&amp;gt;&lt;/a&gt;
for it.&lt;/p&gt;
&lt;p&gt;Recently however I have stumbled upon something new in an API response that I had never seen before: The contents
contained octets (bytes) that are not valid in UTF-8 codepoints and break some languages (such as PHP) UTF-8 handling.&lt;/p&gt;
&lt;h3 id=&#34;say-what&#34;&gt;Say what?&lt;/h3&gt;
&lt;p&gt;A codepoint in UTF-8 describes a single character. UTF-8 uses a pagination approach in order to
let often used characters use less space while still being able to accomadate thousands of code
points. This way a single codepoint can consist of between 1-4 octets. To do this the most significant
bits of an octet are used to signal information about the pagination.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/UTF-8#Description&#34; target=&#34;_blank&#34;&gt;wikipedia article about UTF-8&lt;/a&gt; does a great job of explaining the concept.
Here is a short summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If an octet begins with &lt;code&gt;0xxxxxx&lt;/code&gt; then this octet is a standalone code point. The lowest standalone code point is &lt;code&gt;\x00&lt;/code&gt;, the highest &lt;code&gt;\x7F&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If an octet begins with &lt;code&gt;110xxxx&lt;/code&gt; then it is expected that another octet starting with &lt;code&gt;10xxxxxx&lt;/code&gt; follows. Both octets together are the full codepoint. The lowest octet containing a 2-page indicator is &lt;code&gt;\xC0&lt;/code&gt; while the highest is &lt;code&gt;\xDF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If an octet begins with &lt;code&gt;1110xxx&lt;/code&gt; then it is expected 2 other octets starting with &lt;code&gt;10xxxxxx&lt;/code&gt; follow. All octets together are the full codepoint. The lowest octet containing a 3-page indicator is &lt;code&gt;\xE0&lt;/code&gt; while the highest is &lt;code&gt;\xEF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If an octet begins with &lt;code&gt;11110xx&lt;/code&gt; then it is expected 2 other octets starting with &lt;code&gt;10xxxxxx&lt;/code&gt; follow. All octets together are the full codepoint. The lowest octet containing a 4-page indicator is &lt;code&gt;\xF0&lt;/code&gt; while the highest is &lt;code&gt;\xF7&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The lowest octet containing a following page indicator (&lt;code&gt;10xxxxxx&lt;/code&gt;) is &lt;code&gt;\x80&lt;/code&gt; while the highest is &lt;code&gt;\xBF&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This fact also means however:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;That any octet starting with &lt;code&gt;10xxxxxx&lt;/code&gt; that is not preceeded by a pagination indicator is invalid.&lt;/li&gt;
&lt;li&gt;That any octet starting with &lt;code&gt;110xxxx&lt;/code&gt;, &lt;code&gt;1110xxx&lt;/code&gt; or &lt;code&gt;11110xx&lt;/code&gt; not followed by the appropriate number of pagination indicators (&lt;code&gt;10xxxxx&lt;/code&gt;) is invalid&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To avoid confusion: These invalid octets are not invalid / unwanted codepoints. They are invalid bytes that do not add up to a full code point making the whole string an invalid UTF-8 string.&lt;/p&gt;
&lt;h3 id=&#34;the-solution&#34;&gt;The solution&lt;/h3&gt;
&lt;p&gt;As with many things regex are a solution - in my case the only performant solution I could come up with.
The example below shows the regular expressions used to replace the invalid octets with a space in PHP - although this solution should work in any language that has full regex support.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;?&lt;/span&gt;php
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 2-page indicator without 1 page behind it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; preg_replace(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;/[\xC0-\xDF](?![\x80-\xBF])/&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 3-page indicator without 2 pages behind it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; preg_replace(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;/[\xE0-\xEF](?![\x80-\xBF][\x80-\xBF])/&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 4-page indicator without 3 pages behind it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; preg_replace(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;/[\xF0-\xF7](?![\x80-\xBF][\x80-\xBF][\x80-\xBF])/&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// Paginated character without either another paginated character or page indicator in front of it.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; preg_replace(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;/(?&amp;lt;!([\xC0-\xF7]|[\x80-\xBF]))[\x80-\xBF]/&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After this the string is a valid UTF-8 string again only containing octet sequences that are valid codepoints in UTF-8.
This means that other common UTF-8 sanitization measures can be taken such as using the &lt;code&gt;/u&lt;/code&gt; flag for regular expressions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;?&lt;/span&gt;php
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// Remove control characters and unused code points (requires valid UTF-8)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; preg_replace(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;/\p{C}/u&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// Replace various kinds of whitespace with a single space
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; preg_replace(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;/\s+/u&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;$string&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;why-not-one-big-regex&#34;&gt;Why not one big regex?&lt;/h4&gt;
&lt;p&gt;Looking at this you can see 6 regular expressions that all replace things with a space - so you may wonder &amp;ldquo;wouldn&amp;rsquo;t this be more efficient in a single regex&amp;rdquo;?
In fact, all of this can be built into a single regular expression using the pipe &lt;code&gt;|&lt;/code&gt; character pretty easily.
I wondered about this and set out to test it.&lt;/p&gt;
&lt;p&gt;According to my (very limited results) there were no performance differences when using 6 small regular expressions vs one big one.
I tested this with 1000 iterations on a 15MB text file and monitored runtime as well as peak memory usage: Both did not really change.&lt;/p&gt;
&lt;p&gt;Because they are roughly the same I opted for 6 small regular expressions as this makes it easier to logically separate them as well as document them accordingly.&lt;/p&gt;
&lt;h3 id=&#34;the-disclaimer&#34;&gt;The disclaimer&lt;/h3&gt;
&lt;p&gt;A wise man once said&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;if you ever find yourself thinking &lt;em&gt;&amp;lsquo;A regex would be the perfect solution to this&amp;rsquo;&lt;/em&gt; you will soon find you have two problems&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some problems are only feasibly solvable by using regular expressions. These times are dire and you should not rush over these kinds of implementations.
Regular expressions are notoriosly hard to read and debug and I am very sure that there are still errors lurking in the expressions above.&lt;/p&gt;
&lt;p&gt;In times like this the only solution to preserve your sanity and to keep your project moving without ignoring edge cases is to write tests:
Don&amp;rsquo;t take my word for the regular expressions above - If you end up using them be sure to include tests for all kinds of incredibly dumb invalid strings
you can think of - and then some. If you cannot guarantee that something has no bugs then at least test for the edgecases you know of.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Converting Audible *.aax files</title>
      <link>https://thej6s.com/articles/2019-05-04__converting-audible-to-free-format/</link>
      <pubDate>Sat, 04 May 2019 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2019-05-04__converting-audible-to-free-format/</guid>
      <description>&lt;p&gt;Audible has a great selection of audiobooks that can be downloaded and listened to on the go.
However, there is one big caviat: All audiobooks have DRM on them and can only be listened to
using the official audible app.&lt;/p&gt;
&lt;p&gt;Wan&amp;rsquo;t to listen to the audiobook using your car&amp;rsquo;s stereo? Good luck.
Wan&amp;rsquo;t to preserve the audiobook because you want to listen to it in 10 years time? Nope.
Wan&amp;rsquo;t to use an android device without google play services or (heaven forbid) are looking forward
to the linux smartphones landing in 2019? Amazon is laughing at you.&lt;/p&gt;
&lt;p&gt;Luckily, things are not as dire as my last paragraph would lead you to believe.
If you have googled a bit you will most certainly have seen &lt;a href=&#34;https://en.code-bude.net/2017/02/12/how-to-convert-audible-aax-files-to-mp3-in-linux/&#34; target=&#34;_blank&#34;&gt;this blogpost on code-bude.net&lt;/a&gt; which outlines how to convert aax file to mp3. Since 2017 however things
have gotten easier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The selenium based &lt;a href=&#34;https://github.com/inAudible-NG/audible-activator&#34; target=&#34;_blank&#34;&gt;&amp;lt;code&amp;gt;audible-activator&amp;lt;/code&amp;gt;&lt;/a&gt; tool has been preceeded by an offline tool / rcrack preset called &lt;a href=&#34;https://github.com/inAudible-NG/tables&#34; target=&#34;_blank&#34;&gt;&amp;lt;code&amp;gt;inAudible-NG/tables&amp;lt;/code&amp;gt;&lt;/a&gt; which should be more reliable (I could not get audible-activator to work).&lt;/li&gt;
&lt;li&gt;No other tool is needed: &lt;code&gt;ffmpeg&lt;/code&gt; supports audible conversion out of the box.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-do-we-need&#34;&gt;What do we need?&lt;/h2&gt;
&lt;p&gt;To go forward we need to install 2 pieces of software:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/inAudible-NG/tables&#34; target=&#34;_blank&#34;&gt;&amp;lt;code&amp;gt;inAudible-NG/tables&amp;lt;/code&amp;gt;&lt;/a&gt; can be cloned for 1-time usage&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ffmpeg&lt;/code&gt; is probably already installed on your system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;inAudible-NG/tables&lt;/code&gt; will provide us with a activation hash that is needed to decrypt the files.
This hash is unique per account - meaning you only need to generate it once for all of your audiobooks.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ffmpeg&lt;/code&gt; will convert the files from the propriatary .aax format to whatever you like.
I recommend using opus (for best compression) or mp3 (for best support).&lt;/p&gt;
&lt;h2 id=&#34;getting-the-activation-bytes&#34;&gt;Getting the activation bytes&lt;/h2&gt;
&lt;p&gt;To extract the &amp;lsquo;activation bytes&amp;rsquo; we first need a file hash of an aax file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ffprobe audiobook.aax
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;aax&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; file &lt;span style=&#34;color:#008080&#34;&gt;checksum&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;==&lt;/span&gt; 27ae5bf7df0bab8401776657d90dca85XXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;aax&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; activation_bytes option is missing!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This hash is then passed to rcrack (from &lt;code&gt;inAudible-NG/tables&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ./rcrack . -h 27ae5b47df0bab6401776657d90dca85XXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;----------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;27ae5b47df0bab6401776657d90dca85XXXXXXXX  &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;  hex:c345eXXX
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;converting-the-file&#34;&gt;Converting the file&lt;/h2&gt;
&lt;p&gt;Converting the file can be done with all of the usual ffmpeg options with an additional &lt;code&gt;-activation_bytes&lt;/code&gt; option containing the hex hash from above.
Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ffmpeg &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -i audiobook.aax &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -activation_bytes c345eXXX &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    freedom.mp3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;notes&#34;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;All steps shown here are meant for file preservation. If you want to listen to quality audiobooks then buy, don&amp;rsquo;t pirate.&lt;/li&gt;
&lt;li&gt;The hashes and activation bytes in the examples above are obviously anonymized.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Decrypting boot drives remotely using dropbear</title>
      <link>https://thej6s.com/articles/2019-03-05__decrypting-boot-drives-remotely/</link>
      <pubDate>Tue, 05 Mar 2019 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2019-03-05__decrypting-boot-drives-remotely/</guid>
      <description>&lt;p&gt;Thesedays there is no reason not to encrypt your bootdisk: I would even say that you are acting negligently if you don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;There are moments where you cannot be physically present to decrypt a drive: For example in a server, a NAS or if you want to access your desktop PC remotely. Wouldn&amp;rsquo;t it be nice to be able to ssh into your machine in order to enter the encryption password? With &lt;code&gt;dropbear&lt;/code&gt; that&amp;rsquo;s possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Dropbear seems to have been very actively developed over the last couple of years - a lot of guides you will find on the internet are outdated. This article is up-to-date as of the beginning of 2019.&lt;/p&gt;
&lt;h2 id=&#34;what-you-need&#34;&gt;What you need&lt;/h2&gt;
&lt;p&gt;This article assumes a up-to-date Debian or Ubuntu system - though similar ready to use initramfs packages are available for other systems. All steps have been tested on Debian 10 but should work on Ubuntu in exactly the same way.&lt;/p&gt;
&lt;h2 id=&#34;installating-dropbear&#34;&gt;Installating &lt;code&gt;dropbear&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Dropbear consists of 2 components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dropbear&lt;/code&gt; is a very lightweight SSH server&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dropbear-initramfs&lt;/code&gt; is a initramfs integration for the &lt;code&gt;dropbear&lt;/code&gt; SSH Server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have said initramfs a bunch without explaining what it does. For all intents and purposes initramfs can be thought of a micro-system that starts before you operating system that takes care of some plumbing (such as decrypting and mounting drives).&lt;/p&gt;
&lt;h2 id=&#34;configuring-dropbear&#34;&gt;Configuring &lt;code&gt;dropbear&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;dropbear-initramfs&lt;/code&gt; only minimal configuration is needed: The only thing you have to do in order to get everything to work is add the public key of your client device to &lt;code&gt;/etc/dropbear-initramfs/authorized_keys&lt;/code&gt; and run &lt;code&gt;sudo update-initramfs -u&lt;/code&gt; to update the initramfs image.&lt;/p&gt;
&lt;p&gt;When rebooting the PCs IP-Address will be printend to the screen. You can now connect to the System using &lt;code&gt;ssh root@{YOUR_IP}&lt;/code&gt; and use &lt;code&gt;cryptroot-unlock&lt;/code&gt; in order to unlock your disks.&lt;/p&gt;
&lt;h2 id=&#34;configuring-a-static-ip-address&#34;&gt;Configuring a static IP-Address&lt;/h2&gt;
&lt;p&gt;Of course, looking at the screen to get the IP Address defeats the purpose - thus we have to make sure that the PC uses a static IP-Address while in initramfs. This configuration is different from the one already present in (&lt;code&gt;/etc/network/interfaces&lt;/code&gt; or via NetworkManager) as it has to be present before the system is decrypted and booted.&lt;/p&gt;
&lt;p&gt;To do that edit &lt;code&gt;/etc/initramfs-tools/initramfs.conf&lt;/code&gt; and add a line under the &lt;code&gt;DEVICE=&lt;/code&gt; line.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;IP=192.168.0.30:192.168.0.1:255.255.255.0::enp5s0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This line is in the format &lt;code&gt;IP=ipaddress::gateway::netmask::hostname:eth&lt;/code&gt; - the hostname can be omitted.&lt;/p&gt;
&lt;p&gt;After running &lt;code&gt;sudo update-initramfs -u&lt;/code&gt; again to update the initramfs image our PC will now boot using that static IP Address.&lt;/p&gt;
&lt;h2 id=&#34;avoid-host-key-colissions-on-the-client&#34;&gt;Avoid host key colissions on the client&lt;/h2&gt;
&lt;p&gt;If you regularly ssh into the machine you might notices SSH warning you about changing host keys - this is because openssh and dropbear are 2 separate SSH Keys with separate sets of host keys. Using the same key for both is not recommended as initramfs is not encrypted.&lt;/p&gt;
&lt;p&gt;To avoid host key colissions you can configure a separate trusted hosts store in the &lt;code&gt;~/.ssh/config&lt;/code&gt; of your client:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Host jo-desktop-unlock
	Hostname 192.168.0.30
	User root
	UserKnownHostsFile ~/.ssh/known_hosts.initramfs
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;extra-only-allow-decryption&#34;&gt;Extra: Only allow decryption&lt;/h2&gt;
&lt;p&gt;Dropbear drops you into a shell by default - this has the main disadvantage that you have to remember the &lt;code&gt;cryptroot-unlock&lt;/code&gt; command (there is no real help in the shell) which is error prone.&lt;/p&gt;
&lt;p&gt;Luckily &lt;code&gt;dropbear&lt;/code&gt; has a way of running a specific command immediately after connecting. To immediately run the unlock command add the following to &lt;code&gt;/etc/dropbear-initramfs/config&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DROPBEAR_OPTIONS=&amp;#39;-c cryptroot-unlock&amp;#39;
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>Encapsulating nonfree applications using docker</title>
      <link>https://thej6s.com/articles/2019-02-20__encapsulating-nonfree-applications-using-docker/</link>
      <pubDate>Tue, 19 Feb 2019 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2019-02-20__encapsulating-nonfree-applications-using-docker/</guid>
      <description>&lt;p&gt;In a &lt;a href=&#34;../2019-02-14__desktop-applications-in-containers&#34;&gt;previous article&lt;/a&gt; I lamented the fact that many modern nonfree applications setup their own package manager repositories instead of submitting their packages to the official repositories. I also started exploring ways to avoid having to install nonfree package sources into your system by running desktop applications in containers.&lt;/p&gt;
&lt;p&gt;I have now sucessfully encapsulated a bunch of applications that can be found on github: &lt;a href=&#34;https://github.com/j6s/docker-desktop-apps&#34; target=&#34;_blank&#34;&gt;https://github.com/j6s/docker-desktop-apps&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Desktop applications in containers</title>
      <link>https://thej6s.com/articles/2019-02-14__desktop-applications-in-containers/</link>
      <pubDate>Thu, 14 Feb 2019 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2019-02-14__desktop-applications-in-containers/</guid>
      <description>&lt;p&gt;I have been playing heavily with docker in the last couple of weeks and the idea of encapsulating applications including all of their dependencies and cruft they bring into a kind of &amp;lsquo;sub-system&amp;rsquo; that only has well defined shared resources with the host did not only speak to me when thinking about servers and development environments. I have seen a trend with modern, closed source applications: They all start to provide their own repository for your package manager instead of bothering with the official ones. Adding a third party repository to your package manager simply to install spotify or slack is a question of trust - the list of third party repositories should be minimal.&lt;/p&gt;
&lt;h2 id=&#34;dockerize-it&#34;&gt;Dockerize it&lt;/h2&gt;
&lt;p&gt;Since in Linux everything is a file and docker can mount files to containers the thought of putting applications into containers is not very far fetched: It&amp;rsquo;s as easy as mounting the correct set of sockets to the container and the containerized application is able to talk to the system resources.&lt;/p&gt;
&lt;h3 id=&#34;x11&#34;&gt;X11&lt;/h3&gt;
&lt;p&gt;In order for graphical output to work there are 3 things that need to be done:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The host must allow remote connections to X11 (since the container is seen as remote from the point of X11). This can be done by using &lt;code&gt;xhost local:root&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The X11 socket (Located under &lt;code&gt;/tmp/.X11-unix&lt;/code&gt;) needs to be mounted to the container&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;$DISPLAY&lt;/code&gt; environment variable needs to be passed down to the container&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To test if the connection to X11 is working correctly the following can be executed to setup a simple container containing the &lt;code&gt;xeyes&lt;/code&gt; application:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker build -t &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;thej6s/xeyes&amp;#39;&lt;/span&gt; -  &lt;span style=&#34;color:#d14&#34;&gt;&amp;lt;&amp;lt; __EOF__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;FROM debian
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y x11-apps
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;ENV DISPLAY $DISPLAY
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;CMD xeyes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;__EOF__&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;XSOCK&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/tmp/.X11-unix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xhost local:root
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -v &lt;span style=&#34;color:#008080&#34;&gt;$XSOCK&lt;/span&gt; --net host &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;thej6s/xeyes&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;    &lt;figure&gt;
        &lt;a href=&#34;https://thej6s.com/article-images/xeyes-docker.png&#34; target=&#34;_blank&#34;&gt;
            &lt;img src=&#34;https://thej6s.com/article-images/xeyes-docker.png&#34; alt=&#34;xeyes running inside of docker&#34;&gt;
        &lt;/a&gt;

        
        &lt;figcaption&gt;xeyes running inside of docker&lt;/figcaption&gt;
        
    &lt;/figure&gt;&lt;/p&gt;
&lt;h3 id=&#34;sound-alsa&#34;&gt;Sound: Alsa&lt;/h3&gt;
&lt;p&gt;The next big hardware device that a desktop application might want to use is sound input and output.
The simplest way is to let the guest handle all of the audio related tasks using alsa acessing the audio device
directly. This would work similar to the X11 socket above - but with the &lt;code&gt;/dev/snd&lt;/code&gt; device.&lt;/p&gt;
&lt;p&gt;This works - but has a major drawback: It places all of the control over audio into the containers.
Imagine having to ssh into multiple containers to regulate your volume.&lt;/p&gt;
&lt;h3 id=&#34;sound-pulseaudio&#34;&gt;Sound: Pulseaudio&lt;/h3&gt;
&lt;p&gt;Most distributions and most users are using pulseaudio in order to configure and manager their sound
environment. A dockerized application should play into the global pulse instance instead of acessing
the audio device directly. This way all dockerized applications are still managable by using a tool
such as &lt;code&gt;pavucontrol&lt;/code&gt; on the host.&lt;/p&gt;
&lt;p&gt;This however presents a couple of difficulties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pulseaudio is started as a user service and is bound to the current machine and user&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to overcome these hurdles a couple of steps need to be taken:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create an environment that is accepted by pulseaudio IPC
&lt;ul&gt;
&lt;li&gt;Create a user in the container with the same uid as the user on the host system&lt;/li&gt;
&lt;li&gt;Mount &lt;code&gt;/etc/machine-id&lt;/code&gt; into the container&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mount the pulse audio socket (&lt;code&gt;/run/user/${UID}/pulse&lt;/code&gt;) into the container&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following starts firefox in a container with support for pulseaudio for sound:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;XSOCK&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/tmp/.X11-unix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;$(&lt;/span&gt;id -u&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker build -t &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;j6s/firefox&amp;#39;&lt;/span&gt; - &lt;span style=&#34;color:#d14&#34;&gt;&amp;lt;&amp;lt; __EOF__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;FROM debian
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y firefox-esr
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;ENV HOME /home/user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN useradd -u ${UID} \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        --create-home --home-dir \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        /home/user user &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    usermod -a -G audio user &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    chown -R user:user /home/user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;USER user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;WORKDIR /home/user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;CMD firefox-esr
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;__EOF__&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run --rm &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -v &lt;span style=&#34;color:#008080&#34;&gt;$XSOCK&lt;/span&gt;:&lt;span style=&#34;color:#008080&#34;&gt;$XSOCK&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -v /etc/machine-id:/etc/machine-id &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -v /run/user/&lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;/pulse:/run/user/&lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;/pulse &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    -e &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;DISPLAY=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;DISPLAY&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    --name firefox &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;j6s/firefox&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;    &lt;figure&gt;
        &lt;a href=&#34;https://thej6s.com/article-images/firefox-docker.png&#34; target=&#34;_blank&#34;&gt;
            &lt;img src=&#34;https://thej6s.com/article-images/firefox-docker.png&#34; alt=&#34;Firefox running inside of a container&#34;&gt;
        &lt;/a&gt;

        
        &lt;figcaption&gt;Firefox running inside of a container&lt;/figcaption&gt;
        
    &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;spotify&#34;&gt;Spotify&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s revisit how I started this article: The idea of encapsulating third party closed source applications appealed to me - that was the point of all of this. Spotify is the easiest example, as all that it needs is X11 and sound output.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;XSOCK&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/tmp/.X11-unix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;$(&lt;/span&gt;id -u&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;DIR&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;pwd&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;function&lt;/span&gt; run &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#0086b3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&lt;/span&gt;$&lt;span style=&#34;color:#d14&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;$@&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#0086b3&#34;&gt;eval&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run mkdir -p data/config data/cache
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run chown -R &lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt; data/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run chmod -R &lt;span style=&#34;color:#099&#34;&gt;755&lt;/span&gt; data/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run docker build -t &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;j6s/spotify&amp;#39;&lt;/span&gt; - &lt;span style=&#34;color:#d14&#34;&gt;&amp;lt;&amp;lt; __EOF__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;FROM debian
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y gpg
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN apt-key adv \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        --keyserver hkp://keyserver.ubuntu.com:80 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        --recv-keys 931FF8E79F0876134EDDBDCCA87FF9DF48BF1C90 &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    echo &amp;#39;deb http://repository.spotify.com stable non-free&amp;#39; &amp;gt; /etc/apt/sources.list.d/spotify.list &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    apt-get update &amp;amp;&amp;amp;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    apt-get install -y -q --no-install-recommends spotify-client
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN apt-get install -y -q --no-install-recommends \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        pulseaudio \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        libgl1-mesa-dri \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;        libgl1-mesa-glx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;ENV HOME /home/user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;RUN useradd -u ${UID} --create-home --home-dir /home/user user &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    usermod -a -G audio user &amp;amp;&amp;amp; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;    chown -R user:user /home/user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;USER user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;WORKDIR /home/user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;CMD spotify
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;__EOF__&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run docker run --rm &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	-v &lt;span style=&#34;color:#008080&#34;&gt;$XSOCK&lt;/span&gt;:&lt;span style=&#34;color:#008080&#34;&gt;$XSOCK&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	-v /etc/machine-id:/etc/machine-id &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	-v /run/user/&lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;/pulse:/run/user/&lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;UID&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;/pulse &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	-v &lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;DIR&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;/data/config:/home/user/.config &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	-v &lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;DIR&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;/data/cache:/home/user/.cache &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	-e &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;DISPLAY=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;DISPLAY&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	--name spotify &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;j6s/spotify&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;    &lt;figure&gt;
        &lt;a href=&#34;https://thej6s.com/article-images/spotify-docker.png&#34; target=&#34;_blank&#34;&gt;
            &lt;img src=&#34;https://thej6s.com/article-images/spotify-docker.png&#34; alt=&#34;Spotify running inside of a docker container&#34;&gt;
        &lt;/a&gt;

        
        &lt;figcaption&gt;Spotify running inside of a docker container&lt;/figcaption&gt;
        
    &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;further-reading&#34;&gt;Further reading&lt;/h2&gt;
&lt;p&gt;The following blogpost (and especially the github repository by the author) is very interesting when it comes to desktop applications running inside of containers: &lt;a href=&#34;https://blog.jessfraz.com/post/docker-containers-on-the-desktop/&#34; target=&#34;_blank&#34;&gt;https://blog.jessfraz.com/post/docker-containers-on-the-desktop/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I wrote a follow-up article: &lt;a href=&#34;https://thej6s.com/articles/2019-02-20__encapsulating-nonfree-applications-using-docker/&#34; target=&#34;_blank&#34;&gt;Encapsulating nonfree applications using docker&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Automatic E-Mail attachement extraction</title>
      <link>https://thej6s.com/articles/2019-01-03__automatic-email-attachement-extraction/</link>
      <pubDate>Thu, 03 Jan 2019 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2019-01-03__automatic-email-attachement-extraction/</guid>
      <description>&lt;p&gt;I got a &lt;a href=&#34;https://getrocketbook.com/&#34; target=&#34;_blank&#34;&gt;reusable notebook&lt;/a&gt; for Christmas which is accompanied by a simple app
that makes scanning your notes really easy. Scans of your notes are converted into PDF files which you can send
yourself via E-Mail.&lt;/p&gt;
&lt;p&gt;All of that is near — but I would prefer having them in a special folder that is synced across my devices as that
folder is part of my &lt;a href=&#34;https://gettingthingsdone.com/wp-content/uploads/2014/10/Weekly_Review_Checklist.pdf&#34; target=&#34;_blank&#34;&gt;weekly review&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So an idea popped into my head: Could I configure a mail client that simply saves attachments sent to a special mail
address into a folder automatically — similar to how there are special Kindle &amp;amp; Evernote E-Mail addresses that save
the contents to the respective services? Turns out, there is.&lt;/p&gt;
&lt;h2 id=&#34;what-you-need&#34;&gt;What you need&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An always-on Linux computer such as a raspberry pi, a server or a NAS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getmail&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Package named &lt;code&gt;getmail4&lt;/code&gt; on Debian.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;procmail&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;munpack&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Package named &lt;code&gt;mpack&lt;/code&gt; on Debian.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;E-Mail is a pretty clearly defined system that works very unix-y on servers: Multiple tools are involved that all do a single thing — but they
do that single thing very well. I this case our stack uses &lt;code&gt;getmail&lt;/code&gt; for fetching mail from a server via IMAP or SMTP, &lt;code&gt;procmail&lt;/code&gt; for filtering
those mails and &lt;code&gt;munpack&lt;/code&gt; in order to extract attachments to those mails.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-getmail&#34;&gt;Setting up &lt;code&gt;getmail&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In order to use getmail, we will setup a configuration file in &lt;code&gt;~/.getmail/getmailrc&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[retriever]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;SimpleIMAPSSLRetriever&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;server&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;imap.myserver.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;username&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;my_username&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;password&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;my_password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[destination]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;MDA_external&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;path&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;/usr/bin/procmail&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[options]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;verbose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;read_all&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;delete&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;delete_after&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;delete_bigger_than&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;max_bytes_per_session&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;max_message_size&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;max_messages_per_session&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;delivered&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;received&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;message_log&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;~/getmail.log&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;message_log_syslog&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;message_log_verbose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;[retriever]&lt;/code&gt; section defines where the mails are being fetched from: In this case using IMAP over SSL from &lt;code&gt;imap.myserver.com&lt;/code&gt; using &lt;code&gt;mys username&lt;/code&gt; and &lt;code&gt;my_password&lt;/code&gt;. &lt;code&gt;getmail&lt;/code&gt; ships with retrievers for all major E-Mail protocols which can be seen in the &lt;a href=&#34;https://www.systutorials.com/docs/linux/packages/getmail-4.54.0/configuration.html#conf-retriever&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;[destination]&lt;/code&gt; section then defines what is called an MDA — a &lt;strong&gt;M&lt;/strong&gt;ail &lt;strong&gt;D&lt;/strong&gt;elivery &lt;strong&gt;A&lt;/strong&gt;gent: A different application that will deliver / process the mails. &lt;code&gt;getmail&lt;/code&gt; supports a couple of other different destinations but &lt;code&gt;MDA_external&lt;/code&gt; is what we need in order to pass on the fetched mails to &lt;code&gt;procmail&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At this point we have successfully configured &lt;code&gt;getmail&lt;/code&gt; in order to connect to the IMAP server and fetch E-Mails from it.&lt;/p&gt;
&lt;h2 id=&#34;sorting-mails-using-procmail&#34;&gt;Sorting mails using &lt;code&gt;procmail&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;procmail&lt;/code&gt; is a simple application that can be used as an MDA in order to filter and sort Mails into different mailboxes or pass them on to other processes if they match certain criteria. It uses as configuration file in &lt;code&gt;.procmailrc&lt;/code&gt; which looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#008080&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr/bin:/bin:/usr/local/bin:&lt;span style=&#34;color:#008080&#34;&gt;$HOME&lt;/span&gt;/bin:&lt;span style=&#34;color:#008080&#34;&gt;$PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Process all mails that arrive for save-notes@mydomain.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;:0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* ^TOsave-notes@mydomain&lt;span style=&#34;color:#d14&#34;&gt;\.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| munpack -q -t -C &lt;span style=&#34;color:#008080&#34;&gt;$HOME&lt;/span&gt;/dropping_area
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;procmailrc&lt;/code&gt; format takes some getting used to.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:0&lt;/code&gt; denotes the beginning of a new rule&lt;/li&gt;
&lt;li&gt;&lt;code&gt;* ^TOsave-notes@mydomain\.com&lt;/code&gt; defines conditions that must be matched. In this case all mails that are sent to &lt;code&gt;save-notes@mydomain.com&lt;/code&gt; are being processed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;| munpack -q -t -C $HOME/dropping_area&lt;/code&gt; defines the action to take with that mail. I this case the mail is being piped to &lt;code&gt;munpack&lt;/code&gt; which extracts all attachments into &lt;code&gt;~/dropping_area&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;its-done&#34;&gt;It&amp;rsquo;s done&lt;/h2&gt;
&lt;p&gt;Now, every time &lt;code&gt;getmail&lt;/code&gt; is being executed new mails will be fetched from the server, filtered and attachments will be extracted. To periodically execute &lt;code&gt;getmail&lt;/code&gt; a simple cronjob can be added for the current user:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;*/5 * * * * getmail
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;why-not-use-fetchmail&#34;&gt;Why not use fetchmail?&lt;/h2&gt;
&lt;p&gt;When researching this topic you will find a lot of solutions using &lt;code&gt;fetchmail&lt;/code&gt; instead of &lt;code&gt;getmail&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, using &lt;code&gt;fetchmail&lt;/code&gt; has a major disadvantage: &lt;code&gt;fetchmail&lt;/code&gt; fetches all unread messages from the server and marks them as read. This behaviour is not wanted for situations with &amp;lsquo;catchall&amp;rsquo; mail addresses, where only a small portion of the E-Mails are actually sent to this special mail address.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;getmail&lt;/code&gt; tracks which mails have already been processed by using the message id instead of relying on the &amp;lsquo;read&amp;rsquo; state on the server thereby not modifying any state on the server itself.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#45</title>
      <link>https://thej6s.com/articles/2018-11-05__things-i-learned-2018-45/</link>
      <pubDate>Mon, 05 Nov 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-11-05__things-i-learned-2018-45/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://moa.party/&#34; target=&#34;_blank&#34;&gt;moa&lt;/a&gt; is a service that syncs your posts to mastodon and twitter&lt;/li&gt;
&lt;li&gt;puppeteer needs namespacing in linux kernels. To enable it, see this stack overflow post: &lt;a href=&#34;https://superuser.com/questions/1094597/enable-user-namespaces-in-debian-kernel&#34; target=&#34;_blank&#34;&gt;https://superuser.com/questions/1094597/enable-user-namespaces-in-debian-kernel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;While laravel homestead is a very neat way to setup a vagrant box for a project it has a certain chicken &amp;amp; egg problem: Because it is installed via composer you need a PHP Version compatible with your project - but if you have that you probably don&amp;rsquo;t need a vagrant box for easier setup.&lt;/li&gt;
&lt;li&gt;jenkinsfile-runner allows you to run a jenkinsfile locally &lt;a href=&#34;https://github.com/jenkinsci/jenkinsfile-runner&#34; target=&#34;_blank&#34;&gt;https://github.com/jenkinsci/jenkinsfile-runner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;badblocks&lt;/code&gt; is a utility that can be used to scan a hard drive for bad blocks
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;badblocks -wvs&lt;/code&gt; will perform a write test where it will write a pattern to the device and read it back. For empty disks this is the best way to check their health befor eusing them elsewhere.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The cryptopals challenges are a fun way to get a hands-on introduction to practical encryption fundamentals&lt;/li&gt;
&lt;li&gt;Go has builtin handling for hex/base64 &amp;amp; []byte en- and decoding&lt;/li&gt;
&lt;li&gt;In Go the &lt;code&gt;^&lt;/code&gt; operator is short for XOR&lt;/li&gt;
&lt;li&gt;In go strings are just syntactic sugar over arrays and characters over integers / bytes. Therefor operations such as &lt;code&gt;int(character) - &#39;a&#39;&lt;/code&gt; are completely valid.&lt;/li&gt;
&lt;li&gt;In vue watchers can also be declared by using the &lt;code&gt;this.$watch&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;In vue watchers can be declared using &lt;code&gt;{ immediate: true }&lt;/code&gt; in order to execute the watcher once after it was declared in order to setup initial state&lt;/li&gt;
&lt;li&gt;In vue a watcher may also be a string containing the name of the method handling the change event.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Setting up Neos: Neos made easy #1</title>
      <link>https://thej6s.com/articles/2018-10-31__setting-up-neos/</link>
      <pubDate>Wed, 31 Oct 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-10-31__setting-up-neos/</guid>
      <description>&lt;p&gt;Kicking off a new series, in this short video I show how to setup Neos from start to finish.&lt;/p&gt;
&lt;p&gt;The series will continue on explaining everything a developer needs to know in order to create and
maintain Neos websites.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#36</title>
      <link>https://thej6s.com/articles/2018-09-06__things-i-learned-2018-36/</link>
      <pubDate>Thu, 06 Sep 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-09-06__things-i-learned-2018-36/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;The remote of IKEA Tradfri lamps is not very intuitive:
&lt;ul&gt;
&lt;li&gt;The remote is round and can be mounted in the frame in any orientation&lt;/li&gt;
&lt;li&gt;The symbols for more and less light are almost the same making accidentally mounting it upside-down very easy&lt;/li&gt;
&lt;li&gt;There is no indication to what &amp;rsquo;left&amp;rsquo; and &amp;lsquo;right&amp;rsquo; mean
&lt;a href=&#34;https://thej6s.com/assets/remote.jpg&#34;&gt;&lt;img src=&#34;https://thej6s.com/assets/remote.jpg&#34;  style=&#34;max-width: 300px;&#34;/&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Using xdebugs coverage filter speeds up generation of code coverage for tests considerably by only scanning the given directories instead of all code (including vendor): &lt;a href=&#34;https://xdebug.org/docs/code_coverage#coverage-filter&#34; target=&#34;_blank&#34;&gt;https://xdebug.org/docs/code_coverage#coverage-filter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You cannot use the pullup resistor on D0 on a ESP8266 board&lt;/li&gt;
&lt;li&gt;The Qt installer will check for enough space on the volume mounted as &lt;code&gt;/&lt;/code&gt; even if the destination is not on that volume.&lt;/li&gt;
&lt;li&gt;NodeMCU is a firmware for ESP8266 devices that makes developing for the devices almost as easy as writing simple scripts&lt;/li&gt;
&lt;li&gt;In Go, simple constant expressions are evaluated at compile time &lt;a href=&#34;http://rosettacode.org/wiki/Compile-time_calculation#Go&#34; target=&#34;_blank&#34;&gt;http://rosettacode.org/wiki/Compile-time_calculation#Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In Lua strings are concatenated using &lt;code&gt;..&lt;/code&gt;: &lt;code&gt;print(&amp;quot;Sending count to server: &amp;quot; .. count)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A thinkpad t470 has some kind of protection that disables USB interfaces for a short moment if your short 5V to ground (I suppose to prevent frying components?)&lt;/li&gt;
&lt;li&gt;In a TYPO3 RealUrl lookupTable Configuration the &lt;code&gt;useUniqueCache_conf.encodeTitle_userProc&lt;/code&gt; method can be used to manually transform the url using user defined logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;	&amp;#39;useUniqueCache_conf&amp;#39; =&amp;gt; [
		&amp;#39;encodeTitle_userProc&amp;#39; =&amp;gt; function(array $conf) {
			$processed = strtolower($conf[&amp;#39;title&amp;#39;]);
			$processed = preg_replace(&amp;#39;/\\W+/&amp;#39;, &amp;#39;-&amp;#39;, $processed);
			return $processed;
		}
	],
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>About Attentional Fracturing</title>
      <link>https://thej6s.com/articles/2018-09-04__about-attentional-fracturing/</link>
      <pubDate>Tue, 04 Sep 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-09-04__about-attentional-fracturing/</guid>
      <description>&lt;p&gt;There has been a phenomenon that I have measured and seen in myself and people
around me. Up to today I did not have the right words to describe what exactly
it is that I am talking about. Listening to
&lt;a href=&#34;http://www.hellointernet.fm/podcast/108&#34; target=&#34;_blank&#34;&gt;the latest episode of the Hello Internet Podcast&lt;/a&gt;
gave me a word that conveys my observations: Attentional Fracturing.&lt;/p&gt;
&lt;p&gt;We are increasingly living in an environment where everything and everyone around
us is trying to deal with our attention. Ads constantly bombarding us, TVs in
bars, phones always buzzing, &amp;hellip; In a way attention has become the currency of
this new digital age that we live in.&lt;/p&gt;
&lt;h2 id=&#34;introspective&#34;&gt;Introspective&lt;/h2&gt;
&lt;p&gt;Before talking about the problem, I invite you - the reader - to think about
your own behaviour - how you work, how you spend your time, where you put your
attention. Let me ask you a series of questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In your last week - what was the longest time one single thing has held your attention without being interrupted by Twitter, Facebook, Slack or anything else?&lt;/li&gt;
&lt;li&gt;When did you have the last &lt;strong&gt;meaningful&lt;/strong&gt; conversation with someone that was not interrupted by one of you looking at your phone or &lt;em&gt;quickly&lt;/em&gt; answering that text message?&lt;/li&gt;
&lt;li&gt;When was the last time you have spent 10 minutes reading without having the urge of being interrupted by something?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While asking these questions to myself I came to the conclusion, that my attention
span as decreased to an embarrassingly small level: At any time there are a number of
indicators on my screen - indicating whether or not there are new messages sent to me
on any number of - different mediums. Phones and tablets demanding attention and
everything most things even interrupt me in my thought process when they think
something important has happened by sending notifications.&lt;/p&gt;
&lt;p&gt;When reading I constantly pick up my phone - &lt;em&gt;just in case&lt;/em&gt; someone tried to reach me.
While working I look at that slack notification icon every couple of seconds -
&lt;em&gt;just in case&lt;/em&gt; someone messaged me. It has been a long while since I have spent
a large amount of attention on a single thing.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;The internet is a beautiful place: Every possible piece of information is at our
fingertips at any given point in time. Most times we don&amp;rsquo;t even have to do the
hard work of finding the information ourselves - there is already someone
that summarized the important portions of a book in an article and someone else
that summarized the important portions of the article in a comment.&lt;/p&gt;
&lt;p&gt;The unimaginable mass of summaries and short versions of everything out on the
internet combined with the &amp;lsquo;always on&amp;rsquo; mentality regarding communications has trained
our brains to an ever quicker reward cycle and with that ever shorter attention spans.
At times it feels like the minimum unit of attention that can be given to a single
thing has decreased significantly - as if it had been fractured into little pieces.&lt;/p&gt;
&lt;h2 id=&#34;possible-solutions&#34;&gt;Possible solutions&lt;/h2&gt;
&lt;p&gt;The primary goal of this article is to highlight the problem of attentional
fracturing in order to prompt readers to start thinking about their own attention
spans, not to give a solution. However, here are a couple of things that I
personally have started doing in order to combat the issue. Most of them boil
down to making it harder to unintentionally fracturing your attention into pieces:
Changing the thing that captures your attention must become more intentional
in order to control it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Limit messengers that are always running.&lt;/li&gt;
&lt;li&gt;Messengers that should be always running (because having them running has a net-positive impact) must not always be visible: They can be delegated to a certain workspace that I have to conciously switch to for communications.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Pomodoro_Technique&#34; target=&#34;_blank&#34;&gt;Pomodoro Timers&lt;/a&gt; are a great technique in order to micro-schedule your time into manageble blocks of work and free time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://chrome.google.com/webstore/detail/stayfocusd/laankejkbhbdhmipfmgcngdelahlfoji&#34; target=&#34;_blank&#34;&gt;StayFocusd&lt;/a&gt; is a chrome extension that only allows access to distracting websites outside of work timers.&lt;/li&gt;
&lt;li&gt;Make it harder to unintentionally grab my phone by placing it in my backpack instead of my pocket.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#34</title>
      <link>https://thej6s.com/articles/2018-08-21__things-i-learned-2018-34/</link>
      <pubDate>Tue, 21 Aug 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-08-21__things-i-learned-2018-34/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In git, you can merge multiple sources at once - a merge does not always have to have 2 parents. If you want to merge 3 feature branches into your current branch you can use &lt;code&gt;git merge feature-1 feature-2 feature-3&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DSLite is basically a IPv6-&amp;gt;4 tunnel that uses the same IPv4 Endpoint for multiple Clients thus allows a service provider to serve more Clients than they have IPv4 Adresses for&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Because of this direct access to a router (or a port forward) via the IPv4 Address of a connection is not possible as there essentially is another router doing NAT in front of your router at home.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SSH multihop can be used to connect to a IPv6-only connection if the current connection only supports IPv4. It is however important to note that this will relay all traffic via the server used as a hopping point.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#33</title>
      <link>https://thej6s.com/articles/2018-08-16__things-i-learned-2018-33/</link>
      <pubDate>Thu, 16 Aug 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-08-16__things-i-learned-2018-33/</guid>
      <description>&lt;p&gt;It has been a couple of weeks since I last did one of these - so the list is a little bit longer this time.
This list contains a bunch of things that I have learned since the last article.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google chrome registers a cronjob in /etc/cron.daily/google-chrome when installing.&lt;/li&gt;
&lt;li&gt;In order to get the contents of a slot as a string in vue you have to render the slot in the actual DOM and then grab the &lt;code&gt;innerHTML&lt;/code&gt; of that rendered section.&lt;/li&gt;
&lt;li&gt;Webpacks new &amp;lsquo;better&amp;rsquo; code splitting option via &lt;code&gt;splitChunks&lt;/code&gt; is pretty much useless when not using it in combination with &lt;code&gt;HtmlWebpackPlugin&lt;/code&gt; which in many instances cannot be used (if the app is not a pure SPA)&lt;/li&gt;
&lt;li&gt;On a mac MAMP Pro ships with it&amp;rsquo;s own libtool binary that is not up-to-date. If you foolishly prepend the MAMP &lt;code&gt;bin/&lt;/code&gt; directories to your &lt;code&gt;$PATH&lt;/code&gt; you will run into many errors regarding libtool - most notably the &lt;code&gt;-static&lt;/code&gt; argument not being recognized. Simply changing the order of the &lt;code&gt;$PATH&lt;/code&gt; parts (first system paths such as &lt;code&gt;/usr/bin&lt;/code&gt;, then prepend &lt;code&gt;/Applications/MAMP/bin&lt;/code&gt; &lt;strong&gt;after&lt;/strong&gt; that) then the systems libtool binary will be used.&lt;/li&gt;
&lt;li&gt;kimai is an open source time teacker&lt;/li&gt;
&lt;li&gt;a oneplus 3t uses more battery in power saver mode than in normal mode&lt;/li&gt;
&lt;li&gt;The new JIRA Board view can be disabled in the user profile settings&lt;/li&gt;
&lt;li&gt;When opening big files in vim (or nvim) you can use &lt;code&gt;nvim -u &amp;quot;NONE&amp;quot; ./your-file&lt;/code&gt; in order to disable syntax highlighting. This will stop vim from trying to read the whole file on first open.&lt;/li&gt;
&lt;li&gt;Vim will try to read your file line-by-line. If your have a large file that is all a single line then you are fresh out of luck. In these cases you have to pre-process the file in order to insert regular linebreaks. This can happen with tools specialized for the type of file you are dealing with (e.g. &lt;code&gt;xmllint&lt;/code&gt; or through a clever use of sed: &lt;code&gt;cat ./my-file.txt | sed -e &#39;s/(.{100})/\1\n/g&#39; &amp;gt; my-file-with-linebreaks-every-100-chars.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;When restoring the grub configuration of a system from an chroot environment the live system must boot from efi if the configuration to repair is efi. Otherwise grub will start throwing obscure errors at you.&lt;/li&gt;
&lt;li&gt;In laravel routes can also be grouped in separate files &lt;a href=&#34;https://twitter.com/adamprickett/status/1015514218572009473&#34; target=&#34;_blank&#34;&gt;https://twitter.com/adamprickett/status/1015514218572009473&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;checkinstall&lt;/code&gt; can be used in order to build a package file ( &lt;code&gt;.deb&lt;/code&gt; or &lt;code&gt;.rpm&lt;/code&gt; ) out of a compiled source code. This is useful if you don&amp;rsquo;t want to recompile on every machine (and don&amp;rsquo;t want the build dependencies on every machine)&lt;/li&gt;
&lt;li&gt;When TYPO3 references files that currently do not exist they can simply be placed in the correct place again for them to work again. However, their metadata is only refreshed after a full cache clear (in the install tool) is performed. Thus until the cache is cleared images that were missing in the past will not be scaled.&lt;/li&gt;
&lt;li&gt;You can pipe data into SSH and run a command without interaction on the other side to receive the data. This way you can effectively pipe data over the network.&lt;/li&gt;
&lt;li&gt;This is especially helpfull for full-disk backups without external media: &lt;code&gt;sudo dd if=/dev/sda bs=8M | pv | pigz | ssh jo-nas dd of=backup.img.gz&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#24</title>
      <link>https://thej6s.com/articles/2018-06-18__things-i-learned-2018-24/</link>
      <pubDate>Mon, 18 Jun 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-06-18__things-i-learned-2018-24/</guid>
      <description>&lt;p&gt;Tags: this week I learned&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Running an android system without any google apps or services installed is pretty doable actually&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The only gotcha: A lot of apps require the google maps &lt;strong&gt;framework&lt;/strong&gt; (not the app) which &lt;a href=&#34;https://wenchiching.wordpress.com/2017/11/29/how-to-fix-work-around-unavailable-shared-library-com-google-android-maps/&#34; target=&#34;_blank&#34;&gt;can be installed fairly easily&lt;/a&gt;. To add on this, copying the jar file is not even needed. Doing this you can still install apps that require the google maps framework without actually installing the framework. The xml file is a simple mapping of the service name to the jar file. Be advised though: apps will crash once they actually try to use the framework.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Virtualbox seems to have problems with keeping the clock of the virtual pc consistent - so time drift is very likely to happen. Usinig ntp on the guest does not counteract this since ntp will bail if the time difference is to big. Using &lt;code&gt;ntpd -gq&lt;/code&gt; forces ntp to get a complete new clock reading and updating the system clock (The NTP service has to be stopped for this to work)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NTP does not update your clock if it is up - it syncs your clock with an ntp server by prolonging or shortening the time of a second over a particular period of time. This way time is still linear for all other applications and does not suddenly jump from one time to another.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#23</title>
      <link>https://thej6s.com/articles/2018-06-10__things-i-learned-2018-23/</link>
      <pubDate>Sun, 10 Jun 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-06-10__things-i-learned-2018-23/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;with android oreo the storage format of wifi credentials changed from the traditional wpa_supplicant.conf to a new WifiConfigurationStore.xml.&lt;/li&gt;
&lt;li&gt;WifiConfigurationStore.xml may not be compatible between android versions&lt;/li&gt;
&lt;li&gt;Encryption of android devices is hidden behind a &amp;lsquo;require password to start device&amp;rsquo; option.&lt;/li&gt;
&lt;li&gt;LineageOs + no google play services make a phone super snappy while preserving battery life&lt;/li&gt;
&lt;li&gt;RTL SDR are DVB-TV receivers that can be used as low-cost SDRs (software defined radio) that can read the whole radio spectrum&lt;/li&gt;
&lt;li&gt;A RTL SDR can receive FM Radio&lt;/li&gt;
&lt;li&gt;A RTL SDR can receive clock updates&lt;/li&gt;
&lt;li&gt;A RTL SDR can be used to track plane using their transponder signals&lt;/li&gt;
&lt;li&gt;Cheap power bricks for laptops can emit a lot of radio noise. My cheap brick emits a lot of noise in the typical FM radio spectrum. I found that out when playing with a RTL SDR. &lt;figure&gt;&lt;img src=&#34;https://thej6s.com/assets/radio_noise.png&#34; /&gt;&lt;figcaption&gt;Continuously plugging and unplugging the power brick while tuning into an FM band&lt;/figcaption&gt;&lt;/figure&gt;&lt;/li&gt;
&lt;li&gt;IKEA Tradfri gateway uses the coap protocol. There are client that allow programming your bulbs.&lt;/li&gt;
&lt;li&gt;The coap protocol is actually &lt;a href=&#34;https://github.com/j6s/tradfri-manager&#34; target=&#34;_blank&#34;&gt;pretty easy to work with&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#22</title>
      <link>https://thej6s.com/articles/2018-06-03__things-i-learned-2018-22/</link>
      <pubDate>Sun, 03 Jun 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-06-03__things-i-learned-2018-22/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;code&gt;disown&lt;/code&gt; can be used to de-associate an application running in the background from the current shell thus not being terminated when the shell is. This is usefull when launching GUI applications from a terminal.&lt;/li&gt;
&lt;li&gt;When running chrome / -ium in a virtualbox guest using &lt;code&gt;--blacklist-accelerated-compositing&lt;/code&gt; can help with poor performance: &lt;a href=&#34;http://beshoy.girgis.us/2012/11/virtualbox-ubuntu-chrome-rendering-issue/&#34; target=&#34;_blank&#34;&gt;http://beshoy.girgis.us/2012/11/virtualbox-ubuntu-chrome-rendering-issue/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Smokers gunk in electronics is not only disgusting but can also actively errode the metal and paint inside of cases.&lt;/li&gt;
&lt;li&gt;Explaining programming to someone is actually really hard: Sometimes we forget how deep down the rabit hole we really are in this world.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#21</title>
      <link>https://thej6s.com/articles/2018-05-27__things-i-learned-2018-21/</link>
      <pubDate>Sun, 27 May 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-05-27__things-i-learned-2018-21/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;When using QT5 applications in a GTK(2) context the application &lt;a href=&#34;https://wiki.archlinux.org/index.php/Qt#Configuration_of_Qt5_apps_under_environments_other_than_KDE_Plasma&#34; target=&#34;_blank&#34;&gt;qt5ct&lt;/a&gt; can be used to adjust the QT style.&lt;/li&gt;
&lt;li&gt;When setting qt5ct to use the GTK style it can happen that digikam refuses to open. In these cases setting it to something else helps. I do not know where the roots of this problem is.&lt;/li&gt;
&lt;li&gt;The world did not end when GDPR/DSVGO was introduced&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://getkirby.com/&#34; target=&#34;_blank&#34;&gt;KirbyCMS&lt;/a&gt; 2.5.10 does not set any cookies in the users browser (unless you explicitly want to use session functionalities)&lt;/li&gt;
&lt;li&gt;The text inside of a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; list flows normally with the rest of the text on the page with the bullets being placed to the left of the normal text flow. The default list style then adds a padding-left to position the bullets in a line with the rest of the page.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lsof&lt;/code&gt; prints a list of all open files by process. &lt;code&gt;fatrace&lt;/code&gt; lists live file accessses by mount point. Together they can be used to debug why a disk is not spinning down (e.g. in a NAS)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#20</title>
      <link>https://thej6s.com/articles/2018-05-20__things-i-learned-2018-20/</link>
      <pubDate>Sun, 20 May 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-05-20__things-i-learned-2018-20/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Finding a good non-verbose privacy policy in english is very hard&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.lnx21.de/2017/01/nginx-log-files-anonymisieren/&#34; target=&#34;_blank&#34;&gt;nginx access logs can be anonymized fairly easily&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://f-droid.org/en/&#34; target=&#34;_blank&#34;&gt;f-droid&lt;/a&gt; Is a non-google app store for android that contains only open source software. Perfect for de-googling your phone.&lt;/li&gt;
&lt;li&gt;Testing software can catch programming errors that are very easy to make but catastrophical in their outcome. While some part of me knew this I had to learn it the hard way.&lt;/li&gt;
&lt;li&gt;This I have not learned this week but rediscovered: Working environments are important. Be sure to have separate environments for work and play. Yes, your laptop can be used to code and watch youtube videos. Yes, you can also code in your bed if you want to. But for the sake of your mental health: Separate your environments very carefully. Don&amp;rsquo;t mix play and work time (even your side projects should be treated as &amp;lsquo;work&amp;rsquo; in this case). And above all: Your bed should only ever be used for 2 things - and none of them involve a computer.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#19</title>
      <link>https://thej6s.com/articles/2018-05-13__things-i-learned-2018-19/</link>
      <pubDate>Sun, 13 May 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-05-13__things-i-learned-2018-19/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;When using a &lt;code&gt;rewrite&lt;/code&gt; rule inside of a &lt;code&gt;location&lt;/code&gt; block in nginx you might want to add the &lt;code&gt;break&lt;/code&gt; keyword to it: Not using it will start a full evaluation of the URL after it is rewritten. &lt;code&gt;break&lt;/code&gt; works the way you would expect: It rewrites the rule and continues inside of the block.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;radicale&lt;/code&gt; is a very simple self-hosted cal-dav and card-dav server that can be used to host your own calendars and contacts instead of pushing that data to google: &lt;a href=&#34;https://radicale.org/&#34; target=&#34;_blank&#34;&gt;https://radicale.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Go formatting methods (e.g. fmt.Printf or log.Printf) accept regular printf formatted strings. However the syntax is extended to include precission arguments. With this a string can be pad to a certain length when logging using &lt;code&gt;fmt.Printf(&amp;quot;%20s&amp;quot;, str)&lt;/code&gt;  (right-justified) and &lt;code&gt;fmt.Printf(&amp;quot;%-20s&amp;quot;, strg)&lt;/code&gt; (left-justified).&lt;/li&gt;
&lt;li&gt;For logging purposes the formatting placeholder &lt;code&gt;%v&lt;/code&gt; can be used to always output the value of the given argument (no matter the type) in a human-readable form.&lt;/li&gt;
&lt;li&gt;In go channels can be used to build worker pools. This is useful to control the concurrency of goroutines (e.g. if a single goroutine uses to many resources it can be restricted to only 4 or 8 workers: &lt;a href=&#34;https://gobyexample.com/worker-pools&#34; target=&#34;_blank&#34;&gt;https://gobyexample.com/worker-pools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;gorun is a utility to run go files directly using a shebang. However a gorun file is not a valid go file.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#18</title>
      <link>https://thej6s.com/articles/2018-05-06__things-i-learned-2018-18/</link>
      <pubDate>Sun, 06 May 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-05-06__things-i-learned-2018-18/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tailwinds clearfix cannot be applied to pseudo elements as it uses pseude elements itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In go a type matches an interface if the definitions line up. No matter if the interfaces have anything to do with the type or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I use (and love) AfterShotPro for editing of RAW photos. One free and OpenSource alternative is Darktable - which in contrast I find to be very cluttered and hard to use. However, clipping highlights are handled much more gracefully in Darktable compared to AfterShot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Neutral density filters (ND) for cameras are rated with relative numbers of darkening. A &lt;code&gt;ND2&lt;/code&gt; Filter will make everything half as bright - a &lt;code&gt;ND4&lt;/code&gt; Filter will make everything one fourth as bright - a &lt;code&gt;ND64&lt;/code&gt; Filter will reduce the brightness to 1/64th. Usually the exposure of a photo is measured in stops - which is a logarithmic (log2) scale: 1 Stops is twice as much light. Therefor the number on a filter and the stops it darkens the image by diverge. This is where being a developer and learning your powers of 2 finally pays of.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Expanding on the last point: Photographers are not as familiar with powers of 2 so manufacturers will often simplify the names: A filter that darkens the image by 10 stops should be called &lt;code&gt;ND1024&lt;/code&gt; (2^10 = 1024) but is most often referred to as &lt;code&gt;ND1000&lt;/code&gt;. Much more ridiculously 9 Stop filters are called &lt;code&gt;ND400&lt;/code&gt; (Should be &lt;code&gt;ND512&lt;/code&gt;). I have not found an explanation why it is not rounded to 500.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A single GPG Key can be used for multiple E-Mail adresses.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once a GPG Key is on a keyserver there is no way of getting it off. All you can do is revoke the key and inform the server that the key is no longer valid. This in turn requires that you still have a valid private key. If you accidentally deleted your private key then you are out of luck.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I can sign a GPG Key of someone else with my GPG Key to indicate that I trust this person and their Identity. this way it is possible to build what is called a &amp;lsquo;web of trust&amp;rsquo; of identities and keys that are trusted by peers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;bc&lt;/code&gt; is a calculator on the command line.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Things I learned: 2018#17</title>
      <link>https://thej6s.com/articles/2018-04-29__things-i-learned-2018-17/</link>
      <pubDate>Sun, 29 Apr 2018 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2018-04-29__things-i-learned-2018-17/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In go an if statement may contain a list of multiple commands - the return value of the last will be used to determine the outcome of that statement. This makes multiple return values compatible with if statements.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;if&lt;/span&gt; _, ok = &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;doSomething&lt;/span&gt;(); !ok {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// It failed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In go the following construct is actually a typecasting that tells the compiler and runtime which concrete implementation of an interface I expect: &lt;code&gt;someVariable.(*expectedType)&lt;/code&gt;. If the expected concrete implementation is compatible with the true value of the variable then it is returned as the first returned variable. The second returned variable indicates whether or not the operation was successful. In this example &lt;code&gt;token.Method&lt;/code&gt; is of the type &lt;code&gt;SigningMethod&lt;/code&gt; and &lt;code&gt;SigningMethodHMAC&lt;/code&gt; is a concrete implementation of that method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;if&lt;/span&gt; _, ok &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:=&lt;/span&gt; token.Method.(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;jwt.SigningMethodHMAC); !ok {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;nil&lt;/span&gt;, fmt.&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Unexpected signing method: %v&amp;#34;&lt;/span&gt;, token.Header[&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;alg&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Good twisted pair cables use copper for their cores. Copper is fairly expensive however. Therefor cheap cables often use an alloy containing a lot of aluminium. Aluminium is not as conductive and signal-loss will be higher when using long cables. if you are planning on running cables through walls then you are better off buying a high quality cable since replacing it will be a pain. If your want to check a cable, remove the mantle and hold a lighter to it. If the cores burn and disintegrate then it is aluminium. If the core does not burn then it is copper.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is a bug in Virtualbox where &lt;code&gt;VBoxClient --draganddrop&lt;/code&gt; will consume 100% CPU on Linux guests because it thinks that every mouse movement is a drag&amp;amp;drop event that needs to be synchronized between host and guest. This slows down machines considerably. Disabling Drag&amp;amp;Drop solves this issue.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Network bridging for PI Zero</title>
      <link>https://thej6s.com/articles/2017-10-26__network-bridging-for-pi-zero/</link>
      <pubDate>Thu, 26 Oct 2017 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2017-10-26__network-bridging-for-pi-zero/</guid>
      <description>&lt;p&gt;Tags: linux
The &lt;a href=&#34;https://www.raspberrypi.org/products/raspberry-pi-zero/&#34; target=&#34;_blank&#34;&gt;Raspberry PI Zero&lt;/a&gt;
is a wonderfull small Linux computer that takes the Raspberry Pi appeal to the next level:
The even more compact form factor allows for some serious applications where space is limited.&lt;/p&gt;
&lt;p&gt;However, the small size comes at a cost: The regular PI Zero does not have any networking
capabilities and even the &lt;a href=&#34;https://www.raspberrypi.org/products/raspberry-pi-zero-w/&#34; target=&#34;_blank&#34;&gt;PI Zero W&lt;/a&gt;
which has WiFi onboard sometimes lets the user desire a proper wired connection.&lt;/p&gt;
&lt;p&gt;This article explains, how to configure a temporary network bridge in order to share your
computers network connection to the pi. It assumes, that your workstation is running some
flavour of linux. This method has been tested with debian, but should work on all distributions.&lt;/p&gt;
&lt;p&gt;Our network will look something like the following, with our workstation sitting between our
network and the pi. You can think of the term &amp;ldquo;bridging a network&amp;rdquo; as holding together some
wires in order to get a connection. In this instance our workstation will &amp;ldquo;hold together the wires&amp;rdquo;
in order to let the pi connect to the network.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;----------         ---------------        ------
| Router |  &amp;lt;---&amp;gt;  | Workstation |  &amp;lt;---&amp;gt; | PI |
----------   LAN   ---------------   USB  ------
          (or WIFI)                  
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;setup-the-pi-enable-ssh-via-usb&#34;&gt;Setup the pi: enable SSH via USB&lt;/h2&gt;
&lt;p&gt;Setting up the PI to use the USB connection as network link is already well documented,
so I will not loose any more words on the topic. Here are a couple of links in order to
set your pi up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;English: &lt;a href=&#34;https://www.thepolyglotdeveloper.com/2016/06/connect-raspberry-pi-zero-usb-cable-ssh/&#34; target=&#34;_blank&#34;&gt;https://www.thepolyglotdeveloper.com/2016/06/connect-raspberry-pi-zero-usb-cable-ssh/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;German: &lt;a href=&#34;https://www.desgehtfei.net/?p=114&#34; target=&#34;_blank&#34;&gt;https://www.desgehtfei.net/?p=114&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In case you are having issues, try the following things recommended by the second article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure, that you have the &lt;code&gt;avahi-daemon&lt;/code&gt; installed and running on your workstation.&lt;/li&gt;
&lt;li&gt;Ensure, that &lt;code&gt;avahi-browse -alr&lt;/code&gt; is finding the SSH Service advertised by the pi.&lt;/li&gt;
&lt;li&gt;Set the IPv4 and IPv6 methods to &amp;ldquo;Link local only&amp;rdquo; (This assumes, that you are using network-manager)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;
&lt;p&gt;The following tools will be needed in order to follow the steps in this post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brctl&lt;/code&gt;: An easy CLI interface to create and manage bridged interfaces. Intallable on debian via &lt;code&gt;sudo apt-get install bridge-utils&lt;/code&gt; and on arch via &lt;code&gt;sudo pacman -S bridge-utils&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dhcpcd&lt;/code&gt;: DHCP Client that will help us finding IPs for all interfaces. Installable on debian via &lt;code&gt;sudo apt-get install dhcpcd&lt;/code&gt; and on arch via &lt;code&gt;sudo pacman -S dhcpcd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;creating-a-bridge&#34;&gt;Creating a bridge&lt;/h2&gt;
&lt;p&gt;At this point you should&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;be able to connect to the PI via SSH over USB, but not be able to access the internet from it.&lt;/li&gt;
&lt;li&gt;have installed the packages metioned above&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Note for the following passages&lt;/em&gt;: I will assume, that the network interface on the PI-end is named
&lt;code&gt;usb0&lt;/code&gt; while the network interface on the internet-end is named &lt;code&gt;eth0&lt;/code&gt;. If you are using WiFi, then
your second interface will likely be named &lt;code&gt;wlp2s0&lt;/code&gt; or &lt;code&gt;wifi0&lt;/code&gt;. If you are unsure about the names
of your interfaces, use &lt;code&gt;sudo ip link list&lt;/code&gt; or &lt;code&gt;sudo ifconfig&lt;/code&gt; in order to find them out.&lt;/p&gt;
&lt;p&gt;To start of, we need to bring our network interfaces into promiscuous mode.
&amp;ldquo;What is promiscuous mode?&amp;rdquo; I hear you ask. By default network interfaces will only pass on
packets that are intended to be received by the current machine and discard everything else
before it passes on to the CPU. In order to bridge networks our workstation must be able to
accept packets that are not intended for it, but for the PI and for machines on the other side
of the network. Promiscuous mode enables this behaviour.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Bring both interfaces into promiscuous mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ip link &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; eth0 promisc on
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ip link &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; usb0 promisc on
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we must create a new bridge that will end up connecting the two networks.
In this instance I will name that bridge interface &lt;code&gt;br0&lt;/code&gt; to conform with the network interface
naming conventions, but you are free to pick anything else.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Creating a new bridge interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo brctl addbr br0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Set the forwarding delay to 0.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# While this is not necessarry, I learned that it help with faster configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo brctl setfd br0 &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Add the two interfaces to the bridge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo brctl addif br0 eth0 usb0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Bringing the bridge interface up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ip link &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; br0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point you have successfully bridged the two networks, but it is somewhat likely that
internet connections are not available on both devices. This comes from the bridge interface
not having an IP assigned to it. While I know, that this is technically not always needed, it
has proven to resolve a lot of problems in the past.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Enable DHCP on br0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo dhcpcd br0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point you should be able to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connect to the PI from your workstation&lt;/li&gt;
&lt;li&gt;Connect to the internet from your workstation&lt;/li&gt;
&lt;li&gt;Connect to the internet from the PI&lt;/li&gt;
&lt;li&gt;Connect to other computers on the network to the PI.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basically your PI is now a full client on your network.&lt;/p&gt;
&lt;p&gt;Congratulations, you have bridged your networks&lt;/p&gt;
&lt;h2 id=&#34;cleaning-up&#34;&gt;Cleaning up&lt;/h2&gt;
&lt;p&gt;After you have done your business you have to clean up the configurations you just created:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Disable bridge interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ip link &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; br0 down
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Delete bridge interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo brctl delbr br0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Disable promiscuous mode &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ip link &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; eth0 promisc off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ip link &lt;span style=&#34;color:#0086b3&#34;&gt;set&lt;/span&gt; usb0 promisc off
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Observer design pattern</title>
      <link>https://thej6s.com/articles/2017-09-07__observer-design-pattern/</link>
      <pubDate>Thu, 07 Sep 2017 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2017-09-07__observer-design-pattern/</guid>
      <description>&lt;p&gt;German article about the observer design pattern&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Thinkpad T430 Fancontrol</title>
      <link>https://thej6s.com/articles/2017-01-18__thinkpad-t430-fan-control/</link>
      <pubDate>Wed, 18 Jan 2017 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2017-01-18__thinkpad-t430-fan-control/</guid>
      <description>&lt;p&gt;Fancontrol is a little tricky on Thinkpads and the configuration can be different from device to device. For a Thinkpad T430 I could not find any starting point in the arch wiki or the official thinkfan documentation. However, I found this article from Ivan Denkov that explains the usage of thinkfan for Thinkpad T430&amp;rsquo;s:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://ivan.reallusiondesign.com/thinkpad-t430-ubuntu-fan-control/&#34; target=&#34;_blank&#34;&gt;https://ivan.reallusiondesign.com/thinkpad-t430-ubuntu-fan-control/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This article is a reiteration of the one linked, as there have been breaking changes in thinkfan itself.&lt;/p&gt;
&lt;h2 id=&#34;1-install-lm-sensors-and-thinkfan&#34;&gt;1. Install lm-sensors and thinkfan&lt;/h2&gt;
&lt;p&gt;Both lm-sensors and thinkfan need to be installed. lm-sensors is available from the official repositories, but thinkfan is only available from the AUR.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo pacman -S lm-sensors
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yaourt thinkfan
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After installing both, lm-sensors needs to detect the hardware sensors. This can be done using the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo sensors-detect
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;2-load-kernel-modules&#34;&gt;2. Load kernel modules&lt;/h2&gt;
&lt;p&gt;The kernel modules &lt;code&gt;coretemp&lt;/code&gt; and &lt;code&gt;thinkpad_acpi&lt;/code&gt; need to be loaded for fancontrol to work. The &lt;code&gt;modprobe&lt;/code&gt; command can be used to load them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo modprobe thinkpad_acpi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo modprobe coretemp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3-find-sensors&#34;&gt;3. Find sensors&lt;/h2&gt;
&lt;p&gt;Next, the sys/device files relating to our temperature readings have to be located. The following command will find them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo find /sys/devices -type f -name &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;temp*_input&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Depending on your system configuration the output will look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sudo find /sys/devices -type f -name &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;temp*_input&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/sys/devices/platform/coretemp.0/hwmon/hwmon2/temp3_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/sys/devices/platform/coretemp.0/hwmon/hwmon2/temp1_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/sys/devices/virtual/hwmon/hwmon0/temp1_input
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;4-write-a-configuration-file&#34;&gt;4. Write a configuration file&lt;/h2&gt;
&lt;p&gt;Copy one of the default configurations from &lt;code&gt;/usr/share/doc/thinkfan/examples/&lt;/code&gt; to &lt;code&gt;/etc/thinkfan.conf&lt;/code&gt; and add the following lines to the top (replace the paths with the output of the command above):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp1_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp3_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/virtual/hwmon/hwmon0/temp1_input
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can test your configuration by executing &lt;code&gt;thinkfan -n&lt;/code&gt; manually. If the configuration in &lt;code&gt;/etc/thinkfan.conf&lt;/code&gt; is invalid it will fail to start.&lt;/p&gt;
&lt;p&gt;For reference, this is my configuration file on my personal laptop (I prefer my devices hotter, but quiet):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# The device that is used to control the fan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tp_fan /proc/acpi/ibm/fan
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# The sensors to probe.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# The hottest of these will be used to control temperature&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp1_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp3_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hwmon /sys/devices/virtual/hwmon/hwmon0/temp1_input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# Fan configuration. The first number is the fanspeed level (0-7), the second&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# number is the temperature which will trigger the next lower speed when temperatures&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# are falling and the third number will trigger the next higher speed when&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# temperatures are rising&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;0, 0,  55&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;1, 50, 60&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;2, 55, 65&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;3, 60, 70&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;4, 65, 75&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;5, 70, 80&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;7, 75, 85&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# 127 references the highest available RPM: disengaged.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# This line is pretty much saying &amp;#34;just cool the damn thing, I don&amp;#39;t care&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;127, 80, 32767&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;5-autostart-thinkfan-on-boot&#34;&gt;5. Autostart thinkfan on boot&lt;/h2&gt;
&lt;p&gt;To autostart thinkfan at boot, the necessary kernel modules have to be loaded and thinkfan itself has to be started.&lt;/p&gt;
&lt;p&gt;To load the neccessary kernel modules automatically on system start, ensure that &lt;code&gt;coretemp&lt;/code&gt; and &lt;code&gt;thinkpad_acpi&lt;/code&gt; are present in &lt;code&gt;/etc/modules&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To start thinkfan automatically use systemd:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl enable thinkfan.service
sudo systemctl start thinkfan.service
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>Software design patterns</title>
      <link>https://thej6s.com/articles/2016-10-21__software-design-patterns/</link>
      <pubDate>Fri, 21 Oct 2016 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2016-10-21__software-design-patterns/</guid>
      <description>&lt;p&gt;German article about the basics of why software design patterns are important&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>TYPO3 Websites with Fluid Templates</title>
      <link>https://thej6s.com/articles/2014-11-08__typo3-websites-with-fluid-templates/</link>
      <pubDate>Sat, 08 Nov 2014 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2014-11-08__typo3-websites-with-fluid-templates/</guid>
      <description>&lt;p&gt;German article showing how to correctly setup a TYPO3 environment using Fluid for all page templating.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What is a Hashfunction</title>
      <link>https://thej6s.com/articles/2014-07-28__what-is-a-hashfunction/</link>
      <pubDate>Mon, 28 Jul 2014 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2014-07-28__what-is-a-hashfunction/</guid>
      <description>&lt;p&gt;German article introducing the theoretical concept of a hash function and the maths behind calculating the probability of hash collisions&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Javascript: Debounce &amp; Throttle</title>
      <link>https://thej6s.com/articles/2014-04-29__js-debounce-throttle/</link>
      <pubDate>Tue, 29 Apr 2014 00:00:00 +0000</pubDate>
      <author>hello@thej6s.com (Johannes Hertenstein)</author>
      <guid>https://thej6s.com/articles/2014-04-29__js-debounce-throttle/</guid>
      <description>&lt;p&gt;German article about Debounce &amp;amp; Throttle in Javascript, complete with examples.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
