<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>varakh.de</title>
    <link>https://varakh.de/</link>
    <description>Recent content on varakh.de</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Varakh</copyright>
    <lastBuildDate>Sun, 21 Dec 2025 14:49:00 +0200</lastBuildDate>
    <atom:link href="https://varakh.de/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Linux Momentum</title>
      <link>https://varakh.de/blog/2025-12-21-linux-momentum/</link>
      <pubDate>Sun, 21 Dec 2025 14:49:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-12-21-linux-momentum/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://itsfoss.com/news/linux-mainstream-gaming-2025/&#34;&gt;Linux is riding real &lt;strong&gt;momentum&lt;/strong&gt;&lt;/a&gt; in 2025 as more &lt;a href=&#34;https://pixelgipfel.ch/blogs/news/linux-gaming-2025-how-good-is-it-really-today&#34;&gt;people get fed up&lt;/a&gt; with Windows 11&amp;rsquo;s hardware requirements, constant online integration, and forced upgrade feeling, and &lt;a href=&#34;https://windowsforum.com/threads/move-to-linux-from-windows-11-real-world-reasons-and-safe-migration.382550/&#34;&gt;start looking for an OS that respects their control over the machine instead&lt;/a&gt;. Who wants AI in Notepad anyways. At the same time, gaming on Linux has quietly become &amp;ldquo;good enough&amp;rdquo; for most players, with Proton and SteamOS running a large majority of popular Steam titles smoothly and, in many cases, within a few percent of Windows performance or better. Tools like Lutris, Heroic, and gaming‑friendly distros (Bazzite) mean you no longer have to be a power user to get your library going. For a lot of single‑player, co‑op games, and even multiplayer games, it&amp;rsquo;s almost plug‑and‑play. Valve&amp;rsquo;s hardware and software strategy is quietly reshaping the PC gaming landscape in Linux&amp;rsquo;s favor and they did a tremendous job there. Also gaming‑focused distros like Nobara and Bazzite offer near plug‑and‑play setups, so new users avoid most of the old Linux &amp;ldquo;tinkering&amp;rdquo; stereotype. No doubt, Linux in 2025 still has rough edges, but they are increasingly specific rather than universal. Anti‑cheat is the big holdout: some competitive multiplayer titles either do not work or require workarounds, which still makes Windows preferable for certain esports games. For primarily single‑player or co‑op gamers, these gaps are often irrelevant, and they gain stability, control, and a cleaner system in exchange.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://itsfoss.com/news/linux-mainstream-gaming-2025/">Linux is riding real <strong>momentum</strong></a> in 2025 as more <a href="https://pixelgipfel.ch/blogs/news/linux-gaming-2025-how-good-is-it-really-today">people get fed up</a> with Windows 11&rsquo;s hardware requirements, constant online integration, and forced upgrade feeling, and <a href="https://windowsforum.com/threads/move-to-linux-from-windows-11-real-world-reasons-and-safe-migration.382550/">start looking for an OS that respects their control over the machine instead</a>. Who wants AI in Notepad anyways. At the same time, gaming on Linux has quietly become &ldquo;good enough&rdquo; for most players, with Proton and SteamOS running a large majority of popular Steam titles smoothly and, in many cases, within a few percent of Windows performance or better. Tools like Lutris, Heroic, and gaming‑friendly distros (Bazzite) mean you no longer have to be a power user to get your library going. For a lot of single‑player, co‑op games, and even multiplayer games, it&rsquo;s almost plug‑and‑play. Valve&rsquo;s hardware and software strategy is quietly reshaping the PC gaming landscape in Linux&rsquo;s favor and they did a tremendous job there. Also gaming‑focused distros like Nobara and Bazzite offer near plug‑and‑play setups, so new users avoid most of the old Linux &ldquo;tinkering&rdquo; stereotype. No doubt, Linux in 2025 still has rough edges, but they are increasingly specific rather than universal. Anti‑cheat is the big holdout: some competitive multiplayer titles either do not work or require workarounds, which still makes Windows preferable for certain esports games. For primarily single‑player or co‑op gamers, these gaps are often irrelevant, and they gain stability, control, and a cleaner system in exchange.</p>
<p>Crucially, the story in 2025 isn&rsquo;t just about games: everyday desktop life on Linux (web browsing, office work, chat apps, media, and coding) is now straightforward, with good hardware support, polished desktops like GNOME and KDE, and easy software installation via app stores and flatpaks. Many users report that once they set up their favorite browser, office suite, and a couple of communication tools, Linux feels like a calm, predictable environment compared with the constant churn of Windows 11, making it attractive both as a gaming platform and as a daily driver.</p>
<p>Putting it all together, 2025 feels <strong>less</strong> like &ldquo;the year of Linux on the desktop&rdquo; as a <strong>meme</strong> and <strong>more</strong> like a <a href="https://www.reddit.com/r/linux_gaming/comments/1hmaskf/2025_truly_is_the_year_of_linux_gaming/"><strong>real</strong> inflection point</a>. <a href="https://windowsforum.com/threads/pc-gaming-os-shifts-in-2025-windows-decline-linux-rise-what-it-means.368883/">Steam&rsquo;s own stats</a> support that and show Linux hitting record share on the platform and growing faster than before, even if the overall percentage is still modest. Community reports and long‑term tests from Linux gamers with large libraries confirm that thousands of titles now <a href="https://www.youtube.com/watch?v=bWfY9HktgmI">&ldquo;just work&rdquo;</a>, often with performance equal or better than Windows.</p>
<h2 id="the-turnaround">The Turnaround</h2>
<p>This marks a turnaround in the long lasting dominion of Windows and how it&rsquo;s perceived by broader, even non-tech audience. Microsoft really did everything they can to push people away from their well-established eco-system, people looking for alternatives, and finding that within the Linux community. Valve&rsquo;s strategy empowering gaming on Linux is paying off (they seem to be the good guys here). Imagine a world, where the computer you&rsquo;ve bought is actually <em>yours</em>. It does not spy on you. It does not force certain actions on you. Instead, it works for <em>you</em>. You can be an avid gamer or a desktop user. It doesn&rsquo;t matter. I think we don&rsquo;t need to imagine it anymore. It&rsquo;s here, or at least it&rsquo;s more close than ever before.</p>
<p>As you know, Linux has been my daily driver for years and I kept an eye on how things evolved. I am super happy to see that development, also in previous years, but personally I always had a dual boot setup with Windows (10). Despite not playing frequently, I still kept that, to not close any doors when I <em>really</em> wanted to play something which doesn&rsquo;t work on Linux. It has always bothered me to indirectly support Microsoft. That there was no <em>real</em> alternative. I knew for quite some time that the moment I have the chance to ditch Windows, I will, but Linux was just not there yet. <strong>Until 2025!</strong></p>
<p>Over the past two years I&rsquo;ve though noticed that I&rsquo;ve only been in my Windows when I thought it was &ldquo;time to update&rdquo;, not for gaming. Ultimately, Windows 10 being end-of-life gave the final argument for me to do it despite not playing on my Windows for over 1.5 years.</p>
<p>At least for me, 2025 is the year where I <em>finally</em> ditched Windows altogether! Quick partition deletion, resizing, and that space is now available for my Linux setup. Nice!</p>
<h2 id="recommendations-and-caveats">Recommendations and caveats</h2>
<p>A lot of blog posts focus on the heavy nerdy topics, like <a href="/tags/nix/">#nix</a>, though I think Linux is moving into the right direction. People who never considered it, are picking it up, or at least questioning the current situation. Adoption and usage is significantly increasing. If people start to question their existing behavior and come back with positive feedback on how they felt &ldquo;they got control over their systems back&rdquo;, it&rsquo;s the <strong>perfect time for you</strong> to at least start thinking as well!</p>
<p>You don&rsquo;t need to be a developer. You don&rsquo;t need to be that tech guy. You can make the switch, especially if you just do some browsing, checking mails, and some writing. No need to ditch old hardware, they usually still work. Even if you&rsquo;re a gamer, you can do the switch. Gaming support has never been better.</p>
<p>Keep in mind, leaving your comfort zone is usually perceived as discomfort. Maintain an open mindset while trying it out. Nobody forces you to do the switch. It&rsquo;s all about giving it a try!</p>
<p>As closing words, let me give you my two cents what you should be looking at and what you should avoid. Those points are heavily opinionated, keep that in mind!</p>
<ul>
<li>Don&rsquo;t use Ubuntu. You might read that it&rsquo;s beginner friendly, it might be, but the company behind it usually does &ldquo;their own stuff&rdquo;. I&rsquo;d recommend going with something more standard and broadly used. You&rsquo;ll have a better experience with other distributions.</li>
<li>Fedora is a valid choice.</li>
<li>KDE Desktop might look more familiar to your previous Windows setup.</li>
<li>GNOME Desktop looks really fancy in my opinion, requires you more to change what you&rsquo;re used to from Windows. I still think you should try, it&rsquo;s good and feels super polished.</li>
<li>Bazzite (based on Fedora) seems to be a very good choice for gaming-focused workloads.</li>
<li>For games, research how they work on <a href="https://www.protondb.com">protondb.com</a>, that&rsquo;s a really good source, especially if you&rsquo;re into Steam anyways!</li>
<li>In case you&rsquo;re about to buy new hardware, research on compatibility. Most stuff just works, but cross-checking for Linux compatibility doesn&rsquo;t hurt. I can also recommend going with AMD altogether, especially for graphics. AMD support on Linux is amazing.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>My Setup - Journey to NixOS Part II</title>
      <link>https://varakh.de/blog/2025-12-21-nix-journey-part2/</link>
      <pubDate>Sun, 21 Dec 2025 13:15:23 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-12-21-nix-journey-part2/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;This post is part of &lt;a href=&#34;https://varakh.de/tags/nixjourney/&#34;&gt;#nixjourney&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Recently, I came across a blog post stating someone&amp;rsquo;s reasons &lt;a href=&#34;https://carlosbecker.com/posts/bye-nix/&#34;&gt;to move away from nix&lt;/a&gt; on his Mac where he maintains dotfiles using &lt;a href=&#34;https://nixos.wiki/wiki/Home_Manager&#34;&gt;Home Manager&lt;/a&gt;. This made me think. Some points are valid: &lt;code&gt;/nix/store&lt;/code&gt; is large (my desktop has &lt;code&gt;~267G&lt;/code&gt; right now as I keep building for all hosts on my machine and have the tendency to never clean it up), quickly &amp;ldquo;changing&amp;rdquo; a hot key takes more time than editing the configuration file directly. Though, that cannot come as surprise, right? It&amp;rsquo;s the trade off you make for being the new cool kid on the block (or reproducibility, easy rollback) and central management. It plays nicely together if you manage more than your dotfiles with nix, like &lt;em&gt;a lot&lt;/em&gt; more. That&amp;rsquo;s where nix shines. It&amp;rsquo;s not supposed to &lt;em&gt;work for everyone&lt;/em&gt;. If it doesn&amp;rsquo;t work for you, that&amp;rsquo;s totally fine. It does for me though. As you might now, I am &lt;em&gt;&lt;a href=&#34;https://www.jeffgeerling.com/blog/2022/cosplaying-sysadmin?ref=drewlyton.com&#34;&gt;Cosplaying as a Sysadmin&lt;/a&gt;&lt;/em&gt; for quite some time which made me finally move to &lt;a href=&#34;https://nixos.org/&#34;&gt;NixOS&lt;/a&gt; from Arch (btw) over two years ago.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<blockquote>
<p><em>This post is part of <a href="/tags/nixjourney/">#nixjourney</a> series.</em></p>
</blockquote>
<p>Recently, I came across a blog post stating someone&rsquo;s reasons <a href="https://carlosbecker.com/posts/bye-nix/">to move away from nix</a> on his Mac where he maintains dotfiles using <a href="https://nixos.wiki/wiki/Home_Manager">Home Manager</a>. This made me think. Some points are valid: <code>/nix/store</code> is large (my desktop has <code>~267G</code> right now as I keep building for all hosts on my machine and have the tendency to never clean it up), quickly &ldquo;changing&rdquo; a hot key takes more time than editing the configuration file directly. Though, that cannot come as surprise, right? It&rsquo;s the trade off you make for being the new cool kid on the block (or reproducibility, easy rollback) and central management. It plays nicely together if you manage more than your dotfiles with nix, like <em>a lot</em> more. That&rsquo;s where nix shines. It&rsquo;s not supposed to <em>work for everyone</em>. If it doesn&rsquo;t work for you, that&rsquo;s totally fine. It does for me though. As you might now, I am <em><a href="https://www.jeffgeerling.com/blog/2022/cosplaying-sysadmin?ref=drewlyton.com">Cosplaying as a Sysadmin</a></em> for quite some time which made me finally move to <a href="https://nixos.org/">NixOS</a> from Arch (btw) over two years ago.</p>
<p>That post was the perfect motivation for me to continue the <a href="/tags/nixjourney/">#nixjourney</a> series.</p>
<hr>
<p>When I started looking around into NixOS documentation, some guides, starters, I really had no clue what was going on and how nice the final result would be. I&rsquo;ve learned a lot on the way. It took several months to migrate all hosts during my spare time.
In the beginning, I was confused about all the terms. I knew my goal and hoped that nix can deliver that, but why would there be different solutions? Nix, NixOS, Nix Flakes, Nix channels, home manager, and sops for secrets?!
Took some reading to get this sorted out, but when it was, I noticed flakes are actually what I want. To be honest, without flakes, I would have probably never fully switched to <em>&ldquo;nixify&rdquo;</em> my setup. Flakes give you a <code>.lock</code> file, similar to <code>package-lock.json</code> in node applications or alike. They exactly determine which versions and dependencies you&rsquo;ll get, but on an operating system level whereas Nix channels are more &ldquo;volatile&rdquo;, not providing the same guarantees. You definitely have more control with flakes and I would recommend everyone to go with flakes.</p>
<p>While researching to get a jump start, I thought it would be nice to learn by doing and having a solid base line I can extend, thus I started my journey by picking up <a href="https://github.com/Misterio77/nix-starter-configs">nix-starter-configs</a> [1]. Nix as language felt alien. Despite the fact that I know some functional programming, it was harder to get started and to write each line of code than I thought. In the beginning, I spent more on researching, reading, and asking than actually getting my setup done. In retrospective, the relatively complex starter didn&rsquo;t help either. It might have even confused me more. In all honesty, it was a brutal and steep learning curve to get basic things done. After a while though, results were reasonable. I started to enjoy how simple it was getting applications ready and fully configured through nix code/modules, no manual config tuning on any server afterward, that was huge! I also loved the implicit documentation it forces you to do. You&rsquo;re documenting your steps with git commits (or at least I did that). Your nix setup is a git repository, the same as with any other code. With this, you have all the benefits of versioning, but on an operating system level. Derivations force you to even add proper dependencies to any of your bash scripts which you&rsquo;ve likely put together late the other day and never touched them again. Furthermore, nix modules force you to structure your setup, add custom options, and enable dependencies to other modules properly by for example leveraging <code>lib.mkDefault</code>.</p>
<p>Instead of starting with my desktop machines to NixOS, I decided to move some of my VPS first. I kept the old ones still alive&hellip; in case I decide otherwise half way. Another reason behind this was that I didn&rsquo;t want to disrupt my daily routine yet. In the end of the day, it was experimenting and seeing how it goes, taking the safe route. I also knew that fully migrating all of my dotfiles and in addition my tiling window manager setup to nix would take more time than going with basic servers. The plan was simple. Iterate, move quickly, do mistakes, recover, and have No-Go&rsquo;s show up as early in the process as possible to evaluate if this is more than a prototype, something I want to keep. Turns out: Yes, I really want this to stay and never move back (hopefully or until something better comes up).</p>
<p>Even if something breaks (which actually never happened to me since I&rsquo;ve started using NixOS), having the ability to easily rollback by booting into the previous version feels like a huge step forward (each build/deploy creates a new, bootable generation which you can boot into when your machine comes up through normal means of your bootloader). Back then, I did encounter issues sometimes on my Arch machines with dependencies, or manual interventions were required which I then needed to repeat for all of my hosts which was annoying. I haven&rsquo;t seen this (until now) with my current NixOS setup.</p>
<h2 id="my-setup">My setup</h2>
<p>Let&rsquo;s directly jump into it. I currently manage eight hosts using NixOS. The entire setup is <em>&ldquo;nixified&rdquo;</em>, meaning that I don&rsquo;t add plain config files to a specific location, but instead use the provided modules or write them, though some scheme files are imported from plain text files.</p>
<p>The structure is something which evolved the more I added to my setup, still based on the initial base line I touched above.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln"> 1</span><span class="cl">├── commons
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">│   ├── modules     <span class="c1"># Opinionated modules (with my configuration)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">│   ├── presets     <span class="c1"># Opinionated presets for desktop, server etc., importing modules/ or snippets/</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│   └── snippets    <span class="c1"># Opinionated snippet options to directly use in imports (with my configuration)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── hosts           <span class="c1"># Host configuration, importing presets and specific host configuration</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│   ├── ando <span class="o">(</span>vps<span class="o">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│   ├── hoth <span class="o">(</span>vps<span class="o">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">│   ├── ilum <span class="o">(</span>laptop<span class="o">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│   ├── kuat <span class="o">(</span>vps<span class="o">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">│   ├── mantell <span class="o">(</span>home server<span class="o">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">│   ├── rion <span class="o">(</span>Raspberry Pi 3<span class="o">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">│   ├── ukio <span class="o">(</span>Raspberry Pi 4<span class="o">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">│   └── ziost <span class="o">(</span>desktop<span class="o">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">├── modules         <span class="c1"># Independent modules not provided by upstream</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">├── overlays        <span class="c1"># Overlays</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">└── pkgs            <span class="c1"># Derivations for custom packages</span></span></span></code></pre></div><p>The <code>commons/</code> folder contains opinionated nix files. This means that those represent my configuration or setup, like theming, keyboard shortcuts, or other settings usually wrapped into a custom module under <code>commons/modules/</code>. They typically use the <code>mkIf</code> guard pattern, meaning that I&rsquo;ve wrapped those opinionated settings by either leveraging the <code>.enable</code> upstream module option or one of my custom written modules (not present in upstream at all and located under <code>modules/</code>).</p>
<p>Here&rsquo;s an example for <em>btop</em> to apply my settings like the dracula theme.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">lib</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkIf</span> <span class="n">config</span><span class="o">.</span><span class="n">programs</span><span class="o">.</span><span class="n">btop</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">programs</span><span class="o">.</span><span class="n">btop</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">      <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="n">color_theme</span> <span class="o">=</span> <span class="s2">&#34;dracula&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="n">theme_background</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">      <span class="n">themes</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="c1"># ....</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>As you can see, if I now enable the <code>programs.btop.enable</code> anywhere in my config, I&rsquo;ll automatically get <strong>my</strong> settings.</p>
<p>Files inside the <code>presets/</code> folder import modules and set the enable option for them depending on a use case. I have a <code>desktop.nix</code> and a <code>server.nix</code>. This allows me to import a simple preset in my actual hosts file and then all my defaults are applied. If I need to overwrite any defaults for a host (when I don&rsquo;t need a specific module), I can simple set their module option to be disabled (or not import the preset at all).</p>
<p>The <code>snippets/</code> folder contains nix snippets which I tend to re-use often, but have no intention of modularizing them as they&rsquo;re so simple that I think they&rsquo;re not worth wrapping in an additional module and use the <code>import</code> directive instead. Here&rsquo;s an example of such a snippet.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># locale.nix</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="p">{</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="n">console</span><span class="o">.</span><span class="n">font</span> <span class="o">=</span> <span class="s2">&#34;Lat2-Terminus16&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="n">console</span><span class="o">.</span><span class="n">keyMap</span> <span class="o">=</span> <span class="s2">&#34;de-latin1-nodeadkeys&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>The <code>hosts/</code> folder contains files for my all my hosts. When adding a new host, I add a new folder, adapt my <code>flake.nix</code> to import it under a hostname and that&rsquo;s about it. This means I import a preset and a specific <code>hardware-configuration.nix</code> which is generated during install and some boilerplate code around users, Home Manager, and deployment (see below).</p>
<h2 id="secret-management">Secret management</h2>
<p>When you move to a nixified setup, you don&rsquo;t want any secret hard-coded in your nix files. Those would be tracked in your git or put into the nix store when you build. Instead, what you really want is proper secret management. There are some alternatives out there, but what has worked best for me is <a href="https://github.com/Mic92/sops-nix">sops-nix</a>. It&rsquo;s pretty flexible and supports secrets per host. You configure <code>yaml</code> file(s) for a host, edit them with the <code>sops</code> command, e.g., <code>sops ./hosts/mantell/secrets.yaml</code>. The result is asymmetrically encrypted against a sops key of your machine (or multiple ones) and the hosts machine (automatically derived from SSH setup for example, can also be done manually). It also works <em>per user</em> on a certain host. Pretty convenient. With this setup, you can reference any of your secret keys in your nix files.</p>
<p>Here&rsquo;s an example to secure a reverse proxy with basic auth.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">let</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">fqdn</span> <span class="o">=</span> <span class="s2">&#34;mydomain.tld&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">sops</span><span class="o">.</span><span class="n">secrets</span><span class="o">.</span><span class="n">nginx-basicauth-fqdn</span><span class="o">.</span><span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;nginx&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">services</span><span class="o">.</span><span class="n">nginx</span><span class="o">.</span><span class="n">virtualHosts</span><span class="o">.</span><span class="s2">&#34;</span><span class="si">${</span><span class="n">fqdn</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">locations</span><span class="o">.</span><span class="s2">&#34;/&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">            <span class="n">proxyPass</span> <span class="o">=</span> <span class="s2">&#34;http://127.0.0.1:</span><span class="si">${</span><span class="nb">toString</span> <span class="n">port</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s1">            auth_basic &#34;Protected&#34;;
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s1">            auth_basic_user_file </span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">sops</span><span class="o">.</span><span class="n">secrets</span><span class="o">.</span><span class="n">nginx-basicauth-fqdn</span><span class="o">.</span><span class="n">path</span><span class="si">}</span><span class="s1">;
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s1">            &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Notice that I&rsquo;ve leveraged the directive <code>auth_basic_user_file</code> from nginx directly. Most Nix options actually have a dedicated option to support files as secret inputs. If they only support an environment file, the sops YAML file can host the entire environment file as well. The only catch is that the underlying application needs to have a configuration option to get the necessary application secrets in. Most modern applications do or can be worked around with environment files. If they absolutely don&rsquo;t support that, I personally think it&rsquo;s worth requesting it from upstream. So, if you&rsquo;re an application developer, please consider directly supporting file secrets.</p>
<p><em>When you change receivers/keys for a secret file, make sure to update the keys with <code>sops updatekeys ./hosts/&lt;name&gt;/secrets.yaml</code>. Otherwise sops cannot decrypt that properly!</em></p>
<h2 id="building-and-deployment">Building and deployment</h2>
<p>To get the state of your nix files onto a machine, you need to build the nix generation, either on the host itself or &ldquo;deploy&rdquo; it from your local machine. For my desktop hosts, I directly build it locally with <code>sudo nixos-rebuild switch --flake .\#ziost</code> or instead of the <code>switch</code> the <code>boot</code> option to have it live on next reboot. This means that you need to have your Nix git repository on the machine, checkout the state you like to build, and execute the command above where <code>ziost</code> is one of my flake&rsquo;s configuration (desktop machine).</p>
<p>This works fine, but you might not want to go the same route with your servers. What I use instead is build the nix generation on my machine and then deploy it over SSH. For this, I set up <a href="https://github.com/serokell/deploy-rs">deploy-rs</a> in my <code>flake.nix</code> file for each host to define <em>how</em> I want to deploy, e.g., over SSH with a specific user on the remote machine and alike. Let&rsquo;s imagine I like to deploy the latest state for my server <code>ando</code>, then I&rsquo;d simply invoke <code> deploy .\#ando</code> on my machine in the git repository. <em>deploy-rs</em> sends over all necessary data and the server&rsquo;s updated with my desired state. This means that I build the nix generation on my machine first and send it over afterwards. It also gives you a lot of options how you want the deploy process to happen. You can also decide to build remotely instead.</p>
<h2 id="upgrading">Upgrading</h2>
<p>When I upgrade, I invoke <code>nix flake update</code> to update all defined inputs. This also updates the aforementioned <code>flake.lock</code> file.
Afterward, I build the toplevel target for all my hosts separately to see if it builds successfully before I move on into deploying that state. No worries though, <em>deploy-rs</em> would obviously not deploy something which does not build!</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># build a single target, replace &lt;host&gt; with the proper nix configuration (visible through nix flake show)</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">nix build .<span class="se">\#</span>nixosConfigurations.&lt;host&gt;.config.system.build.toplevel</span></span></code></pre></div><p>For a lot of hosts, this can get quite tedious to do. I use a one-liner to do it for all my defined hosts:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl">nix <span class="nb">eval</span> .<span class="se">\#</span>nixosConfigurations --raw --apply <span class="s1">&#39;c: builtins.concatStringsSep &#34;\n&#34; (builtins.attrNames c)&#39;</span><span class="p">|</span> xargs -I<span class="s1">&#39;{}&#39;</span> nix build .<span class="se">\#</span>nixosConfigurations.<span class="s1">&#39;{}&#39;</span>.config.system.build.toplevel --out-link result-<span class="s1">&#39;{}&#39;</span></span></span></code></pre></div><p>Looks scary, but you can put it into a shell alias or into a <a href="https://nixos.wiki/wiki/Development_environment_with_nix-shell#nix_develop">nix development shell for your nixos-config git repository</a>. It iterates over all defined nix configurations, builds them and stores it as <code>result-&lt;name&gt;</code>.</p>
<p>If that is successful, I deploy one by one as it really depends on the host when I want to do it.</p>
<p>There&rsquo;s also a way to visualize changes of nix generations, e.g., which packages have updates, with <a href="https://sr.ht/~khumba/nvd/">nvd</a>. What I do there is a) build the current generation, b) update nix flake, and lastly c) build the &ldquo;next&rdquo; generation, then compare with <code>nvd diff &lt;current&gt; &lt;next&gt;</code>.</p>
<p>I wrapped this into a little convenient script called <code>nvd-diff-prev-next</code>. Here&rsquo;s an example output when I call that for my VPS <code>ando</code>:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl">nix-shell-env ❯ nvd-diff-prev-next ando
</span></span><span class="line"><span class="ln">2</span><span class="cl">⚠️ Resetting lock file...
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="o">&lt;&lt;&lt;</span> result-ando-prev
</span></span><span class="line"><span class="ln">4</span><span class="cl">&gt;&gt;&gt; result-ando-next
</span></span><span class="line"><span class="ln">5</span><span class="cl">Version changes:
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="o">[</span>U.<span class="o">]</span>  <span class="c1">#01  linux              6.12.61, 6.12.61-modules x2, 6.12.61-modules-shrunk -&gt; 6.12.63, 6.12.63-modules x2, 6.12.63-modules-shrunk</span></span></span></code></pre></div><h2 id="os-releases">OS releases</h2>
<p>NixOS releases come out every six months, following a year and month versioning scheme (<code>25.05</code> and <code>25.11</code>). When this happens, some options you use might be deprecated or got replaced. I typically upgrade the flake input references, then invoke builds and see what breaks (if at all). For strict validation I tend to use <code>--abort-on-warn</code> for building the toplevel target such that even warnings or future deprecations are captured.</p>
<p>This release cycle sounds exhaustive, like you would need to change a lot every half year. In reality though, options are pretty stable, they have automatic migrations, and are usually backwards compatible, even introducing a deprecation / warning. For the past OS releases, my changes are on average 10-20 lines of code changed where most of them target deprecations which would still work fine.</p>
<h2 id="wrap-up">Wrap up</h2>
<p>Now with my setup explained, what made me ultimately move and commit to it?
Reproducibility, easy fallback to boot into a (previously working) generation. Versioning all my setups with git, sharing (configuration) code in one central place. And, lastly, declaring <em>what I want</em> instead of <em>changing what is provided to me as base</em> made me do the final switch. Without any exaggeration, it feels revolutionary when you&rsquo;ve fully moved to it. It also costs less time to maintain which was ultimately the goal of why I looked into alternatives in the first place. There are multiple tools out to have a similar feeling for non-declarative distributions (ansible, Puppet). None of them felt <em>right</em> to me though, more like a workaround. Nix is different in every aspect. It feels way more natural compared to the tools you plug in on top where this can be solved directly, not generating that &ldquo;alien feeling&rdquo; that it &ldquo;doesn&rsquo;t belong there&rdquo;.</p>
<p>Obviously, there are caveats. It&rsquo;s a trade off nevertheless. Despite giving you all the benefits and actually saving you time after the migration, the nix eco system can be a rabbit hole. It&rsquo;s code, your imagination is the limit on how you optimize your setup, where to improve, what to fine-tune, and how much time you spend with this. If you go too deep, then it might not be the time saver anymore, though it will stay fun nevertheless. It&rsquo;s really up to you to hold you back from over-optimizing and iterating too much over it than needed. 😅</p>
<p>For me personally, it worked out quite well, but it would be an unfair statement that I can recommend it to everyone. I think there&rsquo;s a clear audience for this: people willing to take the steep learning curve and people who value reproducibility, stability, and versioning for host setup. For a casual user, I think a standard GNU/Linux distribution will do way better. I think it would even scare people off showing them &ldquo;what is possible&rdquo;. Though, the moment you face maintaining a lot of hosts, it might be a fit for you. Remember, you decide <em>what exactly</em> you &ldquo;nixify&rdquo;. You don&rsquo;t need to &ldquo;nixify&rdquo; your entire setup including user configuration. You can also only have the base system &ldquo;nixified&rdquo;.</p>
<p>The next aspect I&rsquo;d like to personally dive deeper into is some automation around CI/CD and a (local network) cache for Nix. I can imagine that my homesever (<code>mantell</code>) regularly does some build tests, creates merge requests in my git repository and does automatically deploy the main branch to all of my hosts (at least servers). It can also leverage <code>nvd</code> to provide information what has been updated, on which host which version/generation is deployed and alike.</p>
<p>That&rsquo;s quite advanced, though it would even reduce the maintenance efforts further where I need to take action only if something breaks, I want to explicitly change something, or there&rsquo;s a new NixOS release. To be honest, I am not sure that I&rsquo;ll ever dive into that as I am quite happy about my current state.</p>
<p>What nix gave me is that it makes maintaining the hosts enjoyable again. It&rsquo;s not a burden, really. It&rsquo;s actually fun! Something I haven&rsquo;t felt for quite some time with the previous setups using other distributions (before you ask: reducing the number of hosts is not viable for me, I do I need them).</p>
<hr>
<p>1: FYI, I still use a modified version of it as my daily driver, but it <a href="https://github.com/Misterio77/nix-starter-configs/issues/86">might not be elegant or the most up-to-date starter</a> you should use. It does work fine for me over nearly 2.5 years and I have no intention on changing it as of now.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Distribute your Android apps through official channels</title>
      <link>https://varakh.de/blog/2025-09-14-apk-file-distribution/</link>
      <pubDate>Sun, 14 Sep 2025 23:08:21 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-09-14-apk-file-distribution/</guid>
      <description>&lt;p&gt;I use &lt;a href=&#34;https://www.musicpd.org/&#34;&gt;MPD&lt;/a&gt; a lot. It&amp;rsquo;s a small &lt;strong&gt;m&lt;/strong&gt;usic &lt;strong&gt;p&lt;/strong&gt;layer &lt;strong&gt;d&lt;/strong&gt;aemon, acting as a server providing modular access via a lot of clients to my local music hosted on my home server. It can directly output sound through the machine&amp;rsquo;s hardware or also through various other means, like over a network leveraging Pulseaudio&amp;rsquo;s remote networking features. This is what I use for my desktop machine. My home server outputs the stream directly to my desktop machine. Pretty convenient. Desktop usage is fine, even though one of the best MPD front‑ends, &lt;a href=&#34;https://github.com/CDrummond/cantata&#34;&gt;Cantata&lt;/a&gt;, is no longer maintained. But today I heard of &lt;a href=&#34;https://github.com/htkhiem/euphonica&#34;&gt;euphonica&lt;/a&gt;. It&amp;rsquo;s still an early preview version, but in my opinion MPD never had a better-looking front-end!&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I use <a href="https://www.musicpd.org/">MPD</a> a lot. It&rsquo;s a small <strong>m</strong>usic <strong>p</strong>layer <strong>d</strong>aemon, acting as a server providing modular access via a lot of clients to my local music hosted on my home server. It can directly output sound through the machine&rsquo;s hardware or also through various other means, like over a network leveraging Pulseaudio&rsquo;s remote networking features. This is what I use for my desktop machine. My home server outputs the stream directly to my desktop machine. Pretty convenient. Desktop usage is fine, even though one of the best MPD front‑ends, <a href="https://github.com/CDrummond/cantata">Cantata</a>, is no longer maintained. But today I heard of <a href="https://github.com/htkhiem/euphonica">euphonica</a>. It&rsquo;s still an early preview version, but in my opinion MPD never had a better-looking front-end!</p>
<p>Frankly, I’m not writing this to promote a desktop application or MPD itself, I am quite happy with it. Desktop usage is fine, but when it comes to mobile, things are different. Using Android/GrapheneOS as my daily driver (together with an old Raspberry Pi 3 serving as MPD proxy for playback through my AV receiver), I need a decent mobile client to control it. And there&rsquo;s really a lack of those. Back then, <a href="https://mafa.indi.software/">MAFA</a> was a massive improvement compared to the outdated <a href="https://f-droid.org/packages/org.gateshipone.malp/">M.A.L.P.</a> despite being closed-source. I still decided to use MAFA as my daily driver. Using closed-source applications does make me feel uncomfortable, but sometimes it&rsquo;s the price you need to pay. Unfortunate, but that&rsquo;s life.</p>
<p>Recently, the MAFA authors (Indi Software) removed their app from the official Play Store due to <a href="https://discourse.indi.software/t/availability-changes/221/5">questionable (or insufficient) reasoning</a>. Don&rsquo;t get me wrong, the new policies Google has put in place are not nice, but for such an app, there&rsquo;s not much to pay attention to except for <em>developer verification</em> which in my opinion was the whole point of Google introducing it so you can be called out if you smuggle unwanted behavior/malware. But people don&rsquo;t like change, so they take irrational decisions. The same happened with MAFA. It&rsquo;s now <em>only</em> available as direct <code>.apk</code> download 😱. Being closed-source, this is an absolute no-go for me. All applications on Android have network permission (what would you do with your phone otherwise?). They could do anything, execute whatever they want in the background without you noticing. That&rsquo;s an issue with closed-source apps in general, not specifically tied to how they&rsquo;re distributed, but the official distribution through stores (including open stores like Izzy or FDroid) gives some trust, applications are cross-checked (at least by Google for Play Store), but not with your side-loaded apk. When such things happen, you&rsquo;re exposed to the authors, trusting them way more than a closed-source application which is distributed through official channels.</p>
<p>Back to MAFA. A friend posted basically the explanation below on the announcement forum of the MAFA authors, asking and also explaining that no store as distribution is probably a bad idea, leading to distrust. Guess what happened. The MAFA authors (Indi Software) deleted that post within 15 minutes.</p>
<p>To be clear, releasing a mobile app outside of trusted app stores is highly risky and should be avoided at all costs. Both users and developers face significant security, trust, and usability problems when bypassing established distribution channels.</p>
<ul>
<li>Users downloading apps from unknown websites risk installing malware, spyware, or trojans disguised as legitimate apps.</li>
<li>Without Google Play, IzzyOnDroid, or F-Droid, there are no independent review processes or automated checks to catch malicious code.</li>
<li>Lack of regular updates through verified channels exposes users to unpatched vulnerabilities (or they can secretly point to another domain using their in-application updater).</li>
<li>If an app is only available via direct download (APK sideloading), many users immediately see it as suspicious.</li>
<li>Sideloading requires lowering a phone’s security settings, which most users associate with scams or hacked software.</li>
<li>Developers releasing apps this way damage credibility, as users expect apps to be available through legitimate, recognized stores - Play Store is not the only one.</li>
<li>Installing apps outside of app stores is confusing for non-technical users and creates unnecessary friction.</li>
</ul>
<p>Bypassing recognized stores undermines the app’s security, harms user confidence, and reduces usability. Developers who care about adoption, trust, and long-term sustainability should always release their apps through safe and transparent stores, whether proprietary (Google Play) or free/open (F-Droid, IzzyOnDroid).</p>
<p>MAFA is still by far the best Android MPD client, feel free to continue using it, but I cannot. I cannot trust closed-source applications where authors delete posts on their official forums and in addition don&rsquo;t give good reasoning why they went the route in the first place. It just creates a bad feeling for me, so I need to say <em>goodbye MAFA</em>, <em>goodbye Indi Software</em>, <em>hello M.A.L.P.</em> (again)!</p>
<hr>
<p>A side note: I personally maintain <a href="https://git.myservermanager.com/varakh/fbmobile">fbmobile</a> which I distribute through <a href="https://play.google.com/store/apps/details?id=de.varakh.fbmobile">Play Store</a> and <a href="https://apt.izzysoft.de/fdroid/index/apk/de.varakh.fbmobile/">IzzyOnDroid</a>. When Google started changing their policy, I had similar thoughts as the MAFA authors. Just removing it is the easy way and seems legit, given that Google is that evil big tech giant, enforcing their new policy for <em>everyone</em>. To be honest, that wouldn&rsquo;t be too bad for my application. It was just removing <em>one</em> of my distribution channels and not forcing people to install plain apk files. They could still decide to install via <a href="https://apt.izzysoft.de/fdroid/">IzzyOnDroid</a>.
When thinking about the <em>&ldquo;why&rdquo;</em> Google <em>probably</em> introduced it, I suddenly reverted my initial plan. That developers are forced to be authentic and that they can be held liable to a certain degree is actually quite beneficial from my perspective. Don&rsquo;t get me wrong. I don&rsquo;t like this as a developer. It creates additional work, but as user I prefer that developers need to go through this verification process.</p>
<p>Google&rsquo;s move also seems to pay off. Since the new policies have been introduced, I am regularly (like at least weekly) receiving mails from folks that they want to buy my legitimate Google developer account. I guess they need to find new ways to distribute their shady software.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Fixing everything</title>
      <link>https://varakh.de/blog/2025-09-03-curse-of-knowing/</link>
      <pubDate>Wed, 03 Sep 2025 23:00:29 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-09-03-curse-of-knowing/</guid>
      <description>&lt;p&gt;Came across &lt;a href=&#34;https://notashelf.dev/posts/curse-of-knowing&#34;&gt;&lt;em&gt;&amp;ldquo;The Curse of Knowing How, or; Fixing Everything&amp;rdquo;&lt;/em&gt;&lt;/a&gt; yesterday. Author captures it pretty well. Give it a read!&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Came across <a href="https://notashelf.dev/posts/curse-of-knowing"><em>&ldquo;The Curse of Knowing How, or; Fixing Everything&rdquo;</em></a> yesterday. Author captures it pretty well. Give it a read!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reflection on self-hosting</title>
      <link>https://varakh.de/blog/2025-09-03-reflection-on-self-hosting/</link>
      <pubDate>Wed, 03 Sep 2025 22:47:16 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-09-03-reflection-on-self-hosting/</guid>
      <description>&lt;p&gt;Precise reflection on self-hosting and in which rabbit holes you fall on &lt;a href=&#34;https://www.drewlyton.com/story/the-future-is-not-self-hosted/&#34;&gt;drewlyton.com&lt;/a&gt;. Would love to see more community based &amp;ldquo;clouds&amp;rdquo;, though I don&amp;rsquo;t share the enthusiasm nor the notion that libraries would be the best place.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Precise reflection on self-hosting and in which rabbit holes you fall on <a href="https://www.drewlyton.com/story/the-future-is-not-self-hosted/">drewlyton.com</a>. Would love to see more community based &ldquo;clouds&rdquo;, though I don&rsquo;t share the enthusiasm nor the notion that libraries would be the best place.</p>
]]></content:encoded>
    </item>
    <item>
      <title>History - Journey to NixOS Part I</title>
      <link>https://varakh.de/blog/2025-05-02-nix-journey-part1/</link>
      <pubDate>Fri, 02 May 2025 00:00:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-05-02-nix-journey-part1/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;This post is part of &lt;a href=&#34;https://varakh.de/tags/nixjourney/&#34;&gt;#nixjourney&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;For over two decades, I&amp;rsquo;ve been an avid GNU/Linux user (&lt;em&gt;&amp;ldquo;Yes, I&amp;rsquo;m that old&amp;rdquo;&lt;/em&gt; 🦕).&lt;/p&gt;&#xA;&lt;p&gt;My first encounter with Linux happened in my teens. Fueled by curiosity about alternative tech, I sought options beyond Windows, the only OS I knew back then. This was the era of screeching modems and dial-up internet connections.&lt;/p&gt;&#xA;&lt;p&gt;It started with Ubuntu 04.10 (&lt;em&gt;&amp;ldquo;Warty Warthog&amp;rdquo;&lt;/em&gt;). The experience was&amp;hellip; rough. Hardware support was spotty, key features didn&amp;rsquo;t work, and I quickly abandoned it. Yet something stuck: the terminal&amp;rsquo;s raw power and Linux&amp;rsquo;s different aesthetic intrigued me, even as basic functionality failed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<blockquote>
<p><em>This post is part of <a href="/tags/nixjourney/">#nixjourney</a> series.</em></p>
</blockquote>
<p>For over two decades, I&rsquo;ve been an avid GNU/Linux user (<em>&ldquo;Yes, I&rsquo;m that old&rdquo;</em> 🦕).</p>
<p>My first encounter with Linux happened in my teens. Fueled by curiosity about alternative tech, I sought options beyond Windows, the only OS I knew back then. This was the era of screeching modems and dial-up internet connections.</p>
<p>It started with Ubuntu 04.10 (<em>&ldquo;Warty Warthog&rdquo;</em>). The experience was&hellip; rough. Hardware support was spotty, key features didn&rsquo;t work, and I quickly abandoned it. Yet something stuck: the terminal&rsquo;s raw power and Linux&rsquo;s different aesthetic intrigued me, even as basic functionality failed.</p>
<p>Two years later, I tried again. <em>What a difference!</em> Out-of-the-box hardware support, GNOME2&rsquo;s polished interface, and stability made it a viable Windows replacement for my aging machine, except for gaming. Linux gaming then was a nightmare, so I kept a dual-boot setup.</p>
<p>Ubuntu became my daily driver for years, though I remained a surface-level user. When everything worked, I was content. When it broke, often due to my reckless config file experiments, I struggled to fix it. My limited understanding of Linux fundamentals turned minor issues into multi-day research projects. I was totally fine being an average user, but tinkering with it was fun, just my lack of knowledge was not. Quickly, those early struggles became lessons: understanding fundamentals and its architecture. When time went by, I became more experienced and I noticed that I needed more. I needed a more bare bones experience where I am <em>forced</em> to learn and deal with everything on my own, a system from scratch.</p>
<p>I did a little bit of distro hopping, but ultimately ended up with <a href="https://archlinux.org/">Arch Linux</a>. The learning curve was very steep coming from the clicky Ubuntu experience. I spent days, weeks, and months reading its (fantastic!) wiki. It felt like a huge achievement when I got my first installation working (and many more would follow). I also noticed that my knowledge got a huge bump. Everything felt familiar, I was getting way better at how internals work, why I initially was right that <code>apt</code> with its PPAs is super inconvenient compared to <code>pacman</code>. I enjoyed every little bit of my new knowledge and the experience I had. Among these, the beauty of <a href="https://aur.archlinux.org/">AUR</a>, the freedom to have an unbloated system nobody pre-installs software I don&rsquo;t want. That&rsquo;s how digital freedom feels. I was finally there where I wanted to be.
Very quickly I became a super user. Tiling window manager, command-line first. It was also super convenient to code (what I already did for a couple of years). I enjoyed it so much that Arch Linux has been my main driver for over 15 years, even maintaining some AUR packages myself.</p>
<p>Over the last three years of my Arch experience, a strange feeling haunted me though. Confident, that I knew already a lot, as I&rsquo;ve also managed some servers and more than just one personal device running Arch, I still had that feeling: <em>This cannot be the end of my GNU/Linux journey</em>. I always enjoyed new tech. I was curious about alternatives and out of sheer curiosity and by pure accident for further acceleration and evolvement, I stumbled upon something called NixOS as it tackled one of my main pain points when I was managing multiple devices.</p>
<p>Arch is great for bleeding-edge software, but keeping configurations consistent across my growing amount of devices like laptops, servers, and arm-powered computers quickly became a headache and time consuming. I needed a tool or OS which <em>actually</em> requires <em>less</em> time. More automation, more configuration sharing, and a convenient way to bootstrap a fresh machine in a matter of minutes (reproducible). With my personal discovery of <a href="https://nixos.org/">NixOS</a> through IRC (<em>&ldquo;yep, still old&rdquo;</em> 🦖), it seemed like a perfect match as other config management tools didn&rsquo;t align well with me personally. I had an &ldquo;alien&rdquo; feeling when looking at <a href="https://www.puppet.com/">puppet</a>, <a href="https://www.redhat.com/en/ansible-collaborative">ansible</a>, or alike. I was seeking a piece of software which feels &ldquo;native&rdquo;, embedded into the concepts of an OS and not an addition which works around some quirks.</p>
<h4 id="moving-from-arch-linux-to-nixos-simplifying-multi-device-maintenance">Moving from Arch Linux to NixOS: Simplifying Multi-Device Maintenance</h4>
<p>After years of managing multiple devices with Arch Linux, I switched to NixOS and it has been a game changer. NixOS uses <strong>declarative configuration</strong>, meaning you define your entire system setup in configuration files (<code>configuration.nix</code>). This lets you:</p>
<ul>
<li>Reproduce identical setups across devices</li>
<li>Roll back updates atomically if something breaks</li>
<li>Avoid dependency conflicts with isolated package environments</li>
</ul>
<p>With NixOS, provisioning a new machine is as simple as cloning your config repo and running <code>nixos-rebuild  switch --flake .\#target</code>. You can maintain:</p>
<ul>
<li>Host-specific hardware configs</li>
<li>Shared services like SSH and monitoring</li>
<li>User environments with tools like <a href="https://github.com/nix-community/home-manager">Home Manager</a></li>
</ul>
<p>This approach eliminates configuration drift and turns system maintenance into a version-controlled, repeatable process.</p>
<p>Nix&rsquo;s functional language took some getting used to, but the benefits, safe testing, managing multiple software versions, and automating updates-are worth it. If you manage more than a couple of Linux devices, NixOS&rsquo;s declarative model saves time and headaches. It&rsquo;s not just a distro, it&rsquo;s a new way to manage systems reliably and at scale.</p>
<p><em>Next up in the <a href="/tags/nixjourney/">#nixjourney</a> series: exploring my setup where I manage around 9 devices leveraging <a href="https://nixos.wiki/wiki/flakes">Nix flakes</a>.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>If it&#39;s too complex, kill it</title>
      <link>https://varakh.de/blog/2025-05-01-get-rid-of-complexity/</link>
      <pubDate>Thu, 01 May 2025 00:00:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-05-01-get-rid-of-complexity/</guid>
      <description>&lt;p&gt;When coding - whether professionally or as a hobby - you&amp;rsquo;ve likely found yourself staring at your work thinking:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;What the hell did I write there?&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Or worse: the code was written by someone else. You&amp;rsquo;re not alone. This frustration stems from how codebases evolve. Features get added quickly, hotfixes are rushed to production, and contributions accumulate. Gradually, your once-readable code becomes a tangled mess.&lt;/p&gt;&#xA;&lt;p&gt;You might think: &lt;em&gt;&amp;ldquo;just add comments&amp;rdquo;&lt;/em&gt;. &lt;strong&gt;Don&amp;rsquo;t.&lt;/strong&gt; Heavy reliance on inline comments to explain logic often signals code that needs refactoring. Exceptions exist - method documentation and complex algorithm explanations are valid, but verbose step-by-step comments usually mask unclear code.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When coding - whether professionally or as a hobby - you&rsquo;ve likely found yourself staring at your work thinking:</p>
<blockquote>
<p><em>&ldquo;What the hell did I write there?&rdquo;</em></p>
</blockquote>
<p>Or worse: the code was written by someone else. You&rsquo;re not alone. This frustration stems from how codebases evolve. Features get added quickly, hotfixes are rushed to production, and contributions accumulate. Gradually, your once-readable code becomes a tangled mess.</p>
<p>You might think: <em>&ldquo;just add comments&rdquo;</em>. <strong>Don&rsquo;t.</strong> Heavy reliance on inline comments to explain logic often signals code that needs refactoring. Exceptions exist - method documentation and complex algorithm explanations are valid, but verbose step-by-step comments usually mask unclear code.</p>
<p>Programming languages and frameworks are precise by design. There&rsquo;s no room for interpretation. We&rsquo;re engineers, we&rsquo;ll understand it. While documentation, onboarding, and experience help us understand code, <strong>complexity remains the ultimate barrier</strong> though. Simple code is inherently easier to understand, extend, and maintain. The less complex your code is, the better you and others will understand (and extend and maintain) it.</p>
<p>I&rsquo;ll try to share my thoughts on <em>complexity</em>:</p>
<blockquote>
<p>Rather prioritize clarity over cleverness, and you&rsquo;ll build systems that stand the test of time.</p>
</blockquote>
<h4 id="abstraction-layers">Abstraction layers</h4>
<p>Does your code need to be <em>that</em> complex?</p>
<p>I&rsquo;ve seen this pattern repeatedly and still fall into the trap myself. We over-engineer solutions because they&rsquo;re &ldquo;clever&rdquo; or &ldquo;future-proof,&rdquo; adding layers like &ldquo;X might need this later.&rdquo; But ask yourself:</p>
<ul>
<li>Will X ever actually happen?</li>
<li>What&rsquo;s the real cost of maintaining these abstractions today?</li>
<li>Couldn&rsquo;t you add them <em>when</em> they&rsquo;re needed?</li>
</ul>
<p>If your answer is &ldquo;Yes, I can live without it now,&rdquo; <strong>delete that complexity immediately</strong>. Future-proofing often becomes future-burdening.</p>
<p>Example?</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="ln">1</span><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">interface</span> <span class="nc">MyEndpoint</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">    </span><span class="n">PostResponse</span><span class="w"> </span><span class="nf">createPost</span><span class="p">(</span><span class="n">CreatePostRequest</span><span class="w"> </span><span class="n">post</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">MyRestEndpoint</span><span class="w"> </span><span class="kd">implements</span><span class="w"> </span><span class="n">MyEndpoint</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="n">PostResponse</span><span class="w"> </span><span class="nf">createPost</span><span class="p">(</span><span class="nd">@Valid</span><span class="w"> </span><span class="nd">@RequestBody</span><span class="w"> </span><span class="n">CreatePostRequest</span><span class="w"> </span><span class="n">post</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">        </span><span class="c1">// some logic to create the post in a service</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>This Java example looks pretty straight forward, right? Well, it&rsquo;s clean, no doubt. But why do we need an interface here? Do you <em>really</em> anticipate to add more implementations to create a post in your small back-end in addition to the RESTful way? No? <em>Kill it.</em></p>
<blockquote>
<p>Don&rsquo;t over-do interfaces or abstractions. Introduce them when <em>necessary</em>.</p>
</blockquote>
<p>That was quite an easy example. It gets worse when you see entire applications being introduced just for the sake of abstraction. Step back, think about it twice if it&rsquo;s really serving any benefit despite fulfilling your engineer&rsquo;s dream.</p>
<h4 id="dependencies">Dependencies</h4>
<p>We all love and hate them. We love them because they eliminate the need to write code yourself. Just plug in that tool, and it handles everything without requiring a single line of custom code. We hate them when they break or demand maintenance.</p>
<p><strong>Don&rsquo;t reinvent the wheel</strong>, but for every dependency you add, ask:</p>
<ul>
<li>Is this worth the long-term maintenance cost for the 50 lines of code it saves?</li>
<li>Does its quality and complexity justify the added hassle for your team?</li>
<li>Is it rigorously tested and aligned with your coding standards?</li>
<li>Does it introduce necessary complexity, or just bloat?</li>
</ul>
<p>If the answer is no to any of these: <em>Kill it.</em></p>
<p>Derived from this, it should be common sense, but here&rsquo;s <em>why you should never add unused dependencies</em>. Adding unused dependencies to your project is a major no-go. They introduce unnecessary security risks, increase code bloat, slow down builds, and create extra maintenance overhead. Even if you&rsquo;re &ldquo;preparing for something&rdquo;, unused dependencies expand your attack surface and complicate your codebase without delivering any real benefit.</p>
<p>To keep your software lean, secure, and efficient, always remove dependencies you don&rsquo;t actively use. Regular cleanup helps prevent vulnerabilities, reduces build times, and makes your project easier to maintain. Remember: less is more when it comes to dependencies! It&rsquo;s about <em>reducing</em>, not adding complexity.</p>
<h4 id="shared-code">Shared code</h4>
<p>Code duplication remains a hotly debated topic in software development, balancing the need for flexibility against long-term maintainability.</p>
<p>While the &ldquo;Don&rsquo;t Repeat Yourself&rdquo; (DRY) rule is foundational, blind adherence can lead to over-engineering. Short, stable code snippets or temporary prototypes might justify duplication, but uncontrolled copying creates technical debt through inconsistent logic and hidden bugs.</p>
<p>Adhering to the following <em>might</em> help balance it for you:</p>
<ol>
<li>Libraries:
<ul>
<li>Best for: Stable, widely-used utilities.</li>
<li>Pros: Single source of truth for shared code.</li>
<li>Cons: High maintenance overhead, poor fit for volatile code.</li>
</ul>
</li>
<li>Git submodules:
<ul>
<li>Best for: Large, semi-stable dependencies (e.g., shared API clients).</li>
<li>Pros: Atomic updates, separation of concerns.</li>
<li>Cons: IDE tooling challenges, might feel &ldquo;alien&rdquo; compared to a library.</li>
</ul>
</li>
<li>Plain copy:
<ul>
<li>Best for: Experimental features or highly contextual logic.</li>
<li>Pros: Zero abstraction cost, isolated changes.</li>
<li>Cons: Manual synchronization, version drift risks, actual duplication.</li>
</ul>
</li>
</ol>
<p>When choosing an approach, inspect expected <strong>change frequency</strong> (libraries for low-churn code, copies for high-churn), <strong>cross-project use</strong> (libraries/submodules for shared code, copies for project-specific needs), and <strong>team expertise</strong> (submodules require more Git mastery while libraries demand more packaging skills).</p>
<p>If you find yourself duplicating code, ensure to track origins with comments, as description of a git message or document it externally with proper reasoning. As a rule of thumb, abstracting at the third duplication might serve useful to avoid complexity. In my opinion, the real danger lies not in duplication itself, but in unmanaged duplication. If you (and everyone who needs to) know where code requires synchronization, is it an issue by itself?</p>
<h4 id="tooling">Tooling</h4>
<p>Modern development offers endless tools to &ldquo;simplify&rdquo; configuration management, deployments, and workflows, but each new addition introduces complexity. Are you using tools to solve problems, or just creating new ones?</p>
<p>Ask yourself:</p>
<ul>
<li>Do these tools overlap? If three utilities handle similar tasks (e.g., YAML templating), you&rsquo;re likely maintaining redundant abstractions.</li>
<li>Are they worth the learning curve? A &ldquo;magic&rdquo; deployment CLI might save time initially, but obscure errors and tribal knowledge will haunt your team later. Rather solve it with <a href="https://en.wikipedia.org/wiki/KISS_principle">KISS</a> being very explicit about each tool used and its purpose.</li>
<li>Can you debug without them? If a tool obscures the underlying process (e.g., abstracting Docker into a proprietary layer), you lose visibility when things break.</li>
</ul>
<p>Audit your toolchain. Remove underused tools, consolidate overlapping ones, and favor transparency over &ldquo;black-box&rdquo; solutions. Hot take, but sometimes, a well-documented shell script beats a bloated framework.</p>
<h4 id="cicd-complexity">CI/CD complexity</h4>
<p>When building modern applications, you&rsquo;ll typically rely on a pipeline to handle building, testing, and shipping your code. Whether you use GitHub Actions, Jenkins, or other tools, <em>be mindful of the complexity your pipeline introduces</em>. If maintaining it becomes a burden, it&rsquo;s likely too complex!</p>
<p>Avoid letting your DevOps team dictate which tools you <em>must</em> use. Don&rsquo;t work around artificial limitations - implement CI/CD in a way that aligns with the application&rsquo;s requirements and expected environment. As the domain expert, you possess the deepest understanding of your application&rsquo;s requirements and operational needs - knowledge your DevOps team might lack. Collaborate rather than circumvent. You and your DevOps colleagues share the same objectives: rapid, reliable, and automated delivery. Try to keep it simple. If there&rsquo;s (nearly) zero difference between developing, building locally, and shipping a production artifact, then you&rsquo;re spot on!</p>
<h4 id="simplify-releases">Simplify releases</h4>
<p>Releases shouldn&rsquo;t require code changes! Automate version bumps and changelogs instead. Use <a href="https://www.conventionalcommits.org">conventional commits</a> (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>) to auto-generate release notes directly from your commit messages. Tools like <a href="https://git-cliff.org/">git-cliff</a> do the rest. This means cleaner, faster releases, fewer mistakes, and everything&rsquo;s auditable. Stop manually updating versions and doing all the merge backs – automate it!</p>
<h4 id="writing-less-complex-applications-or-why-12-factor-apps-matter">Writing less complex applications or why 12 Factor Apps matter</h4>
<p>If you&rsquo;re like me and have wrestled with messy deployments or &ldquo;works on my machine&rdquo; bugs, the <a href="https://12factor.net/">12 Factor App</a> methodology is a game changer. It lays out simple, practical best practices for building cloud-native apps that are scalable, maintainable, and resilient.</p>
<p>By standardizing how you handle code, dependencies, configs, and processes, it cuts down on complexity and those frustrating environment-specific issues. Plus, it encourages building stateless, easily deployable services that scale smoothly and bounce back quickly from failures.</p>
<p>In my experience, embracing these principles not only makes your life easier but also helps your team deliver reliable software faster. It&rsquo;s all about working smarter, not harder, and keeping things simple where it counts.</p>
<h4 id="conclusion-coding-with-clarity">Conclusion: Coding with clarity</h4>
<p>This article emphasizes applying practical judgment to reduce unnecessary complexity in your codebase. Being practical and having a <em>feeling</em> for it often comes with experience.</p>
<ul>
<li>Resist over-engineering: Don&rsquo;t let abstract ideals dictate your design – solve the core problem first.</li>
<li>Iterate strategically: Add complexity only when requirements demand it, not as a preemptive measure.</li>
<li>Legacy code can be changed: While greenfield projects benefit most upfront, apply these principles incrementally to existing systems for most value to historically grown code base.</li>
</ul>
<p>By prioritizing simplicity, you&rsquo;ll ship faster, improve maintainability, and create code that&rsquo;s easier to onboard others to. Over time, refactoring replaces accidental complexity with robust, resilient systems.</p>
<p>The best code solves problems, not just theoretical puzzles.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Flakes for production and development</title>
      <link>https://varakh.de/blog/2025-04-27-flakes-for-production-and-development/</link>
      <pubDate>Sun, 27 Apr 2025 00:00:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-04-27-flakes-for-production-and-development/</guid>
      <description>&lt;p&gt;Recently, I took a deeper look into &lt;a href=&#34;https://nixos.wiki/wiki/flakes&#34;&gt;Nix flakes&lt;/a&gt;. I won&amp;rsquo;t go into detail about basics in this blog post. To be ready to understand when reading further, I assume some developer experience and also some basic NixOS knowledge, thus don&amp;rsquo;t expect an introduction to &lt;a href=&#34;https://nixos.wiki/wiki/flakes&#34;&gt;flakes&lt;/a&gt; or &lt;code&gt;nix&lt;/code&gt;/NixOS itself.&lt;/p&gt;&#xA;&lt;p&gt;Still with me? Perfect. During my research, I was particular interested how to leverage them as build tool, if they can have an impact on development workflows, and reproducibility during the usual engineering cycle. I&amp;rsquo;d like to share my experience during my experiments.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently, I took a deeper look into <a href="https://nixos.wiki/wiki/flakes">Nix flakes</a>. I won&rsquo;t go into detail about basics in this blog post. To be ready to understand when reading further, I assume some developer experience and also some basic NixOS knowledge, thus don&rsquo;t expect an introduction to <a href="https://nixos.wiki/wiki/flakes">flakes</a> or <code>nix</code>/NixOS itself.</p>
<p>Still with me? Perfect. During my research, I was particular interested how to leverage them as build tool, if they can have an impact on development workflows, and reproducibility during the usual engineering cycle. I&rsquo;d like to share my experience during my experiments.</p>
<p>Kinda in reverse order, starting with the conclusion: <strong>This is fantastic, why did I miss that before?! They have a huge potential to accelerate development workflows, boost reproducibility and make our engineering lives easier.</strong> Wherever possible, I am going to push for it, at least for my small private projects. Though, I am unsure if they should be a first-class citizen for everything. Gradually changing existing build processes and development flows can be quite time consuming. For new projects it might be worth a try though. Also, I have no experience how this works out in distributed teams with members using that Micro*** OS (which should work just fine).</p>
<h3 id="development-workflow">Development workflow</h3>
<p>Collaborating with peers or on your personal projects can be cumbersome when these projects require <em>a lot</em> of different tooling. Maybe you&rsquo;re a front-end developer, some projects use <code>yarn</code>, some <code>pnpm</code>, some are still on Node 20, and some are on recent Node LTS already. When frequently switching between (very different) projects, you&rsquo;ll likely end up with a lot of tools on your <code>PATH</code> or some kind of <em>tool to manage those tools</em>. Just to cover every project. Version conflicts might pop up, specific combinations don&rsquo;t work, or worse, you need to manually dive into bootstrapping tools just for specific projects, adjusting what&rsquo;s on your <code>PATH</code> or in your environment and change every time.</p>
<p>I learned that there&rsquo;s really no need to. When I came across <code>direnv</code> (and it&rsquo;s actually quite popular for some time), I noticed for myself: <em>You did it wrong all the time</em>.
Instead of preparing my operating system for the projects I work on, the projects should prepare my OS/configuration for me to work on them.</p>
<p>The combination of <code>direnv</code> with <a href="https://nixos.wiki/wiki/flakes">flakes</a> is convenient. Probably no other stack can provide similar guarantees to have identical and reproducible development and production (more on that later) setups.</p>
<p>How does it work? How can we get the same experience on any machine with <code>nix</code> installed without messing up our <code>PATH</code> or installing tools to manage tools?</p>
<p>We&rsquo;ll use <a href="https://nixos.wiki/wiki/flakes">flakes</a> in conjunction with a tool called <code>direnv</code> (or better the improved nix variant <a href="https://github.com/nix-community/nix-direnv"><code>nix-direnv</code></a> which can handle the <code>use flake</code> directive). We&rsquo;ll not go into details how you can set them up properly, but <a href="https://nix-community.github.io/home-manager/">home manager</a> makes it easy to get started on your machine.</p>
<p>Once required tools are ready (<code>nix</code> and <code>nix-direnv</code>/<code>direnv</code>), let&rsquo;s dive deeper into our new project which we call <em>myapp</em> which resides on our disk at <code>~/Workspaces/myapp/</code>. We plan to have bootstrap a static site generator project with <a href="https://gohugo.io/">gohugo</a>.</p>
<h5 id="bootstrap-your-project-using-nix-flakes">Bootstrap your project using nix flakes</h5>
<p>Everything (good) begins with a <code>flake.nix</code> file in the root project folder. It defines the environment we like to set up once we change directory into the project folder with the so called <code>devShells</code> (development shells).</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># flake.nix</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;A basic flake with a dev shell&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  <span class="n">inputs</span><span class="o">.</span><span class="n">nixpkgs</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nixos/nixpkgs/nixos-24.11&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  <span class="n">inputs</span><span class="o">.</span><span class="n">systems</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nix-systems/default&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="n">inputs</span><span class="o">.</span><span class="n">flake-utils</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:numtide/flake-utils&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">systems</span><span class="o">.</span><span class="n">follows</span> <span class="o">=</span> <span class="s2">&#34;systems&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">  <span class="n">outputs</span> <span class="o">=</span> <span class="p">{</span> <span class="n">nixpkgs</span><span class="o">,</span> <span class="n">flake-utils</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">flake-utils</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">eachDefaultSystem</span> <span class="p">(</span><span class="n">system</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="k">let</span> <span class="n">pkgs</span> <span class="o">=</span> <span class="n">nixpkgs</span><span class="o">.</span><span class="n">legacyPackages</span><span class="o">.</span><span class="si">${</span><span class="n">system</span><span class="si">}</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">      <span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="n">devShells</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">          <span class="n">pkgs</span><span class="o">.</span><span class="n">mkShell</span> <span class="p">{</span> <span class="n">packages</span> <span class="o">=</span> <span class="p">[</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">hugo</span> <span class="p">];</span> <span class="p">};</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">      <span class="p">});</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>We also need a <code>.envrc</code> file with <code>use flake</code> as content.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># .envrc</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">use flake</span></span></code></pre></div><p>Let&rsquo;s create a lock file. It controls the flake versions we get for any dependency. Invoke <code>nix flake lock</code> which creates a <code>flake.lock</code> file. Make sure to version control it. I also recommend adding <code>.direnv</code> to your <code>.gitignore</code>.</p>
<p>Let&rsquo;s go back to our application. We want to create a web site which uses the static site generator <a href="https://gohugo.io/">gohugo</a>. Obviously, we need the <code>hugo</code> binary. Usually, you would download it or install it into your <code>PATH</code>. You also need to think about updating it periodically. <strong>Not anymore!</strong> Everything&rsquo;s ready to use with our flake definition <code>packages = [ pkgs.hugo ]</code>. Change directory into <code>~/Workspaces/myapp</code>. If you allow <code>direnv</code> to be invoked (it will ask for it), then you should see an indicator in your shell. <code>hugo</code> is available. You can start using it as it would be globally on your <code>PATH</code>.</p>
<p>This is how it could look like:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl">direnv: loading ~/Workspaces/myapp/.envrc
</span></span><span class="line"><span class="ln">2</span><span class="cl">direnv: using flake
</span></span><span class="line"><span class="ln">3</span><span class="cl">direnv: nix-direnv: Using cached dev shell
</span></span><span class="line"><span class="ln">4</span><span class="cl">direnv: <span class="nb">export</span> +AR +AS +CC +CONFIG_SHELL +CXX +HOST_PATH +IN_NIX_SHELL +LD +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_BUILD_CORES +NIX_CC +NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_CFLAGS_COMPILE +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_LDFLAGS +NIX_STORE +NM +OBJCOPY +OBJDUMP +RANLIB +READELF +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +__structuredAttrs +buildInputs +buildPhase +builder +cmakeFlags +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +dontAddDisableDepTrack +mesonFlags +name +nativeBuildInputs +out +outputs +patches +phases +preferLocalBuild +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH ~XDG_DATA_DIRS
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">~/Workspaces/myapp master*
</span></span><span class="line"><span class="ln">7</span><span class="cl">nix-shell-env ❯ which hugo
</span></span><span class="line"><span class="ln">8</span><span class="cl">/nix/store/5h5q5jjr64chslxp4qwjqn86vzc1ybj5-hugo-0.136.5/bin/hugo</span></span></code></pre></div><p>What we&rsquo;ve achieved: an environment based on the directory you&rsquo;re in. If you have <em>a lot of projects</em>, switching environments has never been easier. No mess on your <code>PATH</code> anymore. The project decides what you need and what <em>everyone</em> gets.</p>
<p>Even if you only have few projects to work on, using this method (maybe we call it git native flakes repository?) makes it easy for anyone to get started. Your environment is &ldquo;inside your directory&rdquo; and automatically started. You can add any <a href="https://search.nixos.org/packages">nix package</a> to it, even specific Python dependencies, Ruby, or specific versions of NodeJS and npm, e.g., with <code>packages = [ pkgs.nodejs_20 pkgs.pnpm_9 ];</code>.</p>
<p>Key takeaways from this section:</p>
<ul>
<li>Use <a href="https://nixos.wiki/wiki/flakes">flakes</a> to manage your required environments and easily switch between them through convenience feature of <code>direnv</code> (<code>nix-direnv</code>)</li>
<li><em>Identical</em> development setup for everyone</li>
<li>Easy to get started, just needs <code>nix</code> and <code>nix-direnv</code>/<code>direnv</code> on the system</li>
<li>Easy to maintain and upgrade with <code>nix flake update</code> (and look into nix&rsquo; <code>inputs</code> to follow nix releases) and everyone gets the new required environment once they change into a project&rsquo;s directory</li>
<li>Huge time saver: you don&rsquo;t need to update your dependencies on your system for all the different tools you need. The flake is doing it for you and for everyone else involved in your project as well</li>
</ul>
<p>The static web site example is kinda simple and might not capture what you&rsquo;re looking for. It also doesn&rsquo;t cover the power of flakes, though it clearly shows that you can easily set up required environment/packages through <a href="https://nixos.wiki/wiki/flakes">flakes</a> which are then used as development shells using <em>direnv</em>. Any developer in your team only needs to properly set up <code>nix</code> as package manager and have <code>direnv</code> installed. <em>&ldquo;It works on my machine&rdquo;</em> is no excuse anymore. If it works on your machine, it will work on production (and vice versa), because we&rsquo;ll make production artifacts leverage our <a href="https://nixos.wiki/wiki/flakes">flakes</a> as well.</p>
<h3 id="packaging-and-shipping">Packaging and shipping</h3>
<p>Packaging and shipping your application to production is mostly done as container image or natively. Let&rsquo;s touch on the container approach first.</p>
<p>You might be familiar that <code>Dockerfile</code> container images can be quite tedious to create in the first place (<code>... AS builder</code>) to avoid unnecessary layers. It gets worse when we think about long-term maintenance and horrible when we talk about security. You often end up with stuff in your image you actually don&rsquo;t need. Also, your development setup is likely different, right? Some packages from a repository of your operating system or maybe you&rsquo;ve just downloaded that binary and put it into your <code>PATH</code> and now it simply <em>&ldquo;works&rdquo;</em>? And a peer wrote this pipeline with some other versions. Still works? But, should it <em>&ldquo;work&rdquo;</em> like that? The answer to that question is probably <em>no, it should not, we should do better</em>.</p>
<p>If you think about container images, you most likely want to use <code>FROM scratch</code> to reduce unnecessary bloat and attack surface. The issue with only adding your stuff to the image (even with builder) falls short the moment you require different types of linking and libraries. It becomes a mess to manage. Then, your next choice might be <code>FROM alpine</code>.</p>
<p>Compared to scratch images, we can achieve similar results with <a href="https://nixos.wiki/wiki/flakes">flakes</a>. We already have our <code>flake.nix</code> file in the project&rsquo;s root directory and use it for our local development setup. Let&rsquo;s enhance that to build an example Go application a container image from that binary.</p>
<p>Here&rsquo;s the full <code>flake.nix</code>:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;A basic flake with a dev shell&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">nixpkgs</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nixos/nixpkgs/nixos-24.11&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">systems</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nix-systems/default&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">flake-utils</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:numtide/flake-utils&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="n">inputs</span><span class="o">.</span><span class="n">systems</span><span class="o">.</span><span class="n">follows</span> <span class="o">=</span> <span class="s2">&#34;systems&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">  <span class="n">outputs</span> <span class="o">=</span> <span class="p">{</span> <span class="n">nixpkgs</span><span class="o">,</span> <span class="n">flake-utils</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">flake-utils</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">eachDefaultSystem</span> <span class="p">(</span><span class="n">system</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">      <span class="k">let</span> <span class="n">pkgs</span> <span class="o">=</span> <span class="n">nixpkgs</span><span class="o">.</span><span class="n">legacyPackages</span><span class="o">.</span><span class="si">${</span><span class="n">system</span><span class="si">}</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">      <span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">packages</span> <span class="o">=</span> <span class="k">rec</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">          <span class="n">default</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">buildGoModule</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">            <span class="n">pname</span> <span class="o">=</span> <span class="s2">&#34;myapp&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">            <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;latest&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="n">pwd</span> <span class="o">=</span> <span class="sr">./.</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="n">src</span> <span class="o">=</span> <span class="sr">./.</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">CGO_ENABLED</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="c1"># input actual hash by building once locally</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="n">vendorHash</span> <span class="o">=</span> <span class="s2">&#34;sha256-AAAA&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">          <span class="p">};</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">          <span class="n">container</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">dockerTools</span><span class="o">.</span><span class="n">buildImage</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">            <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;myapp&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">            <span class="n">tag</span> <span class="o">=</span> <span class="s2">&#34;latest&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">            <span class="n">created</span> <span class="o">=</span> <span class="s2">&#34;now&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">            <span class="n">copyToRoot</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">buildEnv</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">              <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;image-root&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">              <span class="n">paths</span> <span class="o">=</span> <span class="p">[</span> <span class="n">default</span> <span class="p">];</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">              <span class="n">pathsToLink</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;/bin&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="p">};</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">            <span class="n">config</span><span class="o">.</span><span class="n">Cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">default</span><span class="si">}</span><span class="s2">/bin/myapp&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">          <span class="p">};</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="n">devShells</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">          <span class="n">pkgs</span><span class="o">.</span><span class="n">mkShell</span> <span class="p">{</span> <span class="n">packages</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">[</span> <span class="n">go</span> <span class="p">];</span> <span class="p">};</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">      <span class="p">});</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Run <code>nix build</code> to build the native application (it defaults to target <code>default</code>). It will be placed into a <code>result/</code> folder. Make sure you also add this directory/file to your <code>.gitignore</code>.</p>
<p>To build your container image, invoke <code>nix build .#container</code>. It will automatically build the defined <code>default</code> package and use it. Then, import it into your image registry with <code>docker load &lt; result</code> (or <code>podman</code>) to make it available for further usage.</p>
<p>For one of my projects, I gave it a shot. It currently uses the <code>AS builder</code> approach and the main container image is derived with <code>FROM alpine</code>. Compared to the traditional way, the produced image by nix <a href="https://nixos.wiki/wiki/flakes">flakes</a> is only ~71% in size.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl">❯ podman image ls
</span></span><span class="line"><span class="ln">2</span><span class="cl">REPOSITORY                           IMAGE ID      SIZE
</span></span><span class="line"><span class="ln">3</span><span class="cl">git.myservermanager.com/varakh/upda  0925c69fcf0f  48.8 MB
</span></span><span class="line"><span class="ln">4</span><span class="cl">withnixflakes/varakh/upda            e574f8840f1d  34.9 MB</span></span></code></pre></div><h3 id="reproducibility">Reproducibility</h3>
<p>When you first invoke <code>nix build</code>, you&rsquo;ll see that it complains about a mismatched <code>vendorHash</code>. You can paste the proposed hash of the output into the <code>flake.nix</code> file. Subsequent invocations then succeed. If you don&rsquo;t change your application afterward, outputs stay the same, thus the hash stays the same. Locally and on any build pipeline. If you&rsquo;ve missed updating the hash, then your build fails. Transposing such a produced artifact through your different development, staging and production environments is pretty straight forward (just remember to use the <em>load</em> command above). Certainly, there are some benefits we&rsquo;ve gained with this:</p>
<ul>
<li>The artifact is 100% identical when you build it, independent of your environment (due to the hash).</li>
<li>The flake&rsquo;s lock file ensures development and production gets the same tooling.</li>
<li><code>direnv</code>/<code>nix-direnv</code> provides a convenient way to develop your application on any machine.</li>
<li>Produced (container image) artifacts are smaller in size compared to the traditional way with your <code>Dockerfile</code>, thus they implicitly reduce attack surface. There&rsquo;s no 3rd party dependency in your image. No alpine, no ubuntu. You&rsquo;re not bound to upstream changes. It&rsquo;s like the <code>FROM scratch</code> approach, but way easier to get started and to maintain.</li>
</ul>
<h3 id="build-pipeline">Build pipeline</h3>
<p>When switching to <code>nix</code> (flakes) as primary build and development tool, your pipeline needs to change. Good news is, that you only need <code>nix</code> and enable flake usage with <code>NIX_CONFIG=experimental-features = nix-command flakes</code> there. Not more. Pretty straight forward and the same as locally.</p>
<p>Bad news is, that you might encounter increased disk space usage due to the nix building steps. Make sure that pipeline executors are deleted or at least clean up their nix store periodically. Furthermore, to do this at large scale (and I don&rsquo;t have any experience with that), you probably want add your own nix cache to avoid downloading everything all over again.</p>
<h5 id="trying-this-out-in-my-ecosystem">Trying this out in my ecosystem</h5>
<p>For all my private project, I use <a href="https://forgejo.org/">Forgejo</a> and their <a href="https://forgejo.org/docs/latest/admin/runner-installation/">runner concept</a>. Depending on a <em>label</em> you select, a runner picks up a job and executes it after you&rsquo;ve registered it to your instance. These labels are prefixed with <code>docker</code>, <code>host</code>, or alike. From these labels, they derive the environment they execute the pipeline in.</p>
<p>What we need is a &ldquo;nix&rdquo; runner then. As all of my machines are on NixOS, that&rsquo;s pretty straight forward. I set up a new <a href="https://forgejo.org/docs/latest/admin/runner-installation/#nixos">Forgejo Runner on NixOS</a> with <a href="https://nixos.wiki/wiki/NixOS_Containers">NixOS Containers</a> to ensure they&rsquo;re isolated.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="n">containers</span><span class="o">.</span><span class="n">gitea-runner</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="n">networking</span><span class="o">.</span><span class="n">hostName</span> <span class="o">=</span> <span class="s2">&#34;my-native-runners&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="n">environment</span><span class="o">.</span><span class="n">systemPackages</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">[</span> <span class="p">];</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">      <span class="n">services</span><span class="o">.</span><span class="n">gitea-actions-runner</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="n">package</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">forgejo-actions-runner</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">instances</span><span class="o">.</span><span class="n">native-runner</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">          <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">          <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;runner-container&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">          <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://forgejo.domain.tld&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">          <span class="n">labels</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;native-container:host&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">          <span class="n">hostPackages</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">            <span class="n">bash</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">            <span class="n">coreutils-full</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">            <span class="n">curl</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="n">gawk</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="n">gcc</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">gitMinimal</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">gnumake</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="n">gnused</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">            <span class="n">gnutar</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">            <span class="n">gzip</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">            <span class="n">nix</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">            <span class="n">nix-direnv</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">            <span class="n">podman</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">            <span class="n">wget</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">          <span class="p">];</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">          <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">            <span class="n">log</span> <span class="o">=</span> <span class="p">{</span> <span class="n">level</span> <span class="o">=</span> <span class="s2">&#34;info&#34;</span><span class="p">;</span> <span class="p">};</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="n">runner</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">              <span class="n">capacity</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">              <span class="n">timeout</span> <span class="o">=</span> <span class="s2">&#34;1h&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">              <span class="n">insecure</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">              <span class="n">fetch_timeout</span> <span class="o">=</span> <span class="s2">&#34;10s&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">              <span class="n">fetch_interval</span> <span class="o">=</span> <span class="s2">&#34;10s&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">            <span class="p">};</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">            <span class="n">cache</span> <span class="o">=</span> <span class="p">{</span> <span class="n">enabled</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span> <span class="p">};</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">          <span class="p">};</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">      <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">&#34;24.11&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Then, with the applications git repository already having the <code>flake.nix</code>, we need to change the step definition the runner executes in the <code>build.yaml</code> workflow file:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">  </span><span class="nt">push</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">    </span><span class="nt">branches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">      </span>- <span class="l">master</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">  </span><span class="nt">pull_request</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span><span class="nt">types</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">opened, synchronize, reopened ]</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">  </span><span class="nt">build</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">native-container</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v3</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Checkout</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build and test</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">        </span><span class="nt">shell</span><span class="p">:</span><span class="w"> </span><span class="l">bash</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">        </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="sd">          nix build
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="sd">          nix build .#container</span></span></span></code></pre></div><hr>
<p>Let me know what you think. The aspects of reproducibility, developer convenience, reducing attack surface, and the simplicity in pipelines are really convincing to me. As I don&rsquo;t have the setup running for a long time, I cannot derive any conclusion on maintenance costs yet, but at least from a complexity perspective it seems to just &ldquo;bump the flake&rdquo; with <code>nix flake update</code> and adapt it if changed. But you only need to do that once, not distributed in all your build tools and (local) environments.</p>
<p><em>Side note: If you don&rsquo;t want to dive into <a href="https://nixos.wiki/wiki/flakes">nix flakes</a> and its ecosystem entirely, you&rsquo;re probably missing out on something very cool, but nevertheless, <code>direnv</code> plays nicely for other directives like <code>dotenv</code> in your <code>.envrc</code> which ensures that environment variables from a project&rsquo;s <code>.env</code> file are available once you enter the project&rsquo;s directory. This could already provide value to automate and start your projects in seconds. No more tinkering with your environment.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Reviving the blog</title>
      <link>https://varakh.de/blog/2025-04-16-reviving-the-blog/</link>
      <pubDate>Wed, 16 Apr 2025 00:00:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2025-04-16-reviving-the-blog/</guid>
      <description>&lt;p&gt;Let&amp;rsquo;s be honest. This is probably my hundredth blog revival. I don&amp;rsquo;t fully understand why I keep returning to it, only to let it stall, gather dust, or even take it offline entirely. There&amp;rsquo;s something magnetic about this space that keeps pulling me back, even when logic suggests I shouldn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;p&gt;Years ago, this blog was a digital journal - raw, personal, and unpolished. But during my 2019 revival, I tried to change: English-language mostly politics in bite-sized posts. Short. Frankly, too much ranting, useless, and very opinionated. 😀&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Let&rsquo;s be honest. This is probably my hundredth blog revival. I don&rsquo;t fully understand why I keep returning to it, only to let it stall, gather dust, or even take it offline entirely. There&rsquo;s something magnetic about this space that keeps pulling me back, even when logic suggests I shouldn&rsquo;t.</p>
<p>Years ago, this blog was a digital journal - raw, personal, and unpolished. But during my 2019 revival, I tried to change: English-language mostly politics in bite-sized posts. Short. Frankly, too much ranting, useless, and very opinionated. 😀</p>
<p>The initial shift came from discomfort. Sharing intimate life details online started feeling invasive. Privacy concerns drove that initial topic switch, but the bigger question lingered: <em>Why keep blogging at all?</em></p>
<p>For those who want some nostalgic feelings when they see that my blog is live again, I&rsquo;m afraid I need to let you down. <strong>I won&rsquo;t be picking up any posts from my very old blog</strong>, which was in German, though I still have a database dump named <code>slimblog_db_all_plus_new_from_jekyll.sql</code> flying around here. Scrolling through them was fun! 😊</p>
<p>When looking at my last blog post, it seems I wasn&rsquo;t that happy about the vote on net neutrality. Maybe that&rsquo;s the reason I stopped - or at least I didn&rsquo;t want to report anything.</p>
<h2 id="the-unshakable-urge">The Unshakable Urge</h2>
<p>The answer lies in an itch I can&rsquo;t stop scratching - the need to share (tech) ideas and thoughts that matter. Looking back at my 2019 posts with brutal honesty? I missed the mark entirely. This time, I&rsquo;m chasing more substance. Less &ldquo;another dude&rsquo;s hot take,&rdquo; more posts worth your time.</p>
<p>This space needs to serve two masters now. It should be a reflection tool for my own growth, yet useful enough to justify your attention. The industry is fast, I&rsquo;m constantly bombarded with tech ideas or discoveries in daily life I want to try out - things I can&rsquo;t simply let go and I feel the urge to share as they&rsquo;re pretty cool. Writing helps me sharpen these thoughts while (hopefully) helping others. Every post forces me to organize. But balance remains elusive. Past attempts prove this: My switch to English political posts in 2019 became less analysis, more ranting. Opinions evolve, lives change, and what felt urgent then, now reads like digital graffiti.</p>
<p>Here&rsquo;s to new beginnings (again and with <a href="https://gohugo.io/">hugo</a> instead of <a href="https://jekyllrb.com/">jekyll</a>). Let&rsquo;s see how long this one lasts. My goal is to create engaging and more insightful content that could help you. Stay tuned for contents focusing on software, development, engineering, coding, and computer science topics. Feel free to let me know if you want me to tailor this for a specific topic.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Please, don&#39;t abolish our net neutrality</title>
      <link>https://varakh.de/blog/2019-04-05-abolish-net-neutrality/</link>
      <pubDate>Fri, 05 Apr 2019 00:00:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2019-04-05-abolish-net-neutrality/</guid>
      <description>&lt;p&gt;After the recent vote in the European parliament and the passing of article 13 (article 17) German (political) institutes seem to continue with their bullshit.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.computerbase.de/2019-04/vodafone-1-1-.-verlangen-gema/&#34;&gt;The portal boerse.* is now being blocked by German internet providers Vodafone and 1&amp;amp;1&lt;/a&gt;, because the German GEMA, an institute which &amp;ldquo;represents&amp;rdquo; artists, forced them to. Besides the &amp;ldquo;zero traffic&amp;rdquo; mobile streaming offered by the Telekom and by Vodafone, this the first time providers really don&amp;rsquo;t care too much.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>After the recent vote in the European parliament and the passing of article 13 (article 17) German (political) institutes seem to continue with their bullshit.</p>
<p><a href="https://www.computerbase.de/2019-04/vodafone-1-1-.-verlangen-gema/">The portal boerse.* is now being blocked by German internet providers Vodafone and 1&amp;1</a>, because the German GEMA, an institute which &ldquo;represents&rdquo; artists, forced them to. Besides the &ldquo;zero traffic&rdquo; mobile streaming offered by the Telekom and by Vodafone, this the first time providers really don&rsquo;t care too much.</p>
<p>Which site&rsquo;s next? I&rsquo;d vote for <em>cdu.de</em> for all users of the Telekom. We need to stop this. Now! 😀</p>
<p>PS: Fortunately, every German institute is very unskilled when it comes down to digital strategies and their implementation. Just change your DNS which is responsible for assigning web pages to IP address so your browser can connect. I encourage you to use the DNS servers of <a href="https://digitalcourage.de/support/zensurfreier-dns-server">Digitalcourage e.V.</a> anyway.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Block EU users</title>
      <link>https://varakh.de/blog/2019-04-02-block-eu-users/</link>
      <pubDate>Tue, 02 Apr 2019 00:00:00 +0200</pubDate>
      <guid>https://varakh.de/blog/2019-04-02-block-eu-users/</guid>
      <description>&lt;p&gt;Unfortunately, first rumors come up that major platforms, e.g., &lt;a href=&#34;https://www.twitch.tv/videos/392340867&#34;&gt;twitch&lt;/a&gt;, consider blocking &lt;em&gt;all&lt;/em&gt; European users from their content due to article 13 (article 17) of the new EU directive. If that&amp;rsquo;s the case those responsible will sooner or later realize what they&amp;rsquo;ve done to digital development and citizenship in Europe. Supporting digital development is already not a priority number one and now we&amp;rsquo;re actively blocking it on purpose.&#xA;I really hope that enough global players jump on the bandwagon so that this will be a major disruption in citizens daily life. Maybe this will change something, end the conservative reign and we finally start to focus on our future.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Unfortunately, first rumors come up that major platforms, e.g., <a href="https://www.twitch.tv/videos/392340867">twitch</a>, consider blocking <em>all</em> European users from their content due to article 13 (article 17) of the new EU directive. If that&rsquo;s the case those responsible will sooner or later realize what they&rsquo;ve done to digital development and citizenship in Europe. Supporting digital development is already not a priority number one and now we&rsquo;re actively blocking it on purpose.
I really hope that enough global players jump on the bandwagon so that this will be a major disruption in citizens daily life. Maybe this will change something, end the conservative reign and we finally start to focus on our future.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reda resigned</title>
      <link>https://varakh.de/blog/2019-03-29-reda-resigned/</link>
      <pubDate>Fri, 29 Mar 2019 00:00:00 +0100</pubDate>
      <guid>https://varakh.de/blog/2019-03-29-reda-resigned/</guid>
      <description>&lt;p&gt;Julia Reda resigned from her political party &amp;ldquo;Piratenpartei&amp;rdquo; yesterday. What a pity, I think she did a fantastic job to enlighten many political dinosaurs and citizens of the EU.&lt;/p&gt;&#xA;&lt;p&gt;She also advised to &lt;em&gt;not&lt;/em&gt; vote for &amp;ldquo;Piratenpartei&amp;rdquo; on the 25th of May. For whom shall we vote then?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Julia Reda resigned from her political party &ldquo;Piratenpartei&rdquo; yesterday. What a pity, I think she did a fantastic job to enlighten many political dinosaurs and citizens of the EU.</p>
<p>She also advised to <em>not</em> vote for &ldquo;Piratenpartei&rdquo; on the 25th of May. For whom shall we vote then?</p>
]]></content:encoded>
    </item>
    <item>
      <title>Intellij improvement for versioning</title>
      <link>https://varakh.de/blog/2019-03-28-intellij-improvement-for-versioning/</link>
      <pubDate>Thu, 28 Mar 2019 00:00:00 +0100</pubDate>
      <guid>https://varakh.de/blog/2019-03-28-intellij-improvement-for-versioning/</guid>
      <description>&lt;p&gt;I use git as my everyday companion to support me while developing. What really struck me was the latest improvement JetBrains did to their git integration. If there are new commits available this is indicated by a small little blue icon now. Nice visual helper available in version &lt;em&gt;2019.01&lt;/em&gt;. No need to context switch into another terminal or program.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I use git as my everyday companion to support me while developing. What really struck me was the latest improvement JetBrains did to their git integration. If there are new commits available this is indicated by a small little blue icon now. Nice visual helper available in version <em>2019.01</em>. No need to context switch into another terminal or program.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Lesser bugs</title>
      <link>https://varakh.de/blog/2019-03-28-lesser-bugs/</link>
      <pubDate>Thu, 28 Mar 2019 00:00:00 +0100</pubDate>
      <guid>https://varakh.de/blog/2019-03-28-lesser-bugs/</guid>
      <description>&lt;p&gt;Recently I&amp;rsquo;ve experienced some bugs related to my machines. Intellij didn&amp;rsquo;t close dialog windows. This has been so annoying and I don&amp;rsquo;t like the idea to exclude packages, but I had to. Now this is finally fixed with my compositor upgrade. If you&amp;rsquo;re using &lt;a href=&#34;https://github.com/yshui/compton/releases&#34;&gt;compton&lt;/a&gt;, be sure you have version &lt;code&gt;6.2&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently I&rsquo;ve experienced some bugs related to my machines. Intellij didn&rsquo;t close dialog windows. This has been so annoying and I don&rsquo;t like the idea to exclude packages, but I had to. Now this is finally fixed with my compositor upgrade. If you&rsquo;re using <a href="https://github.com/yshui/compton/releases">compton</a>, be sure you have version <code>6.2</code>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Internet provider unstable</title>
      <link>https://varakh.de/blog/2019-03-27-provider-inconsistency/</link>
      <pubDate>Wed, 27 Mar 2019 00:00:00 +0100</pubDate>
      <guid>https://varakh.de/blog/2019-03-27-provider-inconsistency/</guid>
      <description>&lt;p&gt;Today&amp;rsquo;s the third time in four days my Internet is offline or unstable because of ISP issues. This really starts to suck, especially when you&amp;rsquo;re trying to do some home office. Let me explain which Internet options citizens can book here in Germany. We basically only have two larger companies which provide decent speeds ranging from ~50MBit/s to 400MBit/s and together with kinda fair prices. They share the same cable network for that. Telephone line connection sucks **** here at my location, so I&amp;rsquo;ll not consider that. Situation might be different at any other location. Normally they just provide speeds up to 16MBit/s to 50MBit/s which is the de factor standard for many households not using cable and way too slow for more advanced usage. If you book 50MBit/s there&amp;rsquo;s still no guarantee that you&amp;rsquo;ll actually get this speed, but you surely have to pay for it. 🤑&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Today&rsquo;s the third time in four days my Internet is offline or unstable because of ISP issues. This really starts to suck, especially when you&rsquo;re trying to do some home office. Let me explain which Internet options citizens can book here in Germany. We basically only have two larger companies which provide decent speeds ranging from ~50MBit/s to 400MBit/s and together with kinda fair prices. They share the same cable network for that. Telephone line connection sucks **** here at my location, so I&rsquo;ll not consider that. Situation might be different at any other location. Normally they just provide speeds up to 16MBit/s to 50MBit/s which is the de factor standard for many households not using cable and way too slow for more advanced usage. If you book 50MBit/s there&rsquo;s still no guarantee that you&rsquo;ll actually get this speed, but you surely have to pay for it. 🤑</p>
<p>So, either way: cable, unstable with &ldquo;high speed&rdquo; or slow robust DSL. What a choice.</p>
]]></content:encoded>
    </item>
    <item>
      <title>EU decision making</title>
      <link>https://varakh.de/blog/2019-03-26-eu-decision-making/</link>
      <pubDate>Tue, 26 Mar 2019 00:00:00 +0100</pubDate>
      <guid>https://varakh.de/blog/2019-03-26-eu-decision-making/</guid>
      <description>&lt;p&gt;Wow, unbelievable decision making with regards to article 13, feels like a &lt;a href=&#34;http://clusterfuck.urbanup.com/298891&#34;&gt;clusterfuck&lt;/a&gt;, initiated by &lt;a href=&#34;https://twitter.com/AxelVossMdEP&#34;&gt;this single guy&lt;/a&gt;. What a drop in trust and potential loss of at least one political generation interested in digital. They&amp;rsquo;ll surely enjoy the vote on the 25th of May. Hope you guys don&amp;rsquo;t miss out on that (&lt;a href=&#34;https://twitter.com/hashtag/niewiedercdu&#34;&gt;#niewiedercdu&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;The good thing is: the sheer amount of participants who protested &amp;hellip; astonishing.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Wow, unbelievable decision making with regards to article 13, feels like a <a href="http://clusterfuck.urbanup.com/298891">clusterfuck</a>, initiated by <a href="https://twitter.com/AxelVossMdEP">this single guy</a>. What a drop in trust and potential loss of at least one political generation interested in digital. They&rsquo;ll surely enjoy the vote on the 25th of May. Hope you guys don&rsquo;t miss out on that (<a href="https://twitter.com/hashtag/niewiedercdu">#niewiedercdu</a>).</p>
<p>The good thing is: the sheer amount of participants who protested &hellip; astonishing.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Imprint</title>
      <link>https://varakh.de/imprint/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://varakh.de/imprint/</guid>
      <description>&lt;p&gt;Responsible according to para. 5 TMG (Telemediengesetz – Tele Media Act by German law):&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://varakh.de/images/imprint.svg&#34; alt=&#34;imprint&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The content of our website has been compiled with meticulous care and to the best of our knowledge. However, we cannot assume any liability for the up-to-dateness, completeness or accuracy of any of the pages.&lt;/p&gt;&#xA;&lt;p&gt;Pursuant to section 7, para. 1 of the TMG, we as service providers are liable for our own content on these pages in accordance with general laws. However, pursuant to sections 8 to 10 of the TMG, we as service providers are not under obligation to monitor external information provided or stored on our website. Once we have become aware of a specific infringement of the law, we will immediately remove the content in question. Any liability concerning this matter can only be assumed from the point in time at which the infringement becomes known to us.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Responsible according to para. 5 TMG (Telemediengesetz – Tele Media Act by German law):</p>
<p><img src="/images/imprint.svg" alt="imprint"></p>
<p>The content of our website has been compiled with meticulous care and to the best of our knowledge. However, we cannot assume any liability for the up-to-dateness, completeness or accuracy of any of the pages.</p>
<p>Pursuant to section 7, para. 1 of the TMG, we as service providers are liable for our own content on these pages in accordance with general laws. However, pursuant to sections 8 to 10 of the TMG, we as service providers are not under obligation to monitor external information provided or stored on our website. Once we have become aware of a specific infringement of the law, we will immediately remove the content in question. Any liability concerning this matter can only be assumed from the point in time at which the infringement becomes known to us.</p>
<h3 id="limitation-of-liability-for-external-links">Limitation of liability for external links</h3>
<p>Our website contains links to the websites of third parties (&ldquo;external links&rdquo;). As the content of these websites is not under our control, we cannot assume any liability for such external content. In all cases, the provider of information of the linked websites is liable for the content and accuracy of the information provided. At the point in time when the links were placed, no infringements of the law were recognisable to us. As soon as an infringement of the law becomes known to us, we will immediately remove the link in question.</p>
<h3 id="copyright">Copyright</h3>
<p>The content and works published on this website are governed by the copyright laws of Germany. Any duplication, processing, distribution or any form of utilisation beyond the scope of copyright law shall require the prior written consent of the author or authors in question.</p>
<h3 id="data-protection">Data protection</h3>
<p>A visit to our website can result in the storage on our server of information about the access (date, time, page accessed). This does not represent any analysis of personal data (e.g., name, address or e-mail address). If personal data are collected, this only occurs - to the extent possible - with the prior consent of the user of the website. Any forwarding of the data to third parties without the express consent of the user shall not take place.</p>
<p>We would like to expressly point out that the transmission of data via the Internet (e.g., by e-mail) can offer security vulnerabilities. It is therefore impossible to safeguard the data completely against access by third parties. We cannot assume any liability for damages arising as a result of such security vulnerabilities.</p>
<p>The use by third parties of all published contact details for the purpose of advertising is expressly excluded. We reserve the right to take legal steps in the case of the unsolicited sending of advertising information; e.g., by means of spam mail.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
