<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>traumweh</title>
    <link rel="self" type="application/atom+xml" href="https://traumweh.dev/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://traumweh.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-03-30T16:02:00+02:00</updated>
    <id>https://traumweh.dev/atom.xml</id>
    <entry xml:lang="en">
        <title>Immich&#x27;s Smart Search</title>
        <published>2025-03-30T16:02:00+02:00</published>
        <updated>2025-03-30T16:02:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/immich_smart_search/"/>
        <id>https://traumweh.dev/bytes/immich_smart_search/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/immich_smart_search/">&lt;section id=&quot;introduction&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Immich&amp;#x27;s Smart Search&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#introduction&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I’ve been using Immich for years at this point, but have never used its search feature. My images are sorted into albums, which means I don’t really need to use the search, but instead know where to find things.&lt;&#x2F;p&gt;
&lt;p&gt;But while updating Immich today, I read about new search-models being added, so I thought, why not, let’s give it a try.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;machine-learning&quot;&gt;
&lt;h2&gt;Machine Learning &lt;a class=&quot;header-link&quot; href=&quot;#machine-learning&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;But before I get into my impressions of this search-system, we’ll first need to talk about the machine learning models it uses, and what that entails.&lt;&#x2F;p&gt;
&lt;p&gt;The search uses a pre-trained machine learning model which runs locally and gets further trained locally on one’s images. It finds associations between a text query and a set of images, to determine which ones fit the most.&lt;&#x2F;p&gt;
&lt;p&gt;One can choose from a couple of pre-trained CLIP models. CLIP stands for &lt;em&gt;Contrastive Language-Image Pre-training&lt;&#x2F;em&gt; and was originally created by OpenAI in 2021. But nowadays, there exist multiple implementations of CLIP, e.g. the &lt;em&gt;OpenCLIP&lt;&#x2F;em&gt; or &lt;em&gt;Multilingual-CLIP&lt;&#x2F;em&gt; projects. They are all trained with different compute-budgets and datasets. As far as I can tell, all datasets are based on some subset of the public web. I have read through a couple of the dataset’s research papers, and all of those use some subset of &lt;em&gt;Common Crawl&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Common Crawl is a gigantic web-crawling project, which exists since 2008 and creates multiple datasets per year. As per the project’s website, “The corpus contains raw web page data, metadata extracts, and text extracts.” To create a dataset for CLIP models, this data gets filtered by images with a large enough resolution and sufficiently long alt-text. Duplicates get removed and images get further classified. This includes things like their resolution, the text’s language, or whether they are safe for work. But it also includes keyword-tagging and transformation: Let’s say the image description is: “Photograph of a pink building in Tokyo.” Then extracted tags could be: &lt;em&gt;Photograph&lt;&#x2F;em&gt;, &lt;em&gt;pink&lt;&#x2F;em&gt;, &lt;em&gt;building&lt;&#x2F;em&gt; and &lt;em&gt;Tokyo&lt;&#x2F;em&gt;. Transformations of the image and extracted tags could then also include: &lt;em&gt;realistic image&lt;&#x2F;em&gt;, &lt;em&gt;aesthetic image&lt;&#x2F;em&gt;, &lt;em&gt;architecture&lt;&#x2F;em&gt; and &lt;em&gt;Japan&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;These associations can then be used to train a CLIP model which learns how much an image can be associated with a given text query. This score can then be used to sort a list of images by association to the query.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;problem&quot;&gt;
&lt;h2&gt;My Problem With This &lt;a class=&quot;header-link&quot; href=&quot;#problem&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a really great application for machine learning, because it is very difficult to program classical algorithms for this. But I have one big problem with this: These datasets rely on publicly available data on the open web, but they do not take into account the data’s licenses. Not everything that is publicly available, is also public domain or under an open license.&lt;&#x2F;p&gt;
&lt;p&gt;I heavily oppose this methodology when it comes to Large Language Models (LLMs) and Generative AI (GenAI), because they &lt;del&gt;create&lt;&#x2F;del&gt; hallucinate ‘new’ things directly from the stolen work of others, require enormous amounts of energy to train and run, and steal the jobs of many while actually doing a worse job.&lt;&#x2F;p&gt;
&lt;p&gt;But for this type of algorithm (i.e. image classification), I am split. On the one hand, yes, peoples works are used without asking for permission, but on the other hand, the data isn’t used to create anything new, and running many of these models require only very small amounts of energy. And it doesn’t steal anyone’s job either. Quite the opposite, it actually makes one’s life a lot easier by not needing to manually tag one’s entire collection of thousands of photographs and hundreds of videos.&lt;&#x2F;p&gt;
&lt;p&gt;And if we ignore OpenAI and Google, most alternative CLIP models reuse existing web-crawling databases, instead of constantly re-crawling every single webpage there is. Common Crawl actually does respect one’s &lt;code&gt;robots.txt&lt;&#x2F;code&gt;, both the &lt;code&gt;Disallow&lt;&#x2F;code&gt; and the &lt;code&gt;Crawl-delay&lt;&#x2F;code&gt; parameters.&lt;&#x2F;p&gt;
&lt;p&gt;In the end, I think I have decided for myself, that I am okay with the crawling by Common Crawl as well as with models built on it, which do not try and hallucinate something new, but actually try and make mundane tasks such as image-tagging more accessible and easy.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;search-results&quot;&gt;
&lt;h2&gt;Search Results &lt;a class=&quot;header-link&quot; href=&quot;#search-results&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Anyway, let’s talk about my actual experience with using the so-called &lt;em&gt;Smart Search&lt;&#x2F;em&gt; feature of Immich. I used the model &lt;code&gt;ViT-B-32__laion2b-s34b-b79k&lt;&#x2F;code&gt;; an OpenCLIP model using the English language subset of the &lt;code&gt;laion2b&lt;&#x2F;code&gt; dataset, which contains 2.3 billion samples from Common Crawl, although I could not find out, which snapshot of Common Crawl was used.&lt;&#x2F;p&gt;
&lt;p&gt;The system runs a decade old Intel i7-4790 CPU with 24 GB of DDR3 RAM and no acceleration besides the CPU’s integrated graphics.&lt;&#x2F;p&gt;
&lt;p&gt;My Immich instance contains many thousands of photographs from family, friends and personal events and trips. I did specifically use queries which I thought should have some chance of finding something. I won’t include all queries I tried (for privacy reasons) and I also did not follow any scientific methodology. This is just about me wanting to try out a feature and see if I’d deem it to &lt;em&gt;work well&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I started with single word queries such as &lt;em&gt;red&lt;&#x2F;em&gt;, &lt;em&gt;cat&lt;&#x2F;em&gt;, &lt;em&gt;hat&lt;&#x2F;em&gt;, &lt;em&gt;mountain&lt;&#x2F;em&gt;, &lt;em&gt;cliff&lt;&#x2F;em&gt; or &lt;em&gt;railing&lt;&#x2F;em&gt;. As long as I had enough images which could be associated with these words, the Smart Search feature was able to find them, without pretty much any false positives.&lt;&#x2F;p&gt;
&lt;p&gt;After I couldn’t think of any more single words to try, I moved on to more abstract concepts. These included things like a &lt;em&gt;birthday&lt;&#x2F;em&gt;, &lt;em&gt;school trip&lt;&#x2F;em&gt;, &lt;em&gt;train ride&lt;&#x2F;em&gt;, &lt;em&gt;sleepover&lt;&#x2F;em&gt; or &lt;em&gt;animal park&lt;&#x2F;em&gt;. And once again, the first couple dozen or so images fit the criteria exactly. I do have photographs of a few childhood birthdays, sleepovers and school trips from different years in Immich and the search results were spanning across those, able to classify young people of varying age as school students.&lt;&#x2F;p&gt;
&lt;p&gt;Satisfied, I decided to try some more complex queries. Sentences consisting of combinations of different criteria, to create the context of a specific type of event or trip. I was pretty surprised when it could successfully find photographs from a &lt;em&gt;train ride on an old steam train&lt;&#x2F;em&gt;, or distinguish between a &lt;em&gt;children’s birthday inside&lt;&#x2F;em&gt; and one &lt;em&gt;outside&lt;&#x2F;em&gt; or &lt;em&gt;in the summer&lt;&#x2F;em&gt;. It was also able to provide me with photographs showing a &lt;em&gt;field in front of a forest on a cloudy day&lt;&#x2F;em&gt; or a &lt;em&gt;ruin of a concrete building in the forest&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Overall I am really impressed by this. I wouldn’t be able to tag this number of photographs and videos at a level of detail required to achieve such depth of query specificity. I don’t know how much I will use this in the future, but I am nonetheless happy that it is possible, completely local using a decade old CPU.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Don&#x27;t use Freenom</title>
        <published>2025-02-27T16:56:00+01:00</published>
        <updated>2025-02-27T16:56:00+01:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/freenom/"/>
        <id>https://traumweh.dev/bytes/freenom/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/freenom/">&lt;section id=&quot;introduction&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Don&amp;#x27;t use Freenom&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#introduction&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;After trying for over two years, to get my Freenom account deleted by making a complaint under the GDPR (Regulation (EU) 2016&#x2F;679), said complaint is not going to be pursued further, because it only concerns me (no relevance for the public) and the effort would be too high to find out whether there is any legal basis at all that obliges the company to delete my account.&lt;&#x2F;p&gt;
&lt;p&gt;I’m talking about the Dutch company &lt;em&gt;Freenom&lt;&#x2F;em&gt;. A domain registrar that is primarily known for lending out domains of selected domain extensions free of charge. The company is also known for taking these domains away from users and selling them without notice. And last but not least, Freenom ignores any data protection concerns. The web interface does not give users an option to delete one’s account, and neither do their help pages mention account deletion at all. There is a support form, but let’s put it this way: I submitted my request for deletion in accordance with Article 17 GDPR on December 7, 2022 (and attached further information over time), but never received a response from Freenom. Not that the support is a sham, and doesn’t really exist. I did have a previously received a fairly unfriendly response to another service-related support request, which did not offer any support whatsoever, but was at least an answer.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;authorities&quot;&gt;
&lt;h2&gt;Involving the Data Protection Authorities &lt;a class=&quot;header-link&quot; href=&quot;#authorities&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So, after a period of almost three months, I first contacted Hamburg’s Data Protection Officer, and then, in September 2023, the Dutch Data Protection Authority, the Autoriteit Persoongegevens (herinafter referred to as AP, the AP or the authority). After I received a reply about six more months later stating that the authority had too much to do, and had to send back an attached form, confirming that the problem had not been magically resolved, nothing happened for another year. Until a few days ago.&lt;&#x2F;p&gt;
&lt;p&gt;I received a letter in which the AP summarized the following: They looked at my complaint and reviewed the legal situation to determine what would be the minimum they needed to do. The AP came to the conclusion that they would send a letter to Freenom advising them of their obligations. That’s it. The AP will do nothing more. They justify this as follows:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;De AP kan bij uw klacht onvoldoende efficiënt en effectief optreden&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[The AP cannot act effiently and effectively enough in the case of your complaint.]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Wow, you said that really well! Here, have a gold star in the class log. But why can’t the AP do that?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;De AP zal namelijk verder onderzoek moeten doen naar de door u gestelde overtredingen door bijvoorbeeld een onderzoek ter plaatse en&#x2F;of het opvragen van informatie.&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[The AP needs to review your alleged infringements in more detail, e.g. through investigations on site and&#x2F;or by gathering information.]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Oh, right. Would be totally impractical if an authority would need to review a complaint by investigating it in order to review a complaint. But luckily they’ve got another argument!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;De AP ziet geen breder maatschappelijk belang&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[The AP does not see any broader social significance]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The authority always checks, whether an infringement had affected or could still affect many people, which would depend not least on the specific focus of the authority.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;De focus van de AP voor 2025 is algoritmes &amp;amp; AI (kunstmatige intelligentie), big tech, vrijheid &amp;amp; veiligheid, datahandel en de digitale overheid.&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[The focus of the AP in 2025 is algorithmes &amp;amp; AI (artificial intelligence), big tech, freedom &amp;amp; security, data trading and digital government.]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I would be so bold as to put this complaint in the “freedom” category. Meaning the argument must be based largely on social relevance, right?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;Uw klacht ziet alleen toe op u. Het aantal betrokkenen dat door uw situatie kan worden geraakt is dus beperkt.&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[Your complaint concerns only you. The number of people who could be affected by your situation is therefore limited.]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Oh, it only concerns me? &lt;em&gt;Checks notes.&lt;&#x2F;em&gt; Oh, no, wait a minute. A quick internet search shows that apparently no one on this planet has ever managed to delete their Freenom account, because (as I also described in my complaint) there is no form for this on the part of Freenom, and the support team skillfully ignores any and all GDPR requests.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;nowwhat&quot;&gt;
&lt;h2&gt;Now what? &lt;a class=&quot;header-link&quot; href=&quot;#nowwhat&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;De AP legt geen maatregel op aan de organisatie waarover uw klacht gaat. […] Uw klacht is altijd waardevol.&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[The AP does not impose any measure on the organization about which your complaint is made. […] Your complaint is always valuable.]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I’m overjoyed! Now back to eating my hat…&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span lang=&quot;nl&quot;&gt;[…] maar uw klacht helpt de AP evengoed persoonsgegevens in Nederland te beschermen. Als de AP bijvoorbeeld merkt dat een hoog aantal klachten over dezelfde organisatie gaat, dan kunnen we alsnog een verder onderzoek instellen. Verder kan uw klacht de AP bijvoorbeeld helpen bij een ander onderzoek dat we uitvoeren. Ook helpt de informatie de AP om onderzoeks- en beleidsonderwerpen te bepalen en om onze website te verbeteren.&lt;&#x2F;span&gt;&lt;br &#x2F;&gt;
[[…] but your complaint helps the AP to protect personal data in the Netherlands. For example, if the AP notices that a high number of complaints are about the same organization, we may still investigate further. Furthermore, your complaint may help the AP in another investigation we are conducting. The information also helps the AP to determine research and policy topics and to improve our website.]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;While the AP is absolutely right about this, this letter however also hightlights some of the major problems with the GDPR. The GDPR is completely inaccessible to the majority of people. It already requires a disproportionate amount of knowledge to make a request to a company under Article 17 of the GDPR, or money for a lawyer. As if anyone would be as foolish as me to voluntarily &lt;em&gt;escalate&lt;&#x2F;em&gt; this into a complaint and send it to the relevant authority in case the company does nothing. &lt;em&gt;And to do this in the Dutch language.&lt;&#x2F;em&gt; Only to find out that these authorities are completely overwhelmed and that every further request being submitted makes it worse, so they try to talk their way out of as many complaints as possible with arguments about efficiency and relevancy, in the hopes of being able to at least follow up on the more significant cases.&lt;&#x2F;p&gt;
&lt;p&gt;The AP gives me six weeks from dispatch-date of its letter to lodge an appeal against the decision using a form. But I don’t know yet whether I am willing to make that effort. Otherwise, I &lt;del&gt;dream&lt;&#x2F;del&gt; think my only chance of getting this account adeleted is if there are actually other people to file such a complaint.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Nighttime Piano</title>
        <published>2024-11-25T02:42:00+01:00</published>
        <updated>2024-11-25T02:42:00+01:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/nighttime-piano/"/>
        <id>https://traumweh.dev/bytes/nighttime-piano/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/nighttime-piano/">&lt;section id=&quot;intro&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Nighttime Piano&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#intro&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Every once in a while I need to deal with my thoughts and emotions. And my piano sometimes helps me with that. I haven’t done this in a very long time. So I decided to quickly move around some things in my room, and bring my e-piano over from the other room to make some music.&lt;&#x2F;p&gt;
&lt;p&gt;I learned to play the piano from a very young age and, especially in my teenage-years, used to play piano and guitar basically daily for many years. A little over ten years ago I also started writing my own songs, some only for piano, some also for guitar, and some for my small, broken-up band. Most of these songs I haven’t played in over five, some even in ten years. And tonight I did play some of them again from memory, as well as something new.&lt;&#x2F;p&gt;
&lt;p&gt;I haven’t aimed at perfect recordings at all, I simply connected the piano to my audio interface and pressed record. In total, I recorded nearly one hour of audio (and silence). Below are some of the things I played, for you to listen to and download. I provide the tracks as &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-nc-sa&#x2F;4.0&#x2F;&quot;&gt;CC BY-NC-SA 4.0&lt;&#x2F;a&gt;, which means you can adapt it (although adaptions need to follow the same terms) and use it for your own projects as long as you are giving me credit, and aren’t using it commercially (i.e. primarily directed towards commercial advantage or monetary compensation). If (for whatever reason and against all odds) that license doesn’t work for you, then contact me, and I’m sure we’ll figure things out.&lt;&#x2F;p&gt;
&lt;p&gt;But now, I hope you enjoy this small track list. Be kind to yourself. And pause for a moment.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;dead-names&quot;&gt;
&lt;h2&gt;dead names &lt;a class=&quot;header-link&quot; href=&quot;#dead-names&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first thing I played this night was a song I wrote for someone ruffly nine years ago. It is one of the few songs I do still play regularly (as in, whenever I do play piano), but even so it still was a bumpy ride. The song used to have a different name, but I do not want it to have that name anymore. So let’s just call it &lt;em&gt;dead names&lt;&#x2F;em&gt;. Fitting, isn’t it?&lt;&#x2F;p&gt;
&lt;p&gt;You can download it as an &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;dead-names.mp3&quot;&gt;MP3&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;dead-names.wav&quot;&gt;WAV&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;dead-names.flac&quot;&gt;FLAC&lt;&#x2F;a&gt;. Or you can listen to it below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;audio controls src=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;dead-names.mp3&quot;&gt;&lt;&#x2F;audio&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;untitled-uplifting-draft&quot;&gt;
&lt;h2&gt;untitled uplifting draft &lt;a class=&quot;header-link&quot; href=&quot;#untitled-uplifting-draft&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This second little something is a melody and chord-progression I had stuck in my head now for a couple of years, never knowing what to do with it or how to continue it. Maybe one day I will. But for know, it has its place here, as the &lt;em&gt;untitled uplifting draft&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can download it as an &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;untitled-uplifting-draft.mp3&quot;&gt;MP3&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;untitled-uplifting-draft.wav&quot;&gt;WAV&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;untitled-uplifting-draft.flac&quot;&gt;FLAC&lt;&#x2F;a&gt;. Or you can listen to it below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;audio controls src=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;untitled-uplifting-draft.mp3&quot;&gt;&lt;&#x2F;audio&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;lian&quot;&gt;
&lt;h2&gt;lian &lt;a class=&quot;header-link&quot; href=&quot;#lian&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Lian&lt;&#x2F;em&gt; was the name of one of my ex-bandmates. They were a really good friend of mine, but we sadly lost touch. But this song, as well as some Polaroid pictures, always remind me of them and make me miss the times together on stage and cuddled up on my couch. I never play it quite the same, and you might be able to hear, that it made be get lost in thoughts.&lt;&#x2F;p&gt;
&lt;p&gt;You can download it as an &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;lian.mp3&quot;&gt;MP3&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;lian.wav&quot;&gt;WAV&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;lian.flac&quot;&gt;FLAC&lt;&#x2F;a&gt;. Or you can listen to it below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;audio controls src=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;lian.mp3&quot;&gt;&lt;&#x2F;audio&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;friendship&quot;&gt;
&lt;h2&gt;friendship &lt;a class=&quot;header-link&quot; href=&quot;#friendship&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes I liked to try out different musical functions and patterns. Things like non-typical measures, modulation and whatnot. I’m not gonna spoil what I did in this one, but if I remember correctly, then I didn’t use these functions on purpose, but instead improvised them and refined the track from there. I never gave it a name, but think &lt;em&gt;friendship&lt;&#x2F;em&gt; would fit.&lt;&#x2F;p&gt;
&lt;p&gt;You can download it as an &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;friendship.mp3&quot;&gt;MP3&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;friendship.wav&quot;&gt;WAV&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;friendship.flac&quot;&gt;FLAC&lt;&#x2F;a&gt;. Or you can listen to it below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;audio controls src=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;friendship.mp3&quot;&gt;&lt;&#x2F;audio&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;remedy&quot;&gt;
&lt;h2&gt;remedy &lt;a class=&quot;header-link&quot; href=&quot;#remedy&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This one did change name a couple of times because I was never quite happy. At some point, the title had something to do with socks. Don’t ask, there was a reason, alright? But for the longest part now I called it &lt;em&gt;remedy&lt;&#x2F;em&gt;. I dunno why, but I do think it fits, simple as it is.&lt;&#x2F;p&gt;
&lt;p&gt;You can download it as an &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;remedy.mp3&quot;&gt;MP3&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;remedy.wav&quot;&gt;WAV&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;remedy.flac&quot;&gt;FLAC&lt;&#x2F;a&gt;. Or you can listen to it below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;audio controls src=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;remedy.mp3&quot;&gt;&lt;&#x2F;audio&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;penance&quot;&gt;
&lt;h2&gt;penance &lt;a class=&quot;header-link&quot; href=&quot;#penance&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Even though I haven’t played in a while, and especially haven’t written anything new in an even longer while, this one was improvised one the spot while recording it, so please excuse me missing some of the keys. I think the title, &lt;em&gt;penance&lt;&#x2F;em&gt;, suits it quite well. But why I am calling it &lt;em&gt;penance&lt;&#x2F;em&gt; I will keep to myself.&lt;&#x2F;p&gt;
&lt;p&gt;You can download it as an &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;penance.mp3&quot;&gt;MP3&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;penance.wav&quot;&gt;WAV&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;penance.flac&quot;&gt;FLAC&lt;&#x2F;a&gt;. Or you can listen to it below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;audio controls src=&quot;&#x2F;download&#x2F;nighttime-piano&#x2F;penance.mp3&quot;&gt;&lt;&#x2F;audio&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Vegan Börek</title>
        <published>2024-10-06T10:41:18+02:00</published>
        <updated>2024-10-06T10:41:18+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/vegan_börek/"/>
        <id>https://traumweh.dev/bytes/vegan_börek/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/vegan_börek/">&lt;p&gt;&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Vegan Börek&lt;&#x2F;span&gt;&lt;&#x2F;h1&gt;

&lt;section id=&quot;ingredients&quot;&gt;
&lt;h2&gt;Ingredients &lt;a class=&quot;header-link&quot; href=&quot;#ingredients&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3&gt;Spinach Filling (for ca. 20 pieces)&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;1&#x2F;2 onion, cut into cubes&lt;&#x2F;li&gt;
&lt;li&gt;1–2 cloves of garlic, pressed&lt;&#x2F;li&gt;
&lt;li&gt;150 g baby spinach, fresh&#x2F;frozen&lt;&#x2F;li&gt;
&lt;li&gt;150 g vegan Feta&lt;&#x2F;li&gt;
&lt;li&gt;1–2 tbsp. cashews&lt;&#x2F;li&gt;
&lt;li&gt;Salt and pepper as desired&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Tomato Filling (for ca. 30 pieces)&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;75 g cashews (or vegan Feta)&lt;&#x2F;li&gt;
&lt;li&gt;2 tbsp. sunflower seeds&lt;&#x2F;li&gt;
&lt;li&gt;120 ml tomato puree out of fresh and dried tomatoes&lt;&#x2F;li&gt;
&lt;li&gt;1–2 cloves of garlic, pressed&lt;&#x2F;li&gt;
&lt;li&gt;Salt and pepper as desired&lt;&#x2F;li&gt;
&lt;li&gt;Herbs, e.g. oregano, marjoram, basil, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Yufka flatdough (ca. 20 pieces)&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;280 g (250 g) wheat flour, type 405&lt;&#x2F;li&gt;
&lt;li&gt;50 g (80 g) Cornstarch&lt;&#x2F;li&gt;
&lt;li&gt;2–3 pinches (1 g) of salt&lt;&#x2F;li&gt;
&lt;li&gt;200 ml water&lt;&#x2F;li&gt;
&lt;li&gt;2 tbsp. neutral oil&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Additionally, to brush onto the dough:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;50–100 ml plant-based milk&lt;&#x2F;li&gt;
&lt;li&gt;2 EL neutral oil&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;&#x2F;p&gt;
&lt;section id=&quot;preparation&quot;&gt;
&lt;h2&gt;Preparation &lt;a class=&quot;header-link&quot; href=&quot;#preparation&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3&gt;Spinach Filling&lt;&#x2F;h3&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;&lt;strong&gt;If using frozen spinach:&lt;&#x2F;strong&gt; defrost the spinach (e.g. in a water bath) and squeeze out; instead of fring, as described below, simply add it before step 3&lt;&#x2F;li&gt;
&lt;li&gt;Heat up oil in a pan and fry the onion cubes for 1 to 2 minutes&lt;&#x2F;li&gt;
&lt;li&gt;Add garlic and spinach (if fresh), fry for another 1 to 2 minutes&lt;&#x2F;li&gt;
&lt;li&gt;Squeeze out the remaining water&lt;&#x2F;li&gt;
&lt;li&gt;Chop up the mixture a bit&lt;&#x2F;li&gt;
&lt;li&gt;Crumble the vegan Feta into the mixture&lt;&#x2F;li&gt;
&lt;li&gt;Add salt and pepper as desired&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Tomato Filling&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Douse cashews and sunflower seeds with cooking water&lt;&#x2F;li&gt;
&lt;li&gt;Soak for ca. 15 minutes; drain and rinse afterwards&lt;&#x2F;li&gt;
&lt;li&gt;Add remaining ingredients and process into a paste (e.g. using a kitchen machine)&lt;&#x2F;li&gt;
&lt;li&gt;Add salt, pepper and herbs as desired&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Yufka Flatdough&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Mix flour, starch and salt in a bowl&lt;&#x2F;li&gt;
&lt;li&gt;Add half the water, mix slowly&lt;&#x2F;li&gt;
&lt;li&gt;Add remaining water and oil&lt;&#x2F;li&gt;
&lt;li&gt;Kneat into a soft dough&lt;&#x2F;li&gt;
&lt;li&gt;Divide dough into 8 to 10 beads and wrap in cling film (or leave in bowls under towels)&lt;&#x2F;li&gt;
&lt;li&gt;Rest for 1 hour&lt;&#x2F;li&gt;
&lt;li&gt;Spread some flour on your work surface&lt;&#x2F;li&gt;
&lt;li&gt;Only let one piece of dough at the air at a time to prevent dry out&lt;&#x2F;li&gt;
&lt;li&gt;Roll dough into thin flat pieces, large enough for roughly two pieces of Börek&lt;&#x2F;li&gt;
&lt;li&gt;Cut flatdough into two or three pieces of the desired size&lt;&#x2F;li&gt;
&lt;li&gt;Brush the milk and oil mixture onto the dough&lt;&#x2F;li&gt;
&lt;li&gt;Add desired filling two one end&lt;&#x2F;li&gt;
&lt;li&gt;Roll up the dough from the filled side, ensuring that the endings are not left open but folded inwards&lt;&#x2F;li&gt;
&lt;li&gt;Brush the milk and oil mixture onto the outside as well&lt;&#x2F;li&gt;
&lt;li&gt;Add some poppy and sesame as garnish&lt;&#x2F;li&gt;
&lt;li&gt;Bake for 15 to 20 minutes at 180 ˚C (fan oven) in a preheated oven&lt;&#x2F;li&gt;
&lt;li&gt;Cool down for a couple of minutes (the filling will be very hot!)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bootstrapping OpenSSH: Remote Disk Decryption</title>
        <published>2024-08-09T16:12:00+02:00</published>
        <updated>2024-08-09T16:12:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/ssh_decrypt/"/>
        <id>https://traumweh.dev/bytes/ssh_decrypt/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/ssh_decrypt/">&lt;section id=&quot;problem&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Bootstrapping OpenSSH: Remote Disk Decryption&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#problem&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This is part two (of two) of my journey to remote unlocking encrypted (LUKS) root partitions using SSH during early boot. Here we’ll configure dracut to include the OpenSSH daemon in early boot to type in the passphrase remotely. In the first part, I outlined the steps required to configure a system to use dracut instead of mkinitcpio. If you want to read about that, you can find the first part here: &lt;a href=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;bytes&#x2F;dracut&#x2F;&quot;&gt;Goodbye mkinitcpio, hello dracut!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you just want the details of what files need to be modified or created, which packages to be installed and stuff, you can skip to &lt;a href=&quot;#prerequisites&quot;&gt;this section here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;what-and-why&quot;&gt;
&lt;h2&gt;What and why? &lt;a class=&quot;header-link&quot; href=&quot;#what-and-why&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Everyone should be using full disk encryption (FDE) at this point. If you aren’t, then you really should be! Otherwise, anyone with physical access to your computer can access all your files. And no, user passwords on linux don’t really mean anything if you have physical system access. Take a look at the concept of &lt;code&gt;chroot&lt;&#x2F;code&gt;-ing and you’ll understand why. But FDE also comes with its own difficulties. Assuming one is using LUKS for FDE, there are many options how to protect the disk: passphrases, keyfiles, FIDO2 tokens, smartcards, etc. And all either require physical access at boot time, or decrese the FDE-security.&lt;&#x2F;p&gt;
&lt;p&gt;Here, we’ll simply look at setups using passphrases which a system prompts for at boot time. Depending on the partition, either at early boot, or late boot. Essentially, if the disk is required to access the root filesystem and build up the actual userspace, then it gets prompted for at early boot. Otherwise at late boot. If your FDE disk or partition contains the root partition, then it will be early boot. And that is what this guide assumes, because in this case, the boot process is actively blocked by the FDE prompt and won’t continue without supplying a valid passphrase. But especially for servers, it is not always possible to have physical access to the system during (early) boot. And therefore, a solution would be to start an SSH daemon during early boot.&lt;&#x2F;p&gt;
&lt;p&gt;Two fairly wide-spread SSH daemons, &lt;a href=&quot;https:&#x2F;&#x2F;matt.ucc.asn.au&#x2F;dropbear&#x2F;dropbear.html&quot;&gt;Dropbear&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;tinyssh.org&#x2F;&quot;&gt;tinyssh&lt;&#x2F;a&gt; are commonly used in scenarios where disk space is limited. Because boot partitions and initramfs image sizes are often limited, many people fall back to one of these solutions and simply include them as a module in initramfs. But Dropbear is known for implementing a very old and insecure SSH version without support for modern key algorithms, including FIDO2-based ones. And tinyssh, while more modern, is less known, a lot younger and way less tried-and-tested than OpenSSH. And considering that disk space is a lot less of a problem nowadays, even for embedded systems, adding a few dozens of extra megabytes to the initramfs image doesn’t really make the difference. So one might as well include a full OpenSSH daemon which supports modern, tried and tested key algorithms.&lt;&#x2F;p&gt;
&lt;p&gt;So with that out of the way, let’s look at what steps are actually required.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;prerequisites&quot;&gt;
&lt;h2&gt;Prerequisites &lt;a class=&quot;header-link&quot; href=&quot;#prerequisites&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This configuration assumes your system is using the dracut initramfs builder and a root partition with FDE setup.&lt;&#x2F;p&gt;
&lt;p&gt;Before we can start up an SSH daemon at early boot, we’ll need to ensure that a networking (IP) stack is up and running. This include setting up a network interface, too. We’ll be using &lt;code&gt;systemd-networkd&lt;&#x2F;code&gt;, but &lt;code&gt;legacy-network&lt;&#x2F;code&gt; and other &lt;code&gt;network&lt;&#x2F;code&gt;-modules for dracut should work too. For starters, we’ll need to create a network configuration for systemd-networkd. The following configuration assumes you are using an ethernet interface that starts with &lt;code&gt;e&lt;&#x2F;code&gt;, like &lt;code&gt;eth0&lt;&#x2F;code&gt; or &lt;code&gt;enp1s0&lt;&#x2F;code&gt;. If you use a wireless network interface, you need to change this to respect that. We’ll store this config in &lt;code&gt;&#x2F;etc&#x2F;systemd&#x2F;network&#x2F;20-wired.network&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;[Match]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;e&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;*&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;[Network]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-support z-constant z-genconfig&quot;&gt;DHCP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;ipv4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we’ll ensure that dracut actually sets the networking stack up at early boot. To do that, we simply create a file like &lt;code&gt;&#x2F;etc&#x2F;dracut.d&#x2F;sshd.conf&lt;&#x2F;code&gt; with the following contents to start &lt;code&gt;systemd-networkd&lt;&#x2F;code&gt; at early boot and include the network configuration from above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;conf&quot; class=&quot;language-conf z-code&quot;&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;install_items&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-genconfig&quot;&gt;&amp;quot; &#x2F;etc&#x2F;systemd&#x2F;network&#x2F;20-wired.network &amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;add_dracutmodules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-genconfig&quot;&gt;&amp;quot; systemd-networkd &amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;setting-up-sshd&quot;&gt;
&lt;h2&gt;Setting up SSHD &lt;a class=&quot;header-link&quot; href=&quot;#setting-up-sshd&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Next, we’ll need a dracut module that includes the OpenSSH daemon in the initramfs and loads it at early boot. Luckily, a person named Georg Sauthoff did the work and made &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gsauthof&#x2F;dracut-sshd&quot;&gt;a publicly available dracut-sshd module on GitHub&lt;&#x2F;a&gt;. It is very simple and easy to configure. But first, we’ll start by cloning the repository and copying the module directory &lt;code&gt;46sshd&lt;&#x2F;code&gt; to &lt;code&gt;&#x2F;usr&#x2F;lib&#x2F;dracut&#x2F;modules.d&#x2F;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; also available as a copr repository&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; clone https:&#x2F;&#x2F;github.com&#x2F;gsauthof&#x2F;dracut-sshd&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; dracut-sshd&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cp&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;ri&lt;&#x2F;span&gt; 46sshd &#x2F;usr&#x2F;lib&#x2F;dracut&#x2F;modules.d&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This module reuses the host’s sshd private keys and includes them in the initramfs image. Depending on your threat model, this might be a problem. After all, if one’s root partition is encrypted, one might not want its secrets to be stored in the boot image unencrypted. If one doesn’t want their keys at &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;ssh_host_*_key{,.pub}&lt;&#x2F;code&gt; to be used, simply add new keys at &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;dracut_ssh_host_*_key{,.pub}&lt;&#x2F;code&gt;. If these exist, the module will use them instead. But be aware: you might want to consider creating a separate SSH config host entry for the early-boot daemon, or you’ll be greated by an host-key-missmatch error everytime you connect.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly for the authorized keys, the modules looks at different locations; in order of precedence:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;root&#x2F;.ssh&#x2F;dracut_authorized_keys&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;etc&#x2F;dracut-sshd&#x2F;authorized_keys&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;root&#x2F;.ssh&#x2F;authorized_keys&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Remember to adjust the permissions of all these files accordingly, i.e. only read- and writeable by root:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; chmod 0600 &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;FILES..&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By default, the early-boot SSH daemon listens on port 22. If you want to change this, create a file &lt;code&gt;&#x2F;etc&#x2F;sysconfig&#x2F;dracut-sshd&lt;&#x2F;code&gt; that defines &lt;code&gt;SSHD_OPTS&lt;&#x2F;code&gt; with the option &lt;code&gt;-p 22&lt;&#x2F;code&gt; (and possible other sshd-options as desired). And that should be it. All that’s left now, is to rebuild the initramfs image using dracut (and possible other arguments depending on your setup):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; dracut&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;v&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;OTHER_ARGS..&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And if everything went well, on the next boot, while the passphrase prompt is displayed on screen, an OpenSSH daemon should be running and listening for connections. Simply connect to it, and it should give you the instruction to run &lt;code&gt;systemd-tty-ask-password-agent&lt;&#x2F;code&gt; and supply it with your respective encryption passphrase. You can also use &lt;code&gt;systemd-tty-ask-password-agent --list&lt;&#x2F;code&gt; to display a list of all pending prompts.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Goodbye mkinitcpio, hello dracut!</title>
        <published>2024-08-09T14:55:00+02:00</published>
        <updated>2024-08-09T14:55:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/dracut/"/>
        <id>https://traumweh.dev/bytes/dracut/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/dracut/">&lt;section id=&quot;problem&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Goodbye mkinitcpio, hello dracut!&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#problem&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This is part one (of two) of my journey to remote unlocking encrypted (LUKS) root partitions using SSH during early boot. To achieve this, as a prerequisite, I needed to switch from mkinitcpio to dracut for building the initramfs on one of my systems. So I thought, I might share the few steps I needed to take, to successfully switch over to dracut on my archlinux system.&lt;&#x2F;p&gt;
&lt;p&gt;If you just want the details of what files need to be modified or created, which packages to be installed and stuff, you can skip to &lt;a href=&quot;#first-build&quot;&gt;this section here&lt;&#x2F;a&gt;. You can find the second part here: &lt;a href=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;bytes&#x2F;ssh_decrypt&#x2F;&quot;&gt;Bootstrapping OpenSSH: Remote Disk Decryption&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;initramfs&quot;&gt;
&lt;h2&gt;What an initramfs? &lt;a class=&quot;header-link&quot; href=&quot;#initramfs&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you already know, you can of course simply skip this section. Or read it and correct me where I am wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Essentially, the initramfs is a RAM disk, i.e. filesystem stored in memory, which is used to initialize the system to a point, where it can access the root filesystem. To achieve this, the kernel, which gets started by the bootloader, is responsible of unpacking a contained initramfs image and bootstrap the system. This initramfs image contains all the tooling required to e.g. unlock the filesystem in case of full disk encryption (FDE), load required drivers to e.g. read keyboard events, and load other components as configured (e.g. the networking&#x2F;IP stack).&lt;&#x2F;p&gt;
&lt;p&gt;This RAM disk is stored as a binary file at a place where your bootloader can find it. This depends on your boot method and bootloader. Using UEFI and Grub as an example, this file is simply located in the root of your EFI boot partition, which usually gets mounted as &lt;code&gt;&#x2F;boot&lt;&#x2F;code&gt;. The bootloader is then told, which image(s) to load at boot time.&lt;&#x2F;p&gt;
&lt;p&gt;Tools like dracut or mkinitcpio can be used to configure the initramfs image. They essentially create the filesystem, add all the files to it, add some metadata, and pack them into an image file. On linux, the command &lt;code&gt;lsinitrd&lt;&#x2F;code&gt; can be used, to inspect such an image. It displays information about the early CPIO (&lt;em&gt;copy in, copy out&lt;&#x2F;em&gt;) files, the version (e.g. dracut), modules to load and the entire initramfs filetree.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;mkinitcpio-vs-dracut&quot;&gt;
&lt;h2&gt;Why dracut? &lt;a class=&quot;header-link&quot; href=&quot;#mkinitcpio-vs-dracut&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;mkinitcpio is fine, but not widely adopted. Most distributions, including Debian, Ubuntu, Fedora, RHEL and many more, use dracut. This of course reflects on the amount of information and solutions available for each.&lt;&#x2F;p&gt;
&lt;p&gt;For me, the main deciding factor was the ease of configuration. While neither option is really all that complex, dracut &lt;em&gt;is&lt;&#x2F;em&gt; easier to configure and needing to administer multiple systems means I don’t want to maintain multiple solutions. So I wanted a common basis for all my systems. Therefore my decision fell on dracut.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;first-build&quot;&gt;
&lt;h2&gt;First build &lt;a class=&quot;header-link&quot; href=&quot;#first-build&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now, regarding the actuall steps required to switch from mkinitcpio to dracut: firstly, we need to install dracut. On most systems it is typical, that before installing new packages, one should update the system. In this case, if the update pulled in a newer kernel version or other package version which required rebuilding the initramfs, then the system should be rebooted afterwards to make the first initramfs build using dracut will actually use the latest installed kernel and not the active but out-of-date version.&lt;&#x2F;p&gt;
&lt;p&gt;Once rebooted (if necessary), we simply install our distributions dracut-package (e.g. &lt;code&gt;dracut&lt;&#x2F;code&gt;) using the package manager. We won’t uninstall mkinitcpio yet, only once we have thoroughly tested that dracut actually works. Also, only then will we configure pacman to use dracut instead of mkinitcpio to rebuild the initramfs on kernel updates.&lt;&#x2F;p&gt;
&lt;p&gt;The main configuration file for dracut is &lt;code&gt;&#x2F;etc&#x2F;dracut.conf&lt;&#x2F;code&gt;, but we won’t edit that one directly. Instead, we’ll work on our own file in &lt;code&gt;&#x2F;etc&#x2F;dracut.d&#x2F;&lt;&#x2F;code&gt;, e.g. &lt;code&gt;myflags.conf&lt;&#x2F;code&gt;. This allows for distribution maintainers to update &lt;code&gt;&#x2F;etc&#x2F;dracut.conf&lt;&#x2F;code&gt; if needed on system updates, but also allow us to declutter our changes and keep them sorted. For now, we’ll simply add the following lines to our &lt;code&gt;&#x2F;etc&#x2F;dracut.d&#x2F;myflags.conf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;hostonly&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-genconfig&quot;&gt;&amp;quot;yes&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;hostonly_cmdline&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-genconfig&quot;&gt;&amp;quot;no&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The second line prevents dracut from storing the kernel command line in the initramfs. This might not be useful for everyone. If you are configuring the command line using the bootloader (e.g. Grub), then there is no need for this. AFAIK, setting it to &lt;code&gt;yes&lt;&#x2F;code&gt; can also cause some issues on some systems, especially on non-systemd ones, but don’t quote me on that. Also, dracut’s command line parameters take precedence over configuration files.&lt;&#x2F;p&gt;
&lt;p&gt;The first line on the other hand, is also important for SSHD specifically. While simply telling dracut to build the initramfs image only for this device instead of a generic host, meaning it shouldn’t be used while chrooted, this is also important on some systems and versions of dracut to ensure that the &lt;code&gt;root&lt;&#x2F;code&gt; user can actually be logged into via SSH. Wthout this option, the &lt;code&gt;&#x2F;etc&#x2F;shadow&lt;&#x2F;code&gt; file, which contains the hashes of user passwords, might not be created&#x2F;included in the image. Therefore, once you have built your initramfs image, you should verify whether your image contains an &lt;code&gt;etc&#x2F;shadow&lt;&#x2F;code&gt; file (note the absence of a leading slash!) and that it contains a line starting with &lt;code&gt;root:&lt;&#x2F;code&gt; followed by either a hash (starting with &lt;code&gt;$&lt;&#x2F;code&gt;), or an asterisk (&lt;code&gt;*&lt;&#x2F;code&gt;) using the following command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;lsinitrd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &#x2F;boot&#x2F;IMAGE_NAME.img&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt; etc&#x2F;passwd&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, simply running &lt;code&gt;sudo dracut -f -v&lt;&#x2F;code&gt; should build a new initramfs for the current kernel. The &lt;code&gt;-f&lt;&#x2F;code&gt; is used to force dracut to overwrite the existing initramfs image, &lt;code&gt;-v&lt;&#x2F;code&gt; for verbosity (which is the default on some systems). On some systems the command might fail the first time. In that case, you might need to run &lt;code&gt;sudo dracut -f -v --regenerate-all&lt;&#x2F;code&gt;, but your mileage may vary. You can also specify a path to overwrite a specific image file by simply appending it to the command above. If you didn’t reboot after a kernel update, you could also specify &lt;code&gt;--kver ...&lt;&#x2F;code&gt; to build the image for a specific kernel version.&lt;&#x2F;p&gt;
&lt;p&gt;Reboot the system to see whether your bootloader was able to detect the new initramfs image, and select it. If you use FDE for your root partition, enter the passphrase. Now, if your system boots correctly, dracut works and you can continue with the next steps. But if nothing seems to happen or you don’t get any passphrase prompt (but expected one, of course), you might want to press Escape to get more detailed information about the boot process. This is not necessary if your kernel command line doesn’t include &lt;code&gt;quiet&lt;&#x2F;code&gt;. To get even more detailed information, you can specify the kernel command line options &lt;code&gt;rd.shell&lt;&#x2F;code&gt;, &lt;code&gt;rd.debug&lt;&#x2F;code&gt; and &lt;code&gt;log_buf_len=1M&lt;&#x2F;code&gt;. This helped me to discover a boot loop which didn’t make sense and was fixed by simply rebuilding the initramfs. But for more concrete steps, consult the documentation or ask your system administrator (that’s a joke).&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;automatic-updates&quot;&gt;
&lt;h2&gt;Automatic updates &lt;a class=&quot;header-link&quot; href=&quot;#automatic-updates&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This section assumes a system using the pacman package manager (like archlinux). For other systems, similar solutions probably exist using hooks for the respective package managers. These steps are based on &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Dracut#Generate_a_new_initramfs_on_kernel_upgrade&quot;&gt;this section in the archlinux wiki entry on dracut&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For starters, we’ll create two executable scripts to be run automatically by pacman using so-called hooks. The first one simply automatically copies the vmlinuz binary (single binary that contains the kernel) to &lt;code&gt;&#x2F;boot&lt;&#x2F;code&gt; and calls dracut to build both the new initramfs as well as a generic fallback image for the latest kernel version. Simply create the file &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;dracut-install.sh&lt;&#x2F;code&gt; (the exact path doesn’t matter but must match the ones used in the hooks further below) with the following contents:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;--force&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;--no-hostonly-cmdline&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-while z-shell&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-read z-shell&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;r&lt;&#x2F;span&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-do z-shell&quot;&gt;do&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-double-brace z-begin z-shell&quot;&gt;[[&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;usr&#x2F;lib&#x2F;modules&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-regexp z-quantifier z-shell&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-not z-shell&quot;&gt;^&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;pkgbase&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-double-brace z-end z-shell&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-read z-shell&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;r&lt;&#x2F;span&gt; pkgbase &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;kver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;line&lt;span class=&quot;z-keyword z-operator z-expansion z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;usr&#x2F;lib&#x2F;modules&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;kver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;kver&lt;span class=&quot;z-keyword z-operator z-expansion z-shell&quot;&gt;%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;pkgbase&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;install&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;Dm0644&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;line&lt;span class=&quot;z-keyword z-operator z-expansion z-shell&quot;&gt;%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;pkgbase&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;vmlinuz&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;boot&#x2F;vmlinuz-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;pkgbase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dracut&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;args&lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-array z-shell&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;hostonly&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;boot&#x2F;initramfs-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;pkgbase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.img&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;kver&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;kver&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dracut&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;args&lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-array z-shell&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;no-hostonly&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;boot&#x2F;initramfs-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;pkgbase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-fallback.img&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;kver&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;kver&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-end z-shell&quot;&gt;done&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The second file, &lt;code&gt;&#x2F;usr&#x2F;loca&#x2F;bin&#x2F;dracut-remove.sh&lt;&#x2F;code&gt;, simply removes old images. If you want to retain the previous version, simply modify this script to do so. It should look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-while z-shell&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-read z-shell&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;r&lt;&#x2F;span&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-do z-shell&quot;&gt;do&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-double-brace z-begin z-shell&quot;&gt;[[&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;usr&#x2F;lib&#x2F;modules&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-regexp z-quantifier z-shell&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-not z-shell&quot;&gt;^&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;pkgbase&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-double-brace z-end z-shell&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-read z-shell&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;r&lt;&#x2F;span&gt; pkgbase &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;rm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;boot&#x2F;vmlinuz-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;pkgbase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;boot&#x2F;initramfs-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;pkgbase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.img&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;boot&#x2F;initramfs-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;pkgbase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-fallback.img&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-end z-shell&quot;&gt;done&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don’t forget to make both files executable:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;chmod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; +x &#x2F;usr&#x2F;local&#x2F;bin&#x2F;dracut-&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;install&lt;span class=&quot;z-punctuation z-separator z-shell&quot;&gt;,&lt;&#x2F;span&gt;remove&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.sh&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now all that’s left to do, is creating the pacman hooks themself, one for each script. Hooks are placed in &lt;code&gt;&#x2F;etc&#x2F;pacman.d&#x2F;hooks&lt;&#x2F;code&gt;. This directory might not be created initially, so ensure it exists. Then just create the pacman hook &lt;code&gt;&#x2F;etc&#x2F;pacman.d&#x2F;hooks&#x2F;90-dracut-install.hook&lt;&#x2F;code&gt; and add the following to it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;[Trigger]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Type&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Path
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Operation&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Install
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Operation&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Upgrade
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Target&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; usr&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;lib&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;modules&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;pkgbase
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;[Action]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Description&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Updating linux initcpios (&lt;span class=&quot;z-keyword z-other z-genconfig&quot;&gt;with&lt;&#x2F;span&gt; dracut&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;!&lt;&#x2F;span&gt;)&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;When&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; PostTransaction
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Exec&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;usr&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;local&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;bin&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;dracut&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;-&lt;&#x2F;span&gt;install&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Depends&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; dracut
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;NeedsTargets
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Followed by &lt;code&gt;&#x2F;etc&#x2F;pacman.d&#x2F;hooks&#x2F;60-dracut-remove.hook&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;[Trigger]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Type&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Path
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Operation&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Remove
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Target&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; usr&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;lib&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;modules&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;pkgbase
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;[Action]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Description&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Removing linux initcpios&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;When&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; PreTransaction
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Exec&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;usr&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;local&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;bin&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;dracut&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;-&lt;&#x2F;span&gt;remove&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-storage z-type z-genconfig&quot;&gt;NeedsTargets
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s it. A fairly straight forward process. If you are curious about why I needed this in the first place, then you can find the second part here: &lt;a href=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;bytes&#x2F;ssh_decrypt&#x2F;&quot;&gt;Bootstrapping OpenSSH: Remote Disk Decryption&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SFTP, but with jailtime</title>
        <published>2024-07-30T22:26:00+02:00</published>
        <updated>2024-07-30T22:26:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/sftp_jail/"/>
        <id>https://traumweh.dev/bytes/sftp_jail/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/sftp_jail/">&lt;section id=&quot;problem&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;SFTP, but with jailtime&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#problem&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let’s talk about what problem I tried to solve. Essentially, I wanted to give my devices access to a fairly large set of files. But I didn’t want to use Syncthing, partially because I seem to attract sync-conflicts, but more importantly because some of the devices don’t even have enough free storage space. Of course some might ask: why don’t you just host a Nextcloud instance? Simple: I neither like Nextcloud, nor do I need &lt;em&gt;any&lt;&#x2F;em&gt; of its Groupware, Sharing, and other &lt;em&gt;magic features&lt;&#x2F;em&gt;. I just need a place to put my files to retrieve them at a later point.&lt;&#x2F;p&gt;
&lt;p&gt;So I did the only logical thing: &lt;del&gt;I hosted a Samba server.&lt;&#x2F;del&gt; I looked at SFTP. The server is already accessible via its OpenSSH server using authorized FIDO-based SSH keys, limited to my Wireguard VPN. So I created a &lt;code&gt;nas&lt;&#x2F;code&gt; user and mounted some HDD-based storage to its home directory and done.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;constraints&quot;&gt;
&lt;h2&gt;Some more constraints &lt;a class=&quot;header-link&quot; href=&quot;#constraints&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Except… I neither need, nor want a full secure-shell for this user. It should only be able to access the files on the designated drive; i.e. no access (not even read-access) to &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;etc&lt;&#x2F;code&gt; or similar. On top of that, I was wandering if it was possible to prevent access to the user’s &lt;code&gt;authorized_keys&lt;&#x2F;code&gt; file. That is, can I prevent someone with access to the &lt;code&gt;nas&lt;&#x2F;code&gt; user from changing who can access it?&lt;&#x2F;p&gt;
&lt;p&gt;Turns out: yes! And it is surprisingly simple, too. An OpenSSH server by default hosts an internal SFTP server, so no need to anything in this regard. To verify that your’s has SFTP enabled too, simply verify that your &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config&lt;&#x2F;code&gt; or a file in &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config.d&#x2F;&lt;&#x2F;code&gt; contains the line:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Subsystem&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;sftp &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;usr&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;libexec&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;openssh&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;sftp&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;-&lt;&#x2F;span&gt;server
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If it doesn’t, you can either add it to your &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config&lt;&#x2F;code&gt;, or add it to the file that we’ll craete in a moment. Read on to understand the difference, and what benefits the latter has.&lt;&#x2F;p&gt;
&lt;p&gt;To start, let’s create a new subconfiguration &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config.d&#x2F;20-sftp.conf&lt;&#x2F;code&gt; and, for those who don’t know, talk about what this file-path and -name even are:&lt;&#x2F;p&gt;
&lt;p&gt;Maybe you stumbled across &lt;code&gt;something.d&lt;&#x2F;code&gt; directories are that are littered throughout &lt;code&gt;&#x2F;etc&lt;&#x2F;code&gt; and elsewhere in Linux before and wandered what they were. Think of them as extensions to the regular configuration files like &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config&lt;&#x2F;code&gt;. The regular files are often provided by the distributions package manager and can get overwritten by package updates. Files in &lt;code&gt;something.d&lt;&#x2F;code&gt; on the other hand, are (normally) garanteed to persist updates. On top of that, if they specify options which are already specified in the regular file &lt;code&gt;something&lt;&#x2F;code&gt;, then the &lt;code&gt;something.d&lt;&#x2F;code&gt;-file overrides the values in the regular one.&lt;&#x2F;p&gt;
&lt;p&gt;You might have notices, that we prefixed the file with &lt;code&gt;20-&lt;&#x2F;code&gt;; this is a priority. Most software loads the files in &lt;code&gt;something.d&lt;&#x2F;code&gt; in the order specified by these priorities (low to high), excepting values from 0 (or 1) to 100. It depends on the application whether or not a priority can be specified more than once. Everything after the seperating hyphen (&lt;code&gt;-&lt;&#x2F;code&gt;) is (normally) up to you; use something self-documenting.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;jailtime&quot;&gt;
&lt;h2&gt;To the jail you go! &lt;a class=&quot;header-link&quot; href=&quot;#jailtime&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I stumbled across an OpenSSH option to redefine, what a connected user sees as root (to be read as &lt;code&gt;&#x2F;&lt;&#x2F;code&gt;). The &lt;code&gt;ChrootDirectory&lt;&#x2F;code&gt; option does just that. It changes the root directory a user sees (let’s call that directory the “chroot”). I also found another option, &lt;code&gt;ForceCommand&lt;&#x2F;code&gt;, which forces a user to execute a specific command, including internal commands provides by the OpenSSH server. But just these options alone don’t really help us. After all, we don’t want &lt;em&gt;all&lt;&#x2F;em&gt; users to follow these rules.&lt;&#x2F;p&gt;
&lt;p&gt;Its like the OpenSSH developers had thought about this. Because there is also the &lt;code&gt;Match&lt;&#x2F;code&gt; directive, which allows one to apply a set of options only to a set of connections. So let’s look at a minimal example and go over it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Match&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;user nas
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;ChrootDirectory&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-source z-genconfig&quot;&gt;%h&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;ForceCommand&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;internal&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;-&lt;&#x2F;span&gt;sftp
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the first line, we apply the configuration options only to the connections of the user &lt;code&gt;nas&lt;&#x2F;code&gt;. We could also match users of a specific group, which could e.g. be used to allow multiple users to access the drive and use either file-ownership, permissions or other configuration options to further limit specific users.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;%h&lt;&#x2F;code&gt; in the second line specifies the user’s home directory as the chroot. One could also use &lt;code&gt;%u&lt;&#x2F;code&gt; to build a path like &lt;code&gt;&#x2F;path&#x2F;to&#x2F;drive&#x2F;%u&lt;&#x2F;code&gt; based on the user name (obviosuly not useful with the specified &lt;code&gt;Match&lt;&#x2F;code&gt; line above).&lt;&#x2F;p&gt;
&lt;p&gt;Lastly, we can limit the user to only use SFTP using OpenSSH’s internal SFTP command. This results in connection resets for all other types of connections like regular &lt;code&gt;ssh&lt;&#x2F;code&gt; or &lt;code&gt;scp&lt;&#x2F;code&gt; connections.&lt;&#x2F;p&gt;
&lt;p&gt;We can also specify many more options to override rules not matches to a specific user. To give some examples of this, the following snippet prevents users from accessing graphical X11-sessions or tunnel TCP ports. It also requires them to use asymmetric keys instead of passwords for authentication:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Match&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;user nas
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;ChrootDirectory&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-source z-genconfig&quot;&gt;%h&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;ForceCommand&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;internal&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;-&lt;&#x2F;span&gt;sftp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;X11Forwarding&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;no&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;AllowTcpForwarding&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;no&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;PasswordAuthentication&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;no&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;PubkeyAuthentication&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;yes&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;caveats&quot;&gt;
&lt;h2&gt;Some happy little caveats &lt;a class=&quot;header-link&quot; href=&quot;#caveats&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;ChrootDirectory&lt;&#x2F;code&gt; option requires that the chroot (but not its contents) must be owned by the root user. This means, that it should contain at least one more directory writable by the user(s), or otherwise this whole endeavour would have been useless. In my case, I have the two directories &lt;code&gt;volatile&lt;&#x2F;code&gt; and &lt;code&gt;persistent&lt;&#x2F;code&gt;, the latter being included in daily backups.&lt;&#x2F;p&gt;
&lt;p&gt;A more welcome caveat is the way, public keys are authorized. Because the home directory gets overwritten to be the &lt;code&gt;&#x2F;&lt;&#x2F;code&gt;, the user’s regular &lt;code&gt;~&#x2F;.ssh&#x2F;authorized_keys&lt;&#x2F;code&gt; path doesn’t work anymore. We could of course just change the chroot to a different directory, but either way, the &lt;code&gt;authorized_keys&lt;&#x2F;code&gt; file wouldn’t be accessible anymore.&lt;&#x2F;p&gt;
&lt;p&gt;But this is fine. After all, we don’t want connected users to change who has access, anyway. Instead, we can simply add the following line to the top of our subconfiguration:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; class=&quot;language-ini z-code&quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;AuthorizedKeysFile&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;etc&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;ssh&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;authorized_keys&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-source z-genconfig&quot;&gt;%u&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-genconfig&quot;&gt;ssh&#x2F;authorized_keys&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;Match&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;user nas
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;ChrootDirectory&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-source z-genconfig&quot;&gt;%h&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;ForceCommand&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;internal&lt;span class=&quot;z-keyword z-operator z-genconfig&quot;&gt;-&lt;&#x2F;span&gt;sftp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;X11Forwarding&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;no&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;AllowTcpForwarding&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;no&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;PasswordAuthentication&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;no&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-genconfig&quot;&gt;&lt;span class=&quot;z-meta z-param z-genconfig&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-genconfig&quot;&gt;PubkeyAuthentication&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-genconfig&quot;&gt;yes&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can simply use the file &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;authorized_keys&#x2F;nas&lt;&#x2F;code&gt; to authorize ssh public keys. Its syntax is equivalent to that of regular &lt;code&gt;authorized_keys&lt;&#x2F;code&gt; files.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;conclusion&quot;&gt;
&lt;h2&gt;Conclusion &lt;a class=&quot;header-link&quot; href=&quot;#conclusion&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While this seems like an unnecessarily comlex way to achieve a simple file share, it is still a lot less complex, and way simpler to update than hosting a Nextcloud instance or dealing with sync-conflicts. And to my very specific use-case, this is a good enough solution.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>About</title>
        <published>2024-05-30T12:50:00+02:00</published>
        <updated>2024-05-30T12:50:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/about/"/>
        <id>https://traumweh.dev/about/</id>
        
        <content type="html" xml:base="https://traumweh.dev/about/">&lt;section id=&quot;about&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;About&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#about&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Heya! I’m happy you found my corner of &lt;del&gt;hell&lt;&#x2F;del&gt; the internet. I hope you like it!&lt;&#x2F;p&gt;
&lt;p&gt;I am &lt;span lang=&quot;de&quot;&gt;traumweh&lt;&#x2F;span&gt;, pronounced &lt;span class=&quot;accent&quot;&gt;[tʁaʊ̯mˌveː]&lt;&#x2F;span&gt;, but you can also call me &lt;strong&gt;lilith&lt;&#x2F;strong&gt;. Both are my online nicknames, but lilith is probably easier to pronounce for many people. You can address me using she&#x2F;her, they&#x2F;them and it&#x2F;its pronouns. I am a queer, antifascist computer science student, &lt;strong&gt;feminist and privacy advocate&lt;&#x2F;strong&gt;. I like to spend my time coding in C, Rust or C++ and enjoy learning about all things &lt;strong&gt;privacy&lt;&#x2F;strong&gt;, &lt;strong&gt;security&lt;&#x2F;strong&gt;, &lt;strong&gt;accessibility&lt;&#x2F;strong&gt; and &lt;strong&gt;selfhosting&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;whatido&quot;&gt;
&lt;h2&gt;What I do &lt;a class=&quot;header-link&quot; href=&quot;#whatido&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In my free time I like to do some programming. Some of the things I enjoyed working on are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;lyx&quot;&gt;Lyx: A Link Shortener&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;duckypad_daemon&quot;&gt;DuckyPad Daemon&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;hetzner-ddns&quot;&gt;Hetzner DynDNS service&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;fundgrube&quot;&gt;WIP Lost+Found website&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;fsm&quot;&gt;FSM Designer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;not-monetizable&quot;&gt;Not Monetizable&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I also discovered 3D printing and creating my own models using OpenSCAD. In most cases I will publish the models under the CC BY-NC-SA 4.0 license on my own forgejo instance:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;ratchet_clip&quot;&gt;Clip to securely hold things like gloves&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;wled-esp-case&quot;&gt;Case for an ESP C3 Super Mini running WLED&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;bottletag-holder&quot;&gt;Clamp for a pipe to hold on to bottle-nametags&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;bottletags&quot;&gt;WIP bottle-nametags&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&#x2F;travelcase-inserts&quot;&gt;Inserts for a utility travelcase&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I also onjoy helping out at events related to the Chaos Computer Club. For example, I help with logistics at the Congress or work on the design for the Easterhegg 2025.&lt;&#x2F;p&gt;
&lt;p&gt;I also write up some of the &lt;a href=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;bytes&#x2F;&quot;&gt;things I learned or accomplished recently&lt;&#x2F;a&gt; in more detail. I call them &lt;em&gt;bytes&lt;&#x2F;em&gt;. Because they are often related to programming or system administration, but can also be actual cooking recipes. This makes it a double pun, and how could I possibly say no to that?&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;friends&quot;&gt;
&lt;h2&gt;Friends &lt;a class=&quot;header-link&quot; href=&quot;#friends&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;li.lly.sh&quot;&gt;lilly&lt;&#x2F;a&gt;↗&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kritzl.dev&quot;&gt;kritzl&lt;&#x2F;a&gt;↗&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;vicwrobel.de&quot;&gt;Vic Wrobel&lt;&#x2F;a&gt;↗&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;contact&quot;&gt;
&lt;h2&gt;I&amp;#x27;m here &lt;a class=&quot;header-link&quot; href=&quot;#contact&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Forgejo: &lt;a href=&quot;https:&#x2F;&#x2F;git.lyx.sh&#x2F;traumweh&quot;&gt;@traumweh&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Codeberg: &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;traumweh&quot;&gt;@traumweh&lt;&#x2F;a&gt;↗&lt;&#x2F;li&gt;
&lt;li&gt;GitHub: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;traumweh&quot;&gt;@traumweh&lt;&#x2F;a&gt;↗&lt;&#x2F;li&gt;
&lt;li&gt;Mastodon: &lt;a rel=&quot;me&quot; href=&quot;https:&#x2F;&#x2F;chaos.social&#x2F;@traumweh&quot;&gt;@traumweh&lt;&#x2F;a&gt;↗&lt;&#x2F;li&gt;
&lt;li&gt;Email: hello@lyx.sh (&lt;a href=&quot;&#x2F;download&#x2F;publickey_contact.asc&quot;&gt;PGP Publickey&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Recommendations: Music, Podcasts and Blogs</title>
        <published>2024-05-30T12:24:20+02:00</published>
        <updated>2024-05-30T12:24:20+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/music_podcasts_blogs/"/>
        <id>https://traumweh.dev/bytes/music_podcasts_blogs/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/music_podcasts_blogs/">&lt;section id=&quot;introduction&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Music, Podcasts and Blogs&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#introduction&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Whenever I can—and neither need silence nor want to actively think about things—I’m probably listening to an album or podcast. Or I might be reading a blogpost or book. But sometimes just sitting&#x2F;walking in silence is great too. Because these things mean so much to me, I thought I might as well create lists of &lt;a href=&quot;#podcasts&quot;&gt;my favourite podcasts&lt;&#x2F;a&gt;, &lt;a href=&quot;#blogs&quot;&gt;some great blogs&lt;&#x2F;a&gt; and most importantly for me, &lt;a href=&quot;#music&quot;&gt;of incredible music and artists&lt;&#x2F;a&gt; for you to check out.&lt;&#x2F;p&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;podcasts&quot;&gt;
&lt;h2&gt;Podcasts &lt;a class=&quot;header-link&quot; href=&quot;#podcasts&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul class=&quot;spaced-list&quot;&gt;
  &lt;li&gt;
    &lt;b&gt;Midst&lt;&#x2F;b&gt;&lt;br&gt;
    This is by far the best story podcast I have ever heard! &lt;a href=&quot;https:&#x2F;&#x2F;midst.co&quot;&gt;Available at midst.co, three unreliable narrators chaotically tell the story of midst&lt;&#x2F;a&gt;↗, an english science-fiction space western! It&#x27;s amazing! They also have episode transcripts available.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Late Night Linux (Family)&lt;&#x2F;b&gt;&lt;br&gt;
    This is a family of english podcasts about Linux, open source software and systems administration. &lt;a href=&quot;https:&#x2F;&#x2F;latenightlinux.com&#x2F;about&#x2F;&quot;&gt;A list of the different shows can be found on latenightlinux.com&lt;&#x2F;a&gt;↗. Sadly there isn&#x27;t much diversity in the set of hosts. There are also &lt;b&gt;no transcripts&lt;&#x2F;b&gt; available.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Haecksenwerk&lt;&#x2F;b&gt;&lt;br&gt;
    A German podcast about feminism, technology, culture and more. &lt;a href=&quot;https:&#x2F;&#x2F;www.haecksen.org&#x2F;podcast&quot;&gt;The podcast as well as transcripts are available at haecksen.org&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Tech Won&#x27;t Save Us&lt;&#x2F;b&gt;&lt;br&gt;
    An english technopolitical podcast about current problems regarding Web3 (crypto-currencies, AI, ...), tech-billionairs and other reasons why tech won&#x27;t save us. &lt;a href=&quot;https:&#x2F;&#x2F;www.techwontsave.us&#x2F;&quot;&gt;The podcast can be found at techwontsave.us&lt;&#x2F;a&gt;↗. It sadly doesn&#x27;t have transcripts available.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Kill James Bond!&lt;&#x2F;b&gt;&lt;br&gt;
    An english podcast by November Kelly, Abigail Thorn and Devon about the James Bond movies and why James Bond is a problem. &lt;a href=&quot;https:&#x2F;&#x2F;www.killjamesbond.com&#x2F;&quot;&gt;The podcast---but sadly no transcripts---can be found at killjamesbond.com&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;blogs&quot;&gt;
&lt;h2&gt;Blogs &lt;a class=&quot;header-link&quot; href=&quot;#blogs&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul class=&quot;spaced-list&quot;&gt;
  &lt;li&gt;
    &lt;b&gt;Xe Iaso&lt;&#x2F;b&gt;&lt;br&gt;
    Xe writes long post about a variety of stuff, mostly in regards to software development and can be found at &lt;a href=&quot;https:&#x2F;&#x2F;xeiaso.net&#x2F;blog&#x2F;&quot;&gt;xeiaso.net&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Amos (&lt;span lang=&quot;en&quot;&gt;faster than lime&lt;&#x2F;span&gt;)&lt;&#x2F;b&gt;&lt;br&gt;
    Amos writes long posts about software development, often about Rust and can be found at &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&#x2F;&quot;&gt;fasterthanli.me&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;JeanHeyd Meneide&lt;&#x2F;b&gt;&lt;br&gt;
    On their blog &lt;i&gt;The Pasture&lt;&#x2F;i&gt; at &lt;a href=&quot;https:&#x2F;&#x2F;thephd.dev&#x2F;&quot;&gt;thephd.dev&lt;&#x2F;a&gt;↗ they write about the C and C++ standards and their wonderful terribleness. The fairly technical long-posts are always a delight to read.
  &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;music&quot;&gt;
&lt;h2&gt;Music &lt;a class=&quot;header-link&quot; href=&quot;#music&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul class=&quot;spaced-list&quot;&gt;
  &lt;li&gt;
    &lt;b&gt;Joashua Lee Turner and Bob Barrick - Heartache Here&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=nK9zgvxf1nM&quot;&gt;youtube.com&lt;&#x2F;a&gt;↗. The video does have proper subtitles.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Sugadaisy - Where the wildflowers grow.&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9qzpYqcO_ug&quot;&gt;youtube.com&lt;&#x2F;a&gt;↗, but the video only has bad auto-generated subtitles.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Scruffy&lt;&#x2F;b&gt;&lt;br&gt;
    All their music is available on &lt;a href=&quot;https:&#x2F;&#x2F;scruffymusic.com&quot;&gt;scruffymusic.com&lt;&#x2F;a&gt;↗, but the website is a lot (visually), has bad tab navigation and malformed HTML.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Qumu&lt;&#x2F;b&gt;&lt;br&gt;
    All their music is available on &lt;a href=&quot;https:&#x2F;&#x2F;qumumusic.com&quot;&gt;qumumusic.com&lt;&#x2F;a&gt;↗. The website has low contrast.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Erin Snape&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;erinsnape.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Sufjan Stevens&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;music.sufjan.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Envoi&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;envoiofficial.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Fewjar&lt;&#x2F;b&gt;&lt;br&gt;
    Their music is available on &lt;a href=&quot;https:&#x2F;&#x2F;fewjar.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗ and physical media as well as merch on &lt;a href=&quot;https:&#x2F;&#x2F;fewjar.de&quot;&gt;fewjar.de&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Autumn Orange&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;autumnorange.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;In Love With A Ghost&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;inlovewithaghost.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Saint Motel - Voyeur&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;saintmotel.bandcamp.com&#x2F;album&#x2F;voyeur&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Mutemath - Play Dead&lt;&#x2F;b&gt;&lt;br&gt;
    Honestly, I couldn&#x27;t find a proper place to buy it, so I bought it from a random music distribution service.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Bug Hunter - The Rough Draft&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;bughunterbug.bandcamp.com&#x2F;album&#x2F;the-rough-draft&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;GussWhat? - M.J.&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=mAzh3we3UGk&quot;&gt;youtube.com&lt;&#x2F;a&gt;↗, but the video only has bad auto-generated subtitles.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Meganeko - Nascens&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;meganeko.bandcamp.com&#x2F;album&#x2F;nascens&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Gotye&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;store.gotye.com&#x2F;&quot;&gt;gotye.com&lt;&#x2F;a&gt;↗, but the website has bad tab navigation.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Miracle Of Sound - Level 5&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;miracleofsound.bandcamp.com&#x2F;album&#x2F;level-5&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;aivi &amp;amp; surasshu - The Black Box&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;aivisura.bandcamp.com&#x2F;album&#x2F;the-black-box&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Birdmask - I&#x27;m Fine and other lies.&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;birdmask.bandcamp.com&#x2F;album&#x2F;im-fine-and-other-lies&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Johnny Manchild and The Poor Bastards - Insomnia&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;johnnymanchild.bandcamp.com&#x2F;album&#x2F;insomnia&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Ricky Montgomery - Montgomery Ricky&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;rickymontgomery.bandcamp.com&#x2F;album&#x2F;montgomery-ricky&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;GameChops&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;gamechops.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Unknown Mortal Orchestra - SB-01&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;unknown-mortal-orchestra.bandcamp.com&#x2F;track&#x2F;sb-01-2&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;moow - I can&#x27;t tell you how much it hurts&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;moow-beat.bandcamp.com&#x2F;album&#x2F;i-cant-tell-you-how-much-it-hurts&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;The Altogether&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;thealtogether.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Ken Ashcorp - Blue&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;kenashcorp.bandcamp.com&#x2F;track&#x2F;blue&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Aviators - Stargazers&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;soundoftheaviators.bandcamp.com&#x2F;album&#x2F;stargazers&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;The Revivalists - Men Amongst Mountains&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;therevivalists.bandcamp.com&#x2F;album&#x2F;men-amongst-mountains&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Parcels - Parcels&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;parcelsmusic.bandcamp.com&#x2F;album&#x2F;parcels&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Fish in a Birdcage - Waterfall&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;www.fishinabirdcage.com&#x2F;music&quot;&gt;fishinabirdcage.com&lt;&#x2F;a&gt;↗. The website is a bit much (visually).
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Jacob Collier&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;shop.jacobcollier.com&quot;&gt;shop.jacobcollier.com&lt;&#x2F;a&gt;↗, but the website has bad tab navigation.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Polyphia&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;polyphia.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;To The Rats And Wolves - Cheap Love&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;arisingempire.bandcamp.com&#x2F;album&#x2F;cheap-love&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;To The Rats And Wolves - Dethroned&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;arisingempire.bandcamp.com&#x2F;album&#x2F;dethroned&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;TWRP&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;twrp.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Starbomb&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;starbomb.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;NSP&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;ninjasexparty.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Aberdeen&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;aberdeentheband.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Berlinist - Gris OST&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;berlinistband.bandcamp.com&#x2F;album&#x2F;gris-original-game-soundtrack&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Boqeh&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;boqeh.bandcamp.com&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Lena Raine - Celeste OST&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;radicaldreamland.bandcamp.com&#x2F;album&#x2F;celeste-original-soundtrack&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Danny Baranowsky - Crypt of the Necrodancer OST&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;dbsoundworks.bandcamp.com&#x2F;album&#x2F;crypt-of-the-necrodancer-ost&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Christopher Larkin - Hollow Knight OST&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;christopherlarkin.bandcamp.com&#x2F;album&#x2F;hollow-knight-original-soundtrack&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Curtis Schweitzer - Starbound OST&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;curtisschweitzer.bandcamp.com&#x2F;album&#x2F;starbound-original-soundtrack&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Big Thief - Dragon New Warm Mountain I Believe In You&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;bigthief.bandcamp.com&#x2F;album&#x2F;dragon-new-warm-mountain-i-believe-in-you&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Fredrik - Trilogi&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;fredrik.bandcamp.com&#x2F;album&#x2F;trilogi&quot;&gt;their bandcamp.com page&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Mystery Skulls&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;mysteryskullshq.com&#x2F;&quot;&gt;mysteryskullshq.com&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Paramore&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;www.paramore.net&#x2F;&quot;&gt;paramore.net&lt;&#x2F;a&gt;↗, but the site is a lot (visually) and tab navigation can be confusing.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;Periphery&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;periphery.net&#x2F;&quot;&gt;periphery.net&lt;&#x2F;a&gt;↗. The website has low contrast in some places.
  &lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;b&gt;&lt;span lang=&quot;de&quot;&gt;Systemabsturz&lt;&#x2F;span&gt;&lt;&#x2F;b&gt;&lt;br&gt;
    Available on &lt;a href=&quot;https:&#x2F;&#x2F;systemabsturz.band&#x2F;&quot;&gt;systemabsturz.band&lt;&#x2F;a&gt;↗.
  &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Raspberry Crumble Pie</title>
        <published>2024-05-19T21:55:00+02:00</published>
        <updated>2024-05-19T21:55:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/raspberry_crumble_pie/"/>
        <id>https://traumweh.dev/bytes/raspberry_crumble_pie/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/raspberry_crumble_pie/">&lt;p&gt;&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Raspberry Crumble Pie&lt;&#x2F;span&gt;&lt;&#x2F;h1&gt;

&lt;section id=&quot;ingredients&quot;&gt;
&lt;h2&gt;Ingredients &lt;a class=&quot;header-link&quot; href=&quot;#ingredients&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;375 g flour&lt;&#x2F;li&gt;
&lt;li&gt;250 g margarine&lt;&#x2F;li&gt;
&lt;li&gt;150 g raspberry confiture&lt;&#x2F;li&gt;
&lt;li&gt;200 g raspberries&lt;&#x2F;li&gt;
&lt;li&gt;150 g sugar&lt;&#x2F;li&gt;
&lt;li&gt;1 pinch of salt&lt;&#x2F;li&gt;
&lt;li&gt;1 packet of vanilla sugar&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;&#x2F;p&gt;
&lt;section id=&quot;preparation&quot;&gt;
&lt;h2&gt;preparation &lt;a class=&quot;header-link&quot; href=&quot;#preparation&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Mix and knead the flour, margarine, sugar, salt and vanilla sugar&lt;&#x2F;li&gt;
&lt;li&gt;Grease the baking tin or cover it with baking paper&lt;&#x2F;li&gt;
&lt;li&gt;Spread 2&#x2F;3 of the dough as a flat base with higher rim in the baking tin&lt;&#x2F;li&gt;
&lt;li&gt;Spread the confiture over the base (more jam requires a thicker base)&lt;&#x2F;li&gt;
&lt;li&gt;Spread the raspberries evenly&lt;&#x2F;li&gt;
&lt;li&gt;Make the rest of the dough into crumbles and spread evenly&lt;&#x2F;li&gt;
&lt;li&gt;Bake at 175 °C for approx. 45 minutes&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Reduced Motion: Handling Animations and GIFs</title>
        <published>2024-05-19T20:00:00+02:00</published>
        <updated>2024-05-19T20:00:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/reduced_motion/"/>
        <id>https://traumweh.dev/bytes/reduced_motion/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/reduced_motion/">&lt;section id=&quot;problem&quot;&gt;
&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Reduced Motion&lt;&#x2F;span&gt; &lt;a class=&quot;header-link&quot; href=&quot;#problem&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;When designing websites—well, anything, really—it is important to think about what impacts your designs can have on people with disabilities. Motion-heavy animations, animated GIFs and similar, can cause discomfort for people with, e.g. vestibular motion disorders. For this reason, browsers have had support for the &lt;code&gt;prefers-reduced-motion&lt;&#x2F;code&gt; media query for a long time, allowing users to set motion preferences at both the browser and even the operating system level.&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;animations&quot;&gt;
&lt;h2&gt;Animations &lt;a class=&quot;header-link&quot; href=&quot;#animations&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s take the following CSS animation, which is played when clicking an anchor next to a heading on this page, as an example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-pseudo-class z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css&quot;&gt;:&lt;&#x2F;span&gt;target&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;  &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;highlight &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;3&lt;span class=&quot;z-keyword z-other z-unit z-css&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could add the following snippet below, to disable the animation if a user prefers reduced motion:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;media&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;prefers-reduced-motion: reduce&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;  &lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-pseudo-class z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css&quot;&gt;:&lt;&#x2F;span&gt;target&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;none&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But this disables the animation entirely, meaning when the animation would trigger, users with this preference are left out, not seeing anything. So instead, it might be better to instead show something, although with less motion in it, like this for example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;media&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;prefers-reduced-motion: reduce&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;  &lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-pseudo-class z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css&quot;&gt;:&lt;&#x2F;span&gt;target&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;highlight &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;3&lt;span class=&quot;z-keyword z-other z-unit z-css&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation-timing-function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-timing z-css&quot;&gt;steps&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;  &lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using the &lt;code&gt;steps()&lt;&#x2F;code&gt; function, one can specify the number of animation steps, which in this case only causes the first step of the animation to appear for three seconds, and then immediately disappear.&lt;&#x2F;p&gt;
&lt;p&gt;We can do one more thing, to also include the people using browsers that don’t support the media query, by using &lt;code&gt;no-preference&lt;&#x2F;code&gt; instead of &lt;code&gt;reduce&lt;&#x2F;code&gt; and swapping the rules:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-pseudo-class z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css&quot;&gt;:&lt;&#x2F;span&gt;target&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;  &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;highlight &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;3&lt;span class=&quot;z-keyword z-other z-unit z-css&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;  &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation-timing-function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-timing z-css&quot;&gt;steps&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;media&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;prefers-reduced-motion: no-preference&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;  &lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-pseudo-class z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css&quot;&gt;:&lt;&#x2F;span&gt;target&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;animation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;highlight &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;3&lt;span class=&quot;z-keyword z-other z-unit z-css&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can verify these results, by enabling reduced motion either in your operating system settings or in your browsers preferences and simply clicking on the anchor mark of one of these sections (the hash character behind a heading).&lt;&#x2F;p&gt;

&lt;&#x2F;section&gt;
&lt;section id=&quot;gifs&quot;&gt;
&lt;h2&gt;GIFs &lt;a class=&quot;header-link&quot; href=&quot;#gifs&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To respect a users choice for reduced motion in regard to animated GIFs, one might implement one of these two (non-exhaustive) options:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Show a freeze-frame of the GIF, keeping the alt-text of the original. This could also allow for reduced network traffic because only a single frame would need to be downloaded.&lt;&#x2F;li&gt;
&lt;li&gt;Create a different, static visualisation of the GIF’s information which doesn’t require motion. In this case the question would be, whether the GIF was even needed in the first place.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The second case could be solved in multiple ways, and as already stated, could be interpreted as a lack of need for the GIF in the first place. So instead let’s look at the more interesting case of showing a still.&lt;&#x2F;p&gt;
&lt;p&gt;When I first started thinking about this problem, I couldn’t come up with a solution that didn’t require JavaScript. But then I discovered the HTML &lt;code&gt;&amp;lt;picture&amp;gt;&lt;&#x2F;code&gt; element. It can be used to offer alternative versions of an image for different scenarios by specifying &lt;code&gt;&amp;lt;source&amp;gt;&lt;&#x2F;code&gt; elements as alternatives to a foundamental &lt;code&gt;&amp;lt;img&amp;gt;&lt;&#x2F;code&gt; element. And of these &lt;code&gt;&amp;lt;source&amp;gt;&lt;&#x2F;code&gt; elements, the best match is chosen by the browser. So let’s take this snippet here, which loads the animated cover-image for this website:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;img&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;traumweh.dev&#x2F;black_cat_x32.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;alt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;(Removed for readability.)&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a fairly fast, looping animation, which might very well cause discomfort for some individuals. So using thee &lt;code&gt;&amp;lt;picture&amp;gt;&lt;&#x2F;code&gt; element mentioned above, we could instead write the following code, which uses the &lt;code&gt;media&lt;&#x2F;code&gt; attribute for &lt;code&gt;&amp;lt;source&amp;gt;&lt;&#x2F;code&gt; elements, to specify that a resource is a good match for a certain media preference:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;picture&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;source&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-class z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-class z-html&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-meta z-class-name z-html&quot;&gt;coverart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;srcset&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;traumweh.dev&#x2F;black_cat_x32.gif&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;media&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;(prefers-reduced-motion: no-preference)&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;img&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-class z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-class z-html&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-meta z-class-name z-html&quot;&gt;coverart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;traumweh.dev&#x2F;black_cat_x32.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;alt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;(Removed for readability.)&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;picture&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This produces the following result, which you can verify by enabling reduced motion either in your operating system settings or in your browsers preferences:&lt;&#x2F;p&gt;
&lt;picture&gt;
  &lt;source class=&quot;coverart&quot; srcset=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;black_cat_x32.gif&quot; media=&quot;(prefers-reduced-motion: no-preference)&quot;&gt;
  &lt;img class=&quot;coverart&quot; src=&quot;https:&#x2F;&#x2F;traumweh.dev&#x2F;black_cat_x32.png&quot; alt=&quot;Monochrome pixelart animation of a cat running in a right-ward direction. The image is always centered on the cat. Depending on whether the website is in light or dark mode, the cat is darker or lighter respectively.&quot;&gt;
&lt;&#x2F;picture&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spelt Rolls</title>
        <published>2024-05-19T19:00:00+02:00</published>
        <updated>2024-05-19T19:00:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/spelt_rolls/"/>
        <id>https://traumweh.dev/bytes/spelt_rolls/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/spelt_rolls/">&lt;p&gt;&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Spelt Rolls&lt;&#x2F;span&gt;&lt;&#x2F;h1&gt;

&lt;section id=&quot;ingredients&quot;&gt;
&lt;h2&gt;Ingredients &lt;a class=&quot;header-link&quot; href=&quot;#ingredients&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Yeast:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;2 cubes of yeast&lt;&#x2F;li&gt;
&lt;li&gt;some lukewarm water&lt;&#x2F;li&gt;
&lt;li&gt;some spelt flour&lt;&#x2F;li&gt;
&lt;li&gt;some sugar&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Dough:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;500 g spelt flour&lt;&#x2F;li&gt;
&lt;li&gt;300 g lukewarm water&lt;&#x2F;li&gt;
&lt;li&gt;4 tablespoons olive oil&lt;&#x2F;li&gt;
&lt;li&gt;2 teaspoons salt&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;&#x2F;p&gt;
&lt;section id=&quot;preparation&quot;&gt;
&lt;h2&gt;preparation &lt;a class=&quot;header-link&quot; href=&quot;#preparation&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Mix the yeast with small parts of lukewarm water, flour &amp;amp; sugar&lt;&#x2F;li&gt;
&lt;li&gt;Leave yeast to rise&lt;&#x2F;li&gt;
&lt;li&gt;Knead together with the remaining ingredients for approx. 2.5 minutes&lt;&#x2F;li&gt;
&lt;li&gt;Divide dough into equal portions&lt;&#x2F;li&gt;
&lt;li&gt;Bake at 200 °C for approx. 20 minutes&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spelt Pizza</title>
        <published>2024-05-19T17:00:00+02:00</published>
        <updated>2024-05-19T17:00:00+02:00</updated>
        
        <author>
          <name>
            traumweh
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://traumweh.dev/bytes/spelt_pizza/"/>
        <id>https://traumweh.dev/bytes/spelt_pizza/</id>
        
        <content type="html" xml:base="https://traumweh.dev/bytes/spelt_pizza/">&lt;p&gt;&lt;h1&gt;&lt;span class=&quot;trans-underline&quot;&gt;Spelt Pizza&lt;&#x2F;span&gt;&lt;&#x2F;h1&gt;

&lt;section id=&quot;ingredients&quot;&gt;
&lt;h2&gt;Ingredients &lt;a class=&quot;header-link&quot; href=&quot;#ingredients&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;1 cube of yeast&lt;&#x2F;li&gt;
&lt;li&gt;375 g spelt flour&lt;&#x2F;li&gt;
&lt;li&gt;250 ml lukewarm water&lt;&#x2F;li&gt;
&lt;li&gt;1 teaspoon salt&lt;&#x2F;li&gt;
&lt;li&gt;1 teaspoon sugar&lt;&#x2F;li&gt;
&lt;li&gt;1 teaspoon pizza flavour&lt;&#x2F;li&gt;
&lt;li&gt;2 tablespoons olive oil&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;section&gt;
&lt;&#x2F;p&gt;
&lt;section id=&quot;preparation&quot;&gt;
&lt;h2&gt;preparation &lt;a class=&quot;header-link&quot; href=&quot;#preparation&quot; title=&quot;Link to this section&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Mix and knead all the ingredients together&lt;&#x2F;li&gt;
&lt;li&gt;Spread the dough on a tray&lt;&#x2F;li&gt;
&lt;li&gt;Leave to rise for one hour&lt;&#x2F;li&gt;
&lt;li&gt;Decorate pizza with toppings of your choice&lt;&#x2F;li&gt;
&lt;li&gt;Bake at 180 °C for approx. 20–25 minutes&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;&#x2F;section&gt;
</content>
        
    </entry>
</feed>
