<?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>Nix on Haseeb Majid</title>
    <link>https://haseebmajid.dev/tags/nix/</link>
    <description>Recent content in Nix on Haseeb Majid</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Fri, 12 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://haseebmajid.dev/tags/nix/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How to Fix PAM Issues With Home Manager on Non-NixOS Setups</title>
      <link>https://haseebmajid.dev/posts/2025-12-12-how-to-fix-pam-issues-with-home-manager-on-non-nixos-setups/</link>
      <pubDate>Fri, 12 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2025-12-12-how-to-fix-pam-issues-with-home-manager-on-non-nixos-setups/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
The pam_shim is POC code, so be careful with using it on your own machine. Use it at your own risk.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;
&lt;p&gt;At work I have to use Ubuntu but I want to share my nix config between all my devices i.e. desktop and work laptop.
On my home setup I have been using Niri with Noctalia shell (quickshell) on NixOS. Everything works fine I can use
the Noctalia shell lock screen and can authenticate fine.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<blockquote>
<p>[!WARNING]
The pam_shim is POC code, so be careful with using it on your own machine. Use it at your own risk.</p>
</blockquote>
<h2 id="the-problem">The problem</h2>
<p>At work I have to use Ubuntu but I want to share my nix config between all my devices i.e. desktop and work laptop.
On my home setup I have been using Niri with Noctalia shell (quickshell) on NixOS. Everything works fine I can use
the Noctalia shell lock screen and can authenticate fine.</p>
<p>However when I tried to do that on my Ubuntu machine, it wouldn&rsquo;t let me log back in after locking the screen.
Remember everything is installed via Nix (home-manager).</p>
<h3 id="pam">PAM</h3>
<p>PAM is Linux&rsquo;s standard authentication framework. When you lock your screen and type your password, PAM handles the
authentication logic. It&rsquo;s called &ldquo;pluggable&rdquo; because system administrators can configure different authentication
methods (passwords, fingerprints, smart cards) without modifying applications.</p>
<h3 id="pam--nix">PAM &amp; Nix</h3>
<p>Nix packages are completely self-contained. When you install a package with Nix, it includes all its dependencies in <code>/nix/store/</code>.
But this creates a problem with PAM:</p>
<p>NixOS</p>
<pre tabindex="0"><code>Application → /nix/store/xxx-linux-pam/lib/libpam.so.2
           → /nix/store/yyy-pam-modules/lib/security/pam_unix.so
           → /etc/pam.d/ (managed by NixOS)
           → Authenticate ✅
</code></pre><p>Ubuntu</p>
<pre tabindex="0"><code>Application → /nix/store/xxx-linux-pam/lib/libpam.so.2
           → /nix/store/yyy-pam-modules/lib/security/pam_unix.so (doesn&#39;t exist!)
           → /etc/pam.d/ (managed by Ubuntu, expects different paths)
           → Authentication FAILS ❌
</code></pre><p>So we are locked out &ldquo;forever&rdquo; until we reboot, obviously not great. I know I hit this issue before with Hyprland
and hyprlock (or swaylock) and ended up installing them via apt and not Nix. But this time I wanted to avoid
doing that. I came across this <a href="https://github.com/nix-community/home-manager/issues/7027">issue</a>.</p>
<h2 id="solution">Solution</h2>
<p>We can use <code>pam_shim</code>, which creates a translation layer we can use. Whilst not breaking Nix&rsquo;s package isolation.</p>
<ol>
<li>
<p><strong>PAM Shim Library</strong>: <code>pam-shim</code> creates a wrapper library that intercepts PAM calls and redirects them to the host system&rsquo;s PAM library (<code>/lib/x86_64-linux-gnu/libpam.so.0</code> on Ubuntu)</p>
</li>
<li>
<p><strong>Patching</strong>: The <code>replacePam</code> function uses <code>patchelf</code> to replace PAM library references in the QuickShell binary with the shim library</p>
</li>
<li>
<p><strong>Runtime</strong>: When noctalia-shell&rsquo;s lock screen tries to authenticate:</p>
<ul>
<li>QuickShell calls PAM functions</li>
<li>Calls go through the shim library</li>
<li>Shim redirects to Ubuntu&rsquo;s native PAM</li>
<li>Authentication works against Ubuntu&rsquo;s PAM stack</li>
</ul>
</li>
</ol>
<pre tabindex="0"><code>QuickShell → pam_shim intercepts pam_authenticate()
        → fork() subprocess
        → exec /lib64/ld-linux-x86-64.so.2 (system dynamic linker)
        → loads /lib/x86_64-linux-gnu/libpam.so.0 (Ubuntu&#39;s native PAM)
        → reads /etc/pam.d/common-auth (Ubuntu&#39;s PAM config)
        → loads /lib/x86_64-linux-gnu/security/pam_unix.so (Ubuntu&#39;s PAM module)
        → checks /etc/shadow (system password database)
        → returns PAM_SUCCESS via IPC to pam_shim
        → pam_shim returns result to QuickShell
        → Authentication SUCCEEDS ✅
</code></pre><h2 id="fix">Fix</h2>
<p>update <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="cl"><span class="c1"># PAM shim for non-NixOS systems</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Using &#39;next&#39; branch for full libpam.so.0 API coverage</span>
</span></span><span class="line"><span class="cl"><span class="n">pam-shim</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:Cu3PO42/pam_shim/next&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span><span class="o">.</span><span class="n">nixpkgs</span><span class="o">.</span><span class="n">follows</span> <span class="o">=</span> <span class="s2">&#34;nixpkgs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">inputs</span><span class="o">.</span><span class="n">pam-shim</span><span class="o">.</span><span class="n">homeModules</span><span class="o">.</span><span class="n">default</span>
</span></span></code></pre></div><p>In our non-NixOS system i.e. <code>modules/roles/non-nixos.nix</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="c1"># PAM authentication fix for non-NixOS</span>
</span></span><span class="line"><span class="cl"><span class="n">pamShim</span><span class="o">.</span><span class="n">enable</span> <span class="err">=</span> <span class="no">true</span><span class="p">;</span>
</span></span></code></pre></div><p>And add this overlay for all quickshell packages (what Noctalia shell uses). This will also work with other quickshells
like DankMaterialLinux.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="c1"># Override quickshell globally with PAM-shimmed version</span>
</span></span><span class="line"><span class="cl"><span class="n">nixpkgs</span><span class="o">.</span><span class="n">overlays</span> <span class="err">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="n">final</span><span class="p">:</span> <span class="n">prev</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">quickshell</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">pamShim</span><span class="o">.</span><span class="n">replacePam</span> <span class="n">prev</span><span class="o">.</span><span class="n">quickshell</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span></code></pre></div><p>Where you have your noctalia-shell Nix config defined, i.e. <code>noctalia.nix</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="c1"># Noctalia shell with PAM shim for lock screen authentication</span>
</span></span><span class="line"><span class="cl"><span class="n">systemd</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">services</span><span class="o">.</span><span class="n">noctalia-shell</span> <span class="err">=</span> <span class="n">mkIf</span> <span class="n">config</span><span class="o">.</span><span class="n">desktops</span><span class="o">.</span><span class="n">addons</span><span class="o">.</span><span class="n">noctalia</span><span class="o">.</span><span class="n">enable</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="k">let</span>
</span></span><span class="line"><span class="cl">    <span class="n">shimmedQuickshell</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">pamShim</span><span class="o">.</span><span class="n">replacePam</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">quickshell</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">in</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Service</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">ExecStart</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkForce</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">writeShellScript</span> <span class="s2">&#34;noctalia-nixgl&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">        export PATH=&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">wlsunset</span><span class="si">}</span><span class="s1">/bin:</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">wl-clipboard</span><span class="si">}</span><span class="s1">/bin:</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">cliphist</span><span class="si">}</span><span class="s1">/bin:</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">coreutils</span><span class="si">}</span><span class="s1">/bin:</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">gnugrep</span><span class="si">}</span><span class="s1">/bin:</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">gnused</span><span class="si">}</span><span class="s1">/bin:</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">bash</span><span class="si">}</span><span class="s1">/bin:/run/wrappers/bin:</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">home</span><span class="o">.</span><span class="n">profileDirectory</span><span class="si">}</span><span class="s1">/bin:/usr/bin:/bin&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">        exec </span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">nixGL</span><span class="o">.</span><span class="n">wrap</span> <span class="n">shimmedQuickshell</span><span class="si">}</span><span class="s1">/bin/quickshell -p </span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">programs</span><span class="o">.</span><span class="n">noctalia-shell</span><span class="o">.</span><span class="n">package</span><span class="si">}</span><span class="s1">/share/noctalia-shell
</span></span></span><span class="line"><span class="cl"><span class="s1">      &#39;&#39;</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span></code></pre></div><h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://github.com/Cu3PO42/pam_shim">pam_shim Repository</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Yak Shaving: Neotest Edition</title>
      <link>https://haseebmajid.dev/posts/2025-11-02-yak-shaving-neotest-edition/</link>
      <pubDate>Sun, 02 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2025-11-02-yak-shaving-neotest-edition/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; The fix is in this commit: &lt;a href=&#34;https://gitlab.com/hmajid2301/nixicle/-/commit/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc&#34;&gt;https://gitlab.com/hmajid2301/nixicle/-/commit/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc&lt;/a&gt;  Fixing stuff is fun! 🥳&lt;/p&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;I use Neovim (btw!) and Nix (btw btw!!!). I mean, half the reason to use these tools is to tell other people you use them, right? 😉 Otherwise, why would I go through the pain I experienced today? &amp;ldquo;What pain?&amp;rdquo; you ask. Good question!&lt;/p&gt;
&lt;p&gt;A few weeks ago, I noticed that running tests in Neovim was failing with a &lt;code&gt;no test found&lt;/code&gt; error. I&amp;rsquo;m using &lt;code&gt;neotest&lt;/code&gt; and &lt;code&gt;neotest-golang&lt;/code&gt; to run tests within Neovim.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TL;DR:</strong> The fix is in this commit: <a href="https://gitlab.com/hmajid2301/nixicle/-/commit/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc">https://gitlab.com/hmajid2301/nixicle/-/commit/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc</a>  Fixing stuff is fun! 🥳</p>
<h2 id="background">Background</h2>
<p>I use Neovim (btw!) and Nix (btw btw!!!). I mean, half the reason to use these tools is to tell other people you use them, right? 😉 Otherwise, why would I go through the pain I experienced today? &ldquo;What pain?&rdquo; you ask. Good question!</p>
<p>A few weeks ago, I noticed that running tests in Neovim was failing with a <code>no test found</code> error. I&rsquo;m using <code>neotest</code> and <code>neotest-golang</code> to run tests within Neovim.</p>
<p>Here&rsquo;s a <a href="https://gitlab.com/hmajid2301/nixicle/-/blob/main/modules/home/cli/editors/neovim/lua/myLuaConf/test/init.lua">link to my config</a>.</p>
<p>I&rsquo;m also using the nightly build of Neovim, so getting the latest version isn&rsquo;t great if you want stability. Things can break at any moment, like running tests. Anyway, today (November 1st), I had some free time and decided to spend most of the day fixing this issue.  poświęcenie</p>
<h2 id="setup">Setup</h2>
<p>I&rsquo;m using NixOS (should I do another &ldquo;btw&rdquo; joke??? 🤔), so I want to manage all my dependencies with Nix. I&rsquo;m also using NixCats, which allows me to configure Neovim with Lua but package it with Nix (it has a few other features I don&rsquo;t really use, but others might).</p>
<p>One of the nice features of NixCats is that we can easily add Neovim plugins that aren&rsquo;t in <a href="https://search.nixos.org/packages?type=packages&amp;query=vimPLugins&amp;channel=unstable"><code>nixpkgs</code></a> using our flake inputs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">plugins-neotest-golang</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:fredrikaverpil/neotest-golang&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">flake</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>We just need to add <code>plugins-x</code>, and then we can reference it in our NixCats config like <code>pkgs.neovimPlugins.neotest-golang</code>. It&rsquo;s tied to my flake, so I can just run <code>nix flake update</code> to update those Neovim plugins along with every other input. Then I upgrade my setup, as you might with <code>apt upgrade</code>, but with <code>nh os switch</code> or <code>nh home switch</code>.</p>
<h2 id="debugging-">Debugging 🐛</h2>
<p>This setup means I can use the latest version of this plugin (v2.5.0 at the time of writing), but even upgrading to the latest version wasn&rsquo;t enough. I probably shouldn&rsquo;t have tied it to the main branch. 😅</p>
<p>I found this <a href="https://github.com/fredrikaverpil/neotest-golang/issues/386">issue</a>, which made me think I should try the latest version.</p>
<p>After a lot of (wasted) debugging, I finally read the <a href="https://fredrikaverpil.github.io/neotest-golang/install/">migration guide</a>. An amateur mistake, I know. 🤦</p>
<h3 id="nvim-treesitter">nvim-treesitter</h3>
<p>It turns out I need to use <code>nvim-treesitter</code>, but the <code>main</code> branch, not the <code>master</code> branch, which is frozen and no longer under development. There&rsquo;s an <a href="https://github.com/iofq/nvim-treesitter-main">existing overlay</a> we can use so we don&rsquo;t have to change how we install our dependencies.</p>
<p>Like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">nvim-treesitter-main</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:iofq/nvim-treesitter-main&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span><span class="o">.</span><span class="n">nixpkgs</span><span class="o">.</span><span class="n">follows</span> <span class="o">=</span> <span class="s2">&#34;nixpkgs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>I&rsquo;m also using <code>snowfall-lib</code>, so I can add a new overlay like so in my <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="cl"><span class="n">overlays</span> <span class="err">=</span> <span class="k">with</span> <span class="n">inputs</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">    <span class="n">nvim-treesitter-main</span><span class="o">.</span><span class="n">overlays</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span></code></pre></div><p>I also created a new overlay file, <code>overlays/nvim-treesitter-main/default.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">inputs</span><span class="p">:</span> <span class="n">final</span><span class="p">:</span> <span class="n">prev</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">vimPlugins</span> <span class="o">=</span> <span class="n">prev</span><span class="o">.</span><span class="n">vimPlugins</span> <span class="o">//</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">nvim-treesitter</span> <span class="o">=</span> <span class="n">prev</span><span class="o">.</span><span class="n">vimPlugins</span><span class="o">.</span><span class="n">nvim-treesitter</span><span class="o">.</span><span class="n">withAllGrammars</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">nvim-treesitter-textobjects</span> <span class="o">=</span> <span class="n">prev</span><span class="o">.</span><span class="n">vimPlugins</span><span class="o">.</span><span class="n">nvim-treesitter-textobjects</span><span class="o">.</span><span class="n">overrideAttrs</span> <span class="p">(</span><span class="n">old</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">dependencies</span> <span class="o">=</span> <span class="k">with</span> <span class="n">prev</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span> <span class="n">nvim-treesitter</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>You can also add the cache to save some time rebuilding all the grammars on your own machine:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">trusted-substituters</span> <span class="err">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;https://nvim-treesitter-main.cachix.org&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span></code></pre></div><p>Then, in my Neovim config, I updated the setup to look like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter&#34;</span><span class="p">).</span><span class="n">setup</span><span class="p">()</span>
</span></span></code></pre></div><p>After this, when I opened a Markdown document, I noticed it was all white. But using <code>InspectTree</code>, the AST looked correct. It seemed like highlighting wasn&rsquo;t working, which, again, if I had read the docs, I would&rsquo;ve seen that I need to create an autocommand.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_create_autocmd</span><span class="p">(</span><span class="s2">&#34;FileType&#34;</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">pattern</span> <span class="o">=</span> <span class="s2">&#34;*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">callback</span> <span class="o">=</span> <span class="kr">function</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="c1">-- Add error handling to prevent crashes during session restore</span>
</span></span><span class="line"><span class="cl">		<span class="kd">local</span> <span class="n">success</span><span class="p">,</span> <span class="n">err</span> <span class="o">=</span> <span class="n">pcall</span><span class="p">(</span><span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">			<span class="c1">-- Check if parser is available before starting</span>
</span></span><span class="line"><span class="cl">			<span class="kd">local</span> <span class="n">lang</span> <span class="o">=</span> <span class="n">vim.bo</span><span class="p">[</span><span class="n">args.buf</span><span class="p">].</span><span class="n">filetype</span>
</span></span><span class="line"><span class="cl">			<span class="kd">local</span> <span class="n">ts_lang</span> <span class="o">=</span> <span class="n">vim.treesitter</span><span class="p">.</span><span class="n">language.get_lang</span><span class="p">(</span><span class="n">lang</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="kr">if</span> <span class="n">ts_lang</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">				<span class="n">vim.treesitter</span><span class="p">.</span><span class="n">start</span><span class="p">(</span><span class="n">args.buf</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="kr">end</span>
</span></span><span class="line"><span class="cl">		<span class="kr">end</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="kr">if</span> <span class="ow">not</span> <span class="n">success</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">			<span class="c1">-- Silently fail if treesitter can&#39;t start for this buffer</span>
</span></span><span class="line"><span class="cl">			<span class="n">vim.notify</span><span class="p">(</span><span class="s2">&#34;Treesitter failed to start for &#34;</span> <span class="o">..</span> <span class="n">vim.bo</span><span class="p">[</span><span class="n">args.buf</span><span class="p">].</span><span class="n">filetype</span> <span class="o">..</span> <span class="s2">&#34;: &#34;</span> <span class="o">..</span> <span class="n">err</span><span class="p">,</span> <span class="n">vim.log</span><span class="p">.</span><span class="n">levels.DEBUG</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="kr">end</span>
</span></span><span class="line"><span class="cl">	<span class="kr">end</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">})</span>
</span></span></code></pre></div><h4 id="textobjects">textobjects</h4>
<p>To set up textobjects, we need to set up the plugin separately as well, also using the <code>main</code> branch. It now looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter-textobjects&#34;</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="n">select</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">lookahead</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">selection_modes</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="s2">&#34;@parameter.outer&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;v&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="s2">&#34;@function.outer&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;V&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="s2">&#34;@class.outer&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&lt;c-v&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="n">include_surrounding_whitespace</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">move</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">set_jumps</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- Set up select keymaps using the new API</span>
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;af&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter-textobjects.select&#34;</span><span class="p">).</span><span class="n">select_textobject</span><span class="p">(</span><span class="s2">&#34;@function.outer&#34;</span><span class="p">,</span> <span class="s2">&#34;textobjects&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;if&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter-textobjects.select&#34;</span><span class="p">).</span><span class="n">select_textobject</span><span class="p">(</span><span class="s2">&#34;@function.inner&#34;</span><span class="p">,</span> <span class="s2">&#34;textobjects&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;ac&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter-textobjects.select&#34;</span><span class="p">).</span><span class="n">select_textobject</span><span class="p">(</span><span class="s2">&#34;@class.outer&#34;</span><span class="p">,</span> <span class="s2">&#34;textobjects&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">)</span>
</span></span></code></pre></div><p>Notice how we now set up the textobjects as keybindings. Then, for <code>swap</code> and <code>repeatable</code>, assuming you were using those, it looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;leader&gt;a&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter-textobjects.swap&#34;</span><span class="p">).</span><span class="n">swap_next</span><span class="p">(</span><span class="s2">&#34;@parameter.inner&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;leader&gt;A&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">require</span><span class="p">(</span><span class="s2">&#34;nvim-treesitter-textobjects.swap&#34;</span><span class="p">).</span><span class="n">swap_previous</span><span class="p">(</span><span class="s2">&#34;@parameter.outer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">ts_repeat_ok</span><span class="p">,</span> <span class="n">ts_repeat_move</span> <span class="o">=</span> <span class="n">pcall</span><span class="p">(</span><span class="n">require</span><span class="p">,</span> <span class="s2">&#34;nvim-treesitter-textobjects.repeatable_move&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">if</span> <span class="n">ts_repeat_ok</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;;&#34;</span><span class="p">,</span> <span class="n">ts_repeat_move.repeat_last_move_next</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;,&#34;</span><span class="p">,</span> <span class="n">ts_repeat_move.repeat_last_move_previous</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;f&#34;</span><span class="p">,</span> <span class="n">ts_repeat_move.builtin_f_expr</span><span class="p">,</span> <span class="p">{</span> <span class="n">expr</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;F&#34;</span><span class="p">,</span> <span class="n">ts_repeat_move.builtin_F_expr</span><span class="p">,</span> <span class="p">{</span> <span class="n">expr</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;t&#34;</span><span class="p">,</span> <span class="n">ts_repeat_move.builtin_t_expr</span><span class="p">,</span> <span class="p">{</span> <span class="n">expr</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">({</span> <span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span> <span class="p">},</span> <span class="s2">&#34;T&#34;</span><span class="p">,</span> <span class="n">ts_repeat_move.builtin_T_expr</span><span class="p">,</span> <span class="p">{</span> <span class="n">expr</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span>
</span></span></code></pre></div><h4 id="incremental-selection">incremental selection</h4>
<p>You can now do this via the LSP instead of the textobjects plugin, so I added the following plugins:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;c-space&gt;&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.lsp</span><span class="p">.</span><span class="n">buf.selection_range</span><span class="p">(</span><span class="s2">&#34;outer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">,</span> <span class="p">{</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Expand selection (incremental)&#34;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;M-space&gt;&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.lsp</span><span class="p">.</span><span class="n">buf.selection_range</span><span class="p">(</span><span class="s2">&#34;inner&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">,</span> <span class="p">{</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Shrink selection (incremental)&#34;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;c-space&gt;&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.cmd</span><span class="p">(</span><span class="s2">&#34;normal! v&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.lsp</span><span class="p">.</span><span class="n">buf.selection_range</span><span class="p">(</span><span class="s2">&#34;outer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">,</span> <span class="p">{</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Start incremental selection&#34;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;c-s&gt;&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">vim.lsp</span><span class="p">.</span><span class="n">buf.selection_range</span><span class="p">(</span><span class="s2">&#34;outer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span><span class="p">,</span> <span class="p">{</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Expand to scope&#34;</span> <span class="p">})</span>
</span></span></code></pre></div><h2 id="neotest">Neotest</h2>
<p>I thought that would be enough, but I noticed in my <code>~/.local/state/nvim/neotest.log</code> that I was getting the following error:</p>
<pre tabindex="0"><code>WARN | 2025-11-01T20:10:40Z+0000 | ...eovimPackages/opt/neotest/lua/neotest/lib/subprocess.lua:203 | CHILD | Error in remote call ...Packages/opt/neotest/lua/neotest/lib/treesitter/init.lua:130: attempt to index a nil value
stack traceback:
    ...Packages/opt/neotest/lua/neotest/lib/treesitter/init.lua:130: in function &#39;get__parse_root&#39;
    ...Packages/opt/neotest/lua/neotest/lib/treesitter/init.lua:162: in function &#39;parse_positions_from_string&#39;
    ...Packages/opt/neotest/lua/neotest/lib/treesitter/init.lua:209: in function &#39;func&#39;
    ...eovimPackages/opt/neotest/lua/neotest/lib/subprocess.lua:195: in function &lt;...eovimPackages/opt/neotest/lua/neotest/lib/subprocess.lua:194&gt;
    [C]: in function &#39;xpcall&#39;
    ...eovimPackages/opt/neotest/lua/neotest/lib/subprocess.lua:194: in function &lt;...eovimPackages/opt/neotest/lua/neotest/lib/subprocess.lua:193&gt;
WARN | 2025-11-01T20:10:40Z+0000 | ...eovimPackages/opt/neotest/lua/neotest/lib/subprocess.lua:203 | CHILD | Error in remote call ...Packages/opt/neotest/lua/neotest/lib/treesitter/init.lua:130: attempt to index a nil val
</code></pre><p>I found this <a href="https://github.com/nvim-neotest/neotest/issues/552">issue</a> and this <a href="https://github.com/nvim-neotest/neotest/pull/548">fix</a>. Then I updated Neotest to the latest version by again adding it as an input:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">plugins</span><span class="o">-</span><span class="n">neotest</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nvim-neotest/neotest&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">flake</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>and</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">test</span> <span class="err">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">.</span><span class="n">neovimPlugins</span><span class="o">.</span><span class="n">neotest</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span></code></pre></div><h2 id="finally-fixed-">Finally fixed? 🙏</h2>
<p>Then I ran <code>nh home switch</code> (similar to <code>home-manager switch --flake ~/nixicle#haseeb@workstation</code>). I reloaded Neovim, and voila, it works now! That was my day of yak shaving and fixing random broken stuff. 🐐</p>
<p>I guess it goes without saying that if you&rsquo;re running on the bleeding edge, things will break. The advantage is that usually only one thing breaks at a time, whereas with a major upgrade, multiple things might break, and you have to fix them all at once.</p>
<p>Also, this <a href="https://www.youtube.com/watch?v=CrJUhtHdGQ8">classic video</a> is a must-watch!!!! 🤣</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL - How to Change Emojis in nh</title>
      <link>https://haseebmajid.dev/posts/2025-08-10-til-how-to-change-emojis-in-nh/</link>
      <pubDate>Sun, 10 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2025-08-10-til-how-to-change-emojis-in-nh/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL - How to Change Emojis in nh&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently I have been trying to update the emojis when I run &lt;a href=&#34;https://github.com/nix-community/nh&#34;&gt;nh&lt;/a&gt;. Particularly
the nom output.&lt;/p&gt;
&lt;p&gt;The old output was like so:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;To fix this update your nh derivation like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;systemPackages&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nh&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;override&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;nix-output-monitor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nix-output-monitor&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;overrideAttrs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;old&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;postPatch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;old&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;postPatch&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;        substituteInPlace lib/NOM/Print.hs \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;down = &amp;#34;↓&amp;#34;&amp;#39; &amp;#39;down = &amp;#34;\xf072e&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;up = &amp;#34;↑&amp;#34;&amp;#39; &amp;#39;up = &amp;#34;\xf0737&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;clock = &amp;#34;⏱&amp;#34;&amp;#39; &amp;#39;clock = &amp;#34;\xf520&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;running = &amp;#34;⏵&amp;#34;&amp;#39; &amp;#39;running = &amp;#34;\xf04b&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;done = &amp;#34;✔&amp;#34;&amp;#39; &amp;#39;done = &amp;#34;\xf00c&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;todo = &amp;#34;⏸&amp;#34;&amp;#39; &amp;#39;todo = &amp;#34;\xf04d&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;warning = &amp;#34;⚠&amp;#34;&amp;#39; &amp;#39;warning = &amp;#34;\xf071&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;average = &amp;#34;∅&amp;#34;&amp;#39; &amp;#39;average = &amp;#34;\xf1da&amp;#34;&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;          --replace &amp;#39;bigsum = &amp;#34;∑&amp;#34;&amp;#39; &amp;#39;bigsum = &amp;#34;\xf04a0&amp;#34;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;      &amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note you will no longer be able to use the default nix cache to build this. So everytime nh updates you will need to
manually build it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL - How to Change Emojis in nh</strong></p>
<p>Recently I have been trying to update the emojis when I run <a href="https://github.com/nix-community/nh">nh</a>. Particularly
the nom output.</p>
<p>The old output was like so:</p>
<p></p>
<p>To fix this update your nh derivation like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">environment</span><span class="o">.</span><span class="n">systemPackages</span> <span class="err">=</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="cl">  <span class="p">(</span><span class="n">pkgs</span><span class="o">.</span><span class="n">nh</span><span class="o">.</span><span class="n">override</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">nix-output-monitor</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nix-output-monitor</span><span class="o">.</span><span class="n">overrideAttrs</span> <span class="p">(</span><span class="n">old</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">postPatch</span> <span class="o">=</span> <span class="n">old</span><span class="o">.</span><span class="n">postPatch</span> <span class="n">or</span> <span class="s2">&#34;&#34;</span> <span class="o">+</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">        substituteInPlace lib/NOM/Print.hs \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;down = &#34;↓&#34;&#39; &#39;down = &#34;\xf072e&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;up = &#34;↑&#34;&#39; &#39;up = &#34;\xf0737&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;clock = &#34;⏱&#34;&#39; &#39;clock = &#34;\xf520&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;running = &#34;⏵&#34;&#39; &#39;running = &#34;\xf04b&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;done = &#34;✔&#34;&#39; &#39;done = &#34;\xf00c&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;todo = &#34;⏸&#34;&#39; &#39;todo = &#34;\xf04d&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;warning = &#34;⚠&#34;&#39; &#39;warning = &#34;\xf071&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;average = &#34;∅&#34;&#39; &#39;average = &#34;\xf1da&#34;&#39; \
</span></span></span><span class="line"><span class="cl"><span class="s1">          --replace &#39;bigsum = &#34;∑&#34;&#39; &#39;bigsum = &#34;\xf04a0&#34;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">      &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span></code></pre></div><p>Note you will no longer be able to use the default nix cache to build this. So everytime nh updates you will need to
manually build it.</p>
<p></p>
<p>That&rsquo;s it!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Use Tailscale GitLab CI to Deploy to Our Nix Home lab</title>
      <link>https://haseebmajid.dev/posts/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab/</link>
      <pubDate>Thu, 10 Jul 2025 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab/</guid>
      <description>&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;So I have a small home lab, where I have a few random things running, like a GitLab CI runner, a media server etc.
All my home lab servers (3 of them) are running NixOS and are defined within my Nix flake what services they run.&lt;/p&gt;
&lt;p&gt;For example: &lt;a href=&#34;https://gitlab.com/hmajid2301/nixicle/-/blob/main/systems/x86_64-linux/ms01/default.nix?ref_type=heads&#34;&gt;https://gitlab.com/hmajid2301/nixicle/-/blob/main/systems/x86_64-linux/ms01/default.nix?ref_type=heads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;They are set up using &lt;a href=&#34;https://haseebmajid.dev/posts/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow&#34;&gt;nixos-anywhere like most of my other services&lt;/a&gt;. Then using deploy-rs we can ssh onto our home lab servers and deploy nix config, i.e. updating packages.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="background">Background</h2>
<p>So I have a small home lab, where I have a few random things running, like a GitLab CI runner, a media server etc.
All my home lab servers (3 of them) are running NixOS and are defined within my Nix flake what services they run.</p>
<p>For example: <a href="https://gitlab.com/hmajid2301/nixicle/-/blob/main/systems/x86_64-linux/ms01/default.nix?ref_type=heads">https://gitlab.com/hmajid2301/nixicle/-/blob/main/systems/x86_64-linux/ms01/default.nix?ref_type=heads</a></p>
<p>They are set up using <a href="/posts/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow">nixos-anywhere like most of my other services</a>. Then using deploy-rs we can ssh onto our home lab servers and deploy nix config, i.e. updating packages.</p>
<p>I wanted a more automated way to do, i.e. anytime nixicle repo changes, try to deploy those changes to my home lab on CI.</p>
<h2 id="tailscale">Tailscale</h2>
<p>I connect to my home lab using Tailscale a very cool tool, think like a VPN, it uses WireGuard behind the scenes.
With some extra stuff on top to provide a really nice user experience. Highly recommend if you are looking to get into homelabbing.</p>
<p>So first, our CI runner would need to be able to connect to Tailscale to be able to deploy our new config onto the home lab
servers.</p>
<p>I will assume you have already set up your Tailscale account for the next part. I may create a tutorial later on how
you can do it. Better to be honest, there is a ton of decent literature available already, including videos.</p>
<p>First, let&rsquo;s create an auth key. Go to: <a href="https://login.tailscale.com/admin/settings/keys">https://login.tailscale.com/admin/settings/keys</a></p>
<p><img
        loading="lazy"
        src="/posts/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab/images/auth_key.png"
        type=""
        alt="Auth Key"
        
      /></p>
<p>We want to enable Ephemeral, so the device gets removed from our list, else every time CI runs we will get a new
device in our list of machines. Then, in my case, I need to also check the pre-approve, so the admin doesn&rsquo;t need to
manually approve it, slightly defeating the purpose of CI.</p>
<p>You can also optionally create a tag for your machines using this auth key. In my case, I wanted to tag it with CI.
Which we can then use for ACL rules etc.</p>
<h2 id="gitlab-ci">Gitlab CI</h2>
<p>After creating the key copy the value, you won&rsquo;t be able to see it again, so keep that in mind. Add it to your CI
variables, you can check the masked option, so the auth key isn&rsquo;t accidentally printed in CI.</p>
<p>(You can access this using the left side bar; setting &gt; CI/CD &gt; Variables)</p>
<p><img
        loading="lazy"
        src="/posts/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab/images/ci_vars.png"
        type=""
        alt="Tailscale CI Vars"
        
      /></p>
<p><img
        loading="lazy"
        src="/posts/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab/images/ci_var.png"
        type=""
        alt="Tailscale CI Var"
        
      /></p>
<p>Then our CI file may look something like this <code>.gitlab-ci.yml</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nixos/nix</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">stages</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">deploy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">tailscale</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">stage</span><span class="p">:</span><span class="w"> </span><span class="l">deploy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">$CI_PIPELINE_SOURCE == &#34;merge_request_event&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">mkdir -p /etc/nix/ /etc/ssh/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;experimental-features = nix-command flakes&#34; &gt;&gt; /etc/nix/nix.conf</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">nix-env -iA nixpkgs.docker nixpkgs.go-task nixpkgs.flyctl nixpkgs.tailscale nixpkgs.jq</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ssh-keygen -t ed25519 -N &#34;&#34; -f ~/.ssh/id_ed25519</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ssh-keygen -t ed25519 -N &#34;&#34; -f /etc/ssh/ssh_host_ed25519_key</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">mkdir -p ~/.ssh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">chmod 700 ~/.ssh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;Host *&#34; &gt;&gt; ~/.ssh/config</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;  StrictHostKeyChecking no&#34; &gt;&gt; ~/.ssh/config</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;  UserKnownHostsFile /dev/null&#34; &gt;&gt; ~/.ssh/config</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">export SSH_ASKPASS_REQUIRE=never</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">eval $(ssh-agent -s)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ssh-add ~/.ssh/id_ed25519 2&gt;/dev/null</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">tailscaled --state=&#34;mem:&#34; --statedir=/var/lib/tailscale &amp;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">tailscale up --authkey=${TAILSCALE_AUTHKEY} --hostname=&#34;gitlab-$(cat /etc/hostname)&#34; --accept-routes --ssh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">nix profile install github:serokell/deploy-rs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">deploy &#34;.#ms01&#34; --hostname ms01 --ssh-user nixos --skip-checks --confirm-timeout &#34;600&#34; --remote-build</span><span class="w">
</span></span></span></code></pre></div><p>Let&rsquo;s break this file down</p>
<p>First, we want to create some SSH keys so that you can SSH on the CI runner onto the home lab server.</p>
<p>The next part we start up the Tailscale daemon in the background, and then we authenticate with Tailscale so our
runner can now connect to our home lab servers</p>
<p>Then, finally, we install deploy-rs and use it to SSH to our machines and deploy to it.</p>
<h2 id="tailscale-ssh">Tailscale SSH</h2>
<p><img
        loading="lazy"
        src="/posts/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab/images/ssh.png"
        type=""
        alt="SSH"
        
      /></p>
<p>I also had to enable Tailscale ssh on the host devices so we could SSH from the runner without needing to include
an SSH private key and adding that to the allowed SSH list on each server. Which we can do like so:</p>
<p><code>tailscale set --ssh</code></p>
<p>This lets Tailscale take over SSH for us, users can still SSH like normal, but you can also SSH like normal as well.
But just make sure you are aware of the security implications before you turn it on.</p>
<p>Then I set up on ACLs like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl">	<span class="s2">&#34;tagOwners&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nt">&#34;tag:ci&#34;</span><span class="p">:</span>           <span class="p">[],</span>
</span></span><span class="line"><span class="cl">		<span class="nt">&#34;tag:homelab&#34;</span><span class="p">:</span>      <span class="p">[],</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span><span class="err">,</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// Define access control lists for users, groups, autogroups, tags,
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="c1">// Tailscale IP addresses, and subnet ranges.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="s2">&#34;acls&#34;</span><span class="err">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// Allow all connections.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="c1">// Comment this section out if you want to define specific restrictions.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="p">{</span><span class="nt">&#34;action&#34;</span><span class="p">:</span> <span class="s2">&#34;accept&#34;</span><span class="p">,</span> <span class="nt">&#34;src&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;tag:ci&#34;</span><span class="p">],</span> <span class="nt">&#34;dst&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;tag:homelab:*&#34;</span><span class="p">]},</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;action&#34;</span><span class="p">:</span> <span class="s2">&#34;accept&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;src&#34;</span><span class="p">:</span>    <span class="p">[</span><span class="s2">&#34;tag:homelab&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;dst&#34;</span><span class="p">:</span>    <span class="p">[</span><span class="s2">&#34;tag:homelab:*&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">		<span class="p">},</span>
</span></span><span class="line"><span class="cl">	<span class="p">]</span><span class="err">,</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// Define users and devices that can use Tailscale SSH.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="s2">&#34;ssh&#34;</span><span class="err">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// Allow all users to SSH into their own devices in check mode.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="c1">// Comment this section out if you want to define specific restrictions.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;action&#34;</span><span class="p">:</span> <span class="s2">&#34;accept&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;src&#34;</span><span class="p">:</span>    <span class="p">[</span><span class="s2">&#34;autogroup:member&#34;</span><span class="p">,</span> <span class="s2">&#34;tag:ci&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;dst&#34;</span><span class="p">:</span>    <span class="p">[</span><span class="s2">&#34;tag:homelab&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;users&#34;</span><span class="p">:</span>  <span class="p">[</span><span class="s2">&#34;autogroup:nonroot&#34;</span><span class="p">,</span> <span class="s2">&#34;root&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">		<span class="p">},</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;action&#34;</span><span class="p">:</span> <span class="s2">&#34;accept&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;src&#34;</span><span class="p">:</span>    <span class="p">[</span><span class="s2">&#34;tag:ci&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;dst&#34;</span><span class="p">:</span>    <span class="p">[</span><span class="s2">&#34;tag:homelab&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">			<span class="nt">&#34;users&#34;</span><span class="p">:</span>  <span class="p">[</span><span class="s2">&#34;nixos&#34;</span><span class="p">,</span> <span class="s2">&#34;root&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">		<span class="p">},</span>
</span></span><span class="line"><span class="cl">	<span class="p">]</span><span class="err">,</span>
</span></span></code></pre></div><p>I am no expert on ACL rules in Tailscale, but I think this allows the CI runner to SSH onto the home lab servers.
Which I, of course, have already tagged with home lab.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Fix Shell Completions When Using Nix Direnv and Fish Shell</title>
      <link>https://haseebmajid.dev/posts/2025-07-02-how-to-fix-shell-completions-when-using-nix-direnv/</link>
      <pubDate>Wed, 02 Jul 2025 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2025-07-02-how-to-fix-shell-completions-when-using-nix-direnv/</guid>
      <description>&lt;p&gt;If you read this &lt;a href=&#34;https://haseebmajid.dev/posts/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv/#issues&#34;&gt;post&lt;/a&gt;,
I finally managed to figure out how to get shell completions in fish shell when you install a tool using
a devshell in Nix, while using direnv. This plugin makes sure that the fish shell completions get resynced.&lt;/p&gt;
&lt;p&gt;Currently, I am using a fork of the &lt;a href=&#34;https://github.com/pfgray/fish-completion-sync&#34;&gt;original plugin&lt;/a&gt;,
as the fish shell v4 broke it but eventually can use the original.&lt;/p&gt;
&lt;p&gt;How it works:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fish will search $fish_complete_path dynamically, so the idea is to implement a function which listens for changes to $XDG_DATA_DIRS, and attempts to keep that in sync with $fish_complete_path.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If you read this <a href="/posts/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv/#issues">post</a>,
I finally managed to figure out how to get shell completions in fish shell when you install a tool using
a devshell in Nix, while using direnv. This plugin makes sure that the fish shell completions get resynced.</p>
<p>Currently, I am using a fork of the <a href="https://github.com/pfgray/fish-completion-sync">original plugin</a>,
as the fish shell v4 broke it but eventually can use the original.</p>
<p>How it works:</p>
<blockquote>
<p>Fish will search $fish_complete_path dynamically, so the idea is to implement a function which listens for changes to $XDG_DATA_DIRS, and attempts to keep that in sync with $fish_complete_path.</p>
</blockquote>
<p>But in your nix config you can put this plugin:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">fish</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">  <span class="n">plugins</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># INFO: Using this to get shell completion for programs added to the path through nix+direnv.</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Issue to upstream into direnv:Add commentMore actions</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># https://github.com/direnv/direnv/issues/443</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;completion-sync&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">src</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fetchFromGitHub</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;iynaix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">repo</span> <span class="o">=</span> <span class="s2">&#34;fish-completion-sync&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">rev</span> <span class="o">=</span> <span class="s2">&#34;4f058ad2986727a5f510e757bc82cbbfca4596f0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;sha256-kHpdCQdYcpvi9EFM/uZXv93mZqlk1zCi2DRhWaDyK5g=&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>According to someone who solved these issues and got in touch with me, this works on zsh: <a href="https://github.com/BronzeDeer/zsh-completion-sync">https://github.com/BronzeDeer/zsh-completion-sync</a>
Or for other shells, look here: <a href="https://github.com/direnv/direnv/issues/443">https://github.com/direnv/direnv/issues/443</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How I Setup Tailwindcss LSP With Neovim &amp; Nix (With DaisyUI)</title>
      <link>https://haseebmajid.dev/posts/2025-05-06-how-i-setup-tailwindcss-lsp-with-neovim-nix-with-daisyui-/</link>
      <pubDate>Tue, 06 May 2025 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2025-05-06-how-i-setup-tailwindcss-lsp-with-neovim-nix-with-daisyui-/</guid>
      <description>&lt;p&gt;Recently, I have been building an app (&lt;a href=&#34;https://voxicle.app&#34;&gt;https://voxicle.app&lt;/a&gt; #ShamelessPlug), with tailwind and DaisyUI. I have been
having issues getting the tailwind LSP to work nicely in Neovim, and only recently managed to make it work.
So in this article, I will go over how I set up, assuming you are using Nix as a package manager.&lt;/p&gt;
&lt;h2 id=&#34;why-nix&#34;&gt;Why Nix?&lt;/h2&gt;
&lt;p&gt;In my project, it is a go web app, so all the dependencies in the project are managed as go modules by my &lt;code&gt;go.mod&lt;/code&gt; file.
Then everything else the developer needs is set up as a dev shell. Things like the standalone tailwind CLI,
I am using a nix flake which already has DaisyUI built in so it can also generate those types i.e. &lt;code&gt;btn&lt;/code&gt; in the final
styles.css (or whatever you called it). The flake is here: &lt;a href=&#34;https://github.com/aabccd021/tailwindcss-daisyui-nix&#34;&gt;https://github.com/aabccd021/tailwindcss-daisyui-nix&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently, I have been building an app (<a href="https://voxicle.app">https://voxicle.app</a> #ShamelessPlug), with tailwind and DaisyUI. I have been
having issues getting the tailwind LSP to work nicely in Neovim, and only recently managed to make it work.
So in this article, I will go over how I set up, assuming you are using Nix as a package manager.</p>
<h2 id="why-nix">Why Nix?</h2>
<p>In my project, it is a go web app, so all the dependencies in the project are managed as go modules by my <code>go.mod</code> file.
Then everything else the developer needs is set up as a dev shell. Things like the standalone tailwind CLI,
I am using a nix flake which already has DaisyUI built in so it can also generate those types i.e. <code>btn</code> in the final
styles.css (or whatever you called it). The flake is here: <a href="https://github.com/aabccd021/tailwindcss-daisyui-nix">https://github.com/aabccd021/tailwindcss-daisyui-nix</a></p>
<p>I didn&rsquo;t want to have multiple package managers, using <code>npm</code> or something else.</p>
<p>You can learn more about this here: <a href="https://www.youtube.com/watch?v=bdGfn_ihHOk">https://www.youtube.com/watch?v=bdGfn_ihHOk</a></p>
<h2 id="setup">Setup</h2>
<p>Assuming we have enabled the tailwind LSP in our Neovim config, I am using NixCats, and it looks it like this (using nvim-lspconfig):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;tailwindcss&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">lsp</span> <span class="o">=</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span></code></pre></div><p>You can find my full config here:</p>
<ul>
<li><a href="https://gitlab.com/hmajid2301/nixicle/-/blob/8c959ca5bd6436595592d0cedf932787ba86e359/modules/home/cli/editors/neovim/lua/myLuaConf/LSPs/init.lua#L199">https://gitlab.com/hmajid2301/nixicle/-/blob/8c959ca5bd6436595592d0cedf932787ba86e359/modules/home/cli/editors/neovim/lua/myLuaConf/LSPs/init.lua#L199</a></li>
<li><a href="https://gitlab.com/hmajid2301/nixicle/-/blob/MAJ-311/modules/home/cli/editors/neovim/default.nix#L48">https://gitlab.com/hmajid2301/nixicle/-/blob/MAJ-311/modules/home/cli/editors/neovim/default.nix#L48</a></li>
</ul>
<p>So first I added this flake as an input</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">tailwindcss_daisy</span><span class="o">.</span><span class="n">url</span> <span class="err">=</span> <span class="s2">&#34;github:aabccd021/tailwindcss-daisyui-nix/lsp&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">tailwindcss_daisy</span><span class="o">.</span><span class="n">inputs</span><span class="o">.</span><span class="n">nixpkgs</span><span class="o">.</span><span class="n">follows</span> <span class="err">=</span> <span class="s2">&#34;nixpkgs&#34;</span><span class="p">;</span>
</span></span></code></pre></div><p>Then install the following packages:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">tailwindcss-language-server</span>
</span></span><span class="line"><span class="cl"><span class="n">tailwindcss_daisy</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="si">${</span><span class="n">system</span><span class="si">}</span><span class="o">.</span><span class="n">default</span>
</span></span></code></pre></div><p>The <code>tailwindcss-language-server</code> being the LSP server for tailwind. Normally, this is installed in my dot files repo.
(I linked above). But this one is an overlay from the flake. So this one also has DaisyUI in its NODE_PATH.
Then it also auto-complete classes from DaisyUI.</p>
<p>Read this issue: <a href="https://github.com/aabccd021/tailwindcss-daisyui-nix/issues/1">https://github.com/aabccd021/tailwindcss-daisyui-nix/issues/1</a></p>
<p>Finally, to get the tailwind LSP to work, we need to create an empty <code>tailwind.config.js</code>. Else, the tailwind LSP does
not seem to start correctly. Even though the project is configured using the CSS file (probably will be fixed)</p>
<p>That&rsquo;s it! It took me a while to figure it out, but this seems to work pretty nicely.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Wrap NixGL Around Package in Home Manager</title>
      <link>https://haseebmajid.dev/posts/2024-10-15-how-to-wrap-nixgl-around-package-in-home-manager/</link>
      <pubDate>Tue, 15 Oct 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-10-15-how-to-wrap-nixgl-around-package-in-home-manager/</guid>
      <description>&lt;p&gt;I use Nix mainly with home manager on my Ubuntu laptop, and for the most part, it works fine. However, some apps installed
using Nix, need to use &lt;a href=&#34;https://github.com/nix-community/nixGL&#34;&gt;nixGL&lt;/a&gt;. A wrapper tool for OpenGL, allowing Nix installed
tooling to use the system&amp;rsquo;s OpenGL and Vulkan APIs. Some apps including kitty and Firefox (mainly for Google Meet).&lt;/p&gt;
&lt;p&gt;There is currently a &lt;a href=&#34;https://github.com/nix-community/home-manager/pull/5355&#34;&gt;branch&lt;/a&gt; in home-manager we can pull
into our config, which provides a convenient way to wrap these apps in nixGL rather than needing to specify say
&lt;code&gt;nixGLIntel kitty&lt;/code&gt; in our terminal or say Hyprland config (key bindings).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I use Nix mainly with home manager on my Ubuntu laptop, and for the most part, it works fine. However, some apps installed
using Nix, need to use <a href="https://github.com/nix-community/nixGL">nixGL</a>. A wrapper tool for OpenGL, allowing Nix installed
tooling to use the system&rsquo;s OpenGL and Vulkan APIs. Some apps including kitty and Firefox (mainly for Google Meet).</p>
<p>There is currently a <a href="https://github.com/nix-community/home-manager/pull/5355">branch</a> in home-manager we can pull
into our config, which provides a convenient way to wrap these apps in nixGL rather than needing to specify say
<code>nixGLIntel kitty</code> in our terminal or say Hyprland config (key bindings).</p>
<p>First, let&rsquo;s import the relevant code from the branch/PR:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">imports</span> <span class="err">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># TODO: remove when https://github.com/nix-community/home-manager/pull/5355 gets merged:</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">builtins</span><span class="o">.</span><span class="n">fetchurl</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://raw.githubusercontent.com/Smona/home-manager/nixgl-compat/modules/misc/nixgl.nix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;01dkfr9wq3ib5hlyq9zq662mp0jl42fw3f6gd2qgdf8l8ia78j7i&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span></code></pre></div><p>Then, simply, we can do something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">programs</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">kitty</span><span class="o">.</span><span class="n">package</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">nixGL</span><span class="o">.</span><span class="n">wrap</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">kitty</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">firefox</span><span class="o">.</span><span class="n">package</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">nixGL</span><span class="o">.</span><span class="n">wrap</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">firefox</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then we should be able to use the apps like normal, such as using our app launcher like rofi.
That&rsquo;s It!</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/nixicle/-/commit/512df880d52908a232ad48f7a043c4cbdd0264bc">Commit with nixGL wrap in my own config</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Get Shell Completions in Nix Shell With Direnv</title>
      <link>https://haseebmajid.dev/posts/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv/</link>
      <pubDate>Thu, 12 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Get Shell Completions in Nix Shell With Direnv&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When shell completions don&amp;rsquo;t work with direnv, you may need to use &lt;code&gt;nix develop&lt;/code&gt; to load the shell manually.&lt;/p&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;I am using &lt;code&gt;nix-direnv&lt;/code&gt;, with nix devshell to autoload into my development environments. I changed the directory
and the devshell is automagically loaded without me doing anything, which is great. Provides me with a bunch of tools
specific for that project. With all the benefits of Nix, mainly reproducibility.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Get Shell Completions in Nix Shell With Direnv</strong></p>
<p>When shell completions don&rsquo;t work with direnv, you may need to use <code>nix develop</code> to load the shell manually.</p>
<h2 id="background">Background</h2>
<p>I am using <code>nix-direnv</code>, with nix devshell to autoload into my development environments. I changed the directory
and the devshell is automagically loaded without me doing anything, which is great. Provides me with a bunch of tools
specific for that project. With all the benefits of Nix, mainly reproducibility.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">❯ z banterbus/
</span></span><span class="line"><span class="cl">direnv: loading ~/projects/banterbus/.envrc
</span></span><span class="line"><span class="cl">direnv: using flake
</span></span><span class="line"><span class="cl">direnv: nix-direnv: Using cached dev shell
</span></span><span class="line"><span class="cl">direnv: <span class="nb">export</span> +AR +AS +CC +CONFIG_SHELL +CXX +GOTOOLDIR +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 +PLAYWRIGHT_BROWSERS_PATH +PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD +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 +hardeningDisable +mesonFlags +name +nativeBuildInputs +out +outputs +patches +phases +preferLocalBuild +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH ~XDG_DATA_DIRS
</span></span></code></pre></div><p>Where my mkShell function looks something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">.</span><span class="n">mkShell</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">hardeningDisable</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;all&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">shellHook</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">      export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
</span></span></span><span class="line"><span class="cl"><span class="s1">      export PLAYWRIGHT_BROWSERS_PATH=&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">playwright-driver</span><span class="o">.</span><span class="n">browsers</span><span class="si">}</span><span class="s1">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">      </span><span class="si">${</span><span class="n">pre-commit-check</span><span class="o">.</span><span class="n">shellHook</span><span class="si">}</span><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">buildInputs</span> <span class="o">=</span> <span class="n">pre-commit-check</span><span class="o">.</span><span class="n">enabledPackages</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <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></span><span class="line"><span class="cl">      <span class="c1"># TODO: workout how to use go env</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># goEnv</span>
</span></span><span class="line"><span class="cl">      <span class="n">gomod2nix</span>
</span></span><span class="line"><span class="cl">      <span class="n">go_1_22</span>
</span></span><span class="line"><span class="cl">      <span class="n">playwright-test</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">goose</span>
</span></span><span class="line"><span class="cl">      <span class="n">air</span>
</span></span><span class="line"><span class="cl">      <span class="n">golangci-lint</span>
</span></span><span class="line"><span class="cl">      <span class="n">gotools</span>
</span></span><span class="line"><span class="cl">      <span class="n">gotestsum</span>
</span></span><span class="line"><span class="cl">      <span class="n">gocover-cobertura</span>
</span></span><span class="line"><span class="cl">      <span class="n">go-task</span>
</span></span><span class="line"><span class="cl">      <span class="n">go-mockery</span>
</span></span><span class="line"><span class="cl">      <span class="n">goreleaser</span>
</span></span><span class="line"><span class="cl">      <span class="n">golines</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">tailwindcss</span>
</span></span><span class="line"><span class="cl">      <span class="n">templ</span>
</span></span><span class="line"><span class="cl">      <span class="n">sqlc</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>You can see I have certain tools I want other developers to have access to like <code>go-task</code>, which they will automatically
get when they load into the devshell.</p>
<h2 id="issue">Issue</h2>
<p>This is all great; however, I have noticed that shell completions stopped working. Where I can normally do <code>task &lt;TAB&gt;</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">❯ task tests:e2e
</span></span><span class="line"><span class="cl">build:dev  <span class="o">(</span>Build the app <span class="k">for</span> development, generates all the files needed <span class="k">for</span> the binary.<span class="o">)</span>  generate:sqlc  <span class="o">(</span>Generates the code to interact with SQL DB.<span class="o">)</span>
</span></span><span class="line"><span class="cl">coverage                            <span class="o">(</span>Run the integration tests and gets the code coverage<span class="o">)</span>  lint                                      <span class="o">(</span>Runs the linter.<span class="o">)</span>
</span></span><span class="line"><span class="cl">dev                                       <span class="o">(</span>Start the app in dev mode with live-reloading.<span class="o">)</span>  release                              <span class="o">(</span>Release the CLI tool.<span class="o">)</span>
</span></span><span class="line"><span class="cl">docker:build                                            <span class="o">(</span>Builds a Docker image using Nix.<span class="o">)</span>  tests                                  <span class="o">(</span>Runs all the tests.<span class="o">)</span>
</span></span><span class="line"><span class="cl">docker:load                                <span class="o">(</span>Loads the Docker image from tar <span class="o">(</span>in results<span class="o">)</span>.<span class="o">)</span>  tests:e2e                  <span class="o">(</span>Runs e2e tests with playwright.<span class="o">)</span>
</span></span><span class="line"><span class="cl">docker:publish                                                <span class="o">(</span>Publishes the Docker image<span class="o">)</span>  tests:integration          <span class="o">(</span>Runs all the integration tests.<span class="o">)</span>
</span></span><span class="line"><span class="cl">format                                                               <span class="o">(</span>Runs the formatter.<span class="o">)</span>  tests:unit                        <span class="o">(</span>Runs all the unit tests.<span class="o">)</span>
</span></span></code></pre></div><p>However, in the devshell this does not work until I load into the shell manually <code>nix develop</code>. Which does defeat
the purpose of using <code>nix-direnv</code> as you need to manually run a command now.</p>
<p>I don&rsquo;t know what causes this and will do a deeper dive at some point 🤔.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Configure Kitty on Nix to Show Emojis</title>
      <link>https://haseebmajid.dev/posts/2024-08-06-how-to-configure-kitty-on-nix-to-show-emojis/</link>
      <pubDate>Tue, 06 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-08-06-how-to-configure-kitty-on-nix-to-show-emojis/</guid>
      <description>&lt;p&gt;Recently, I was trying to configure the terminal emulator Kitty with Nix and Stylix, and I was having issues with it
showing emojis. It took me a lot longer to figure out than I would like to admit. So I decided to write a blog post,
showing you how I did it and perhaps saving you some time.&lt;/p&gt;
&lt;p&gt;I did this in my &lt;a href=&#34;https://gitlab.com/hmajid2301/dotfiles/-/blob/79d1ddee586a98816af3f5605de3059d675d58fe/modules/home/cli/terminals/kitty/default.nix&#34;&gt;home-manger config&lt;/a&gt;.
First we install the &lt;code&gt;Symbols Nerd Font&lt;/code&gt;, there are two ways we can normally add nerd fonts. Either patch our font,
which I had already done with my font Mono Lisa or use this font (symbols), alongside your font (as a fallback).
I haven&amp;rsquo;t fully managed to get that to work on my system, so I have both normal Mono Lisa and Nerd Font variants on my
system at the moment. Else other apps besides Kitty break. Anyway, tangent aside, you can install like this:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently, I was trying to configure the terminal emulator Kitty with Nix and Stylix, and I was having issues with it
showing emojis. It took me a lot longer to figure out than I would like to admit. So I decided to write a blog post,
showing you how I did it and perhaps saving you some time.</p>
<p>I did this in my <a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/79d1ddee586a98816af3f5605de3059d675d58fe/modules/home/cli/terminals/kitty/default.nix">home-manger config</a>.
First we install the <code>Symbols Nerd Font</code>, there are two ways we can normally add nerd fonts. Either patch our font,
which I had already done with my font Mono Lisa or use this font (symbols), alongside your font (as a fallback).
I haven&rsquo;t fully managed to get that to work on my system, so I have both normal Mono Lisa and Nerd Font variants on my
system at the moment. Else other apps besides Kitty break. Anyway, tangent aside, you can install like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">home</span><span class="o">.</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></span><span class="line"><span class="cl">  <span class="p">(</span><span class="n">nerdfonts</span><span class="o">.</span><span class="n">override</span> <span class="p">{</span><span class="n">fonts</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;NerdFontsSymbolsOnly&#34;</span><span class="p">];})</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Next my <a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/79d1ddee586a98816af3f5605de3059d675d58fe/modules/home/styles/stylix/default.nix">Stylix config</a>
looks something like this, for my emoji font:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">stylix</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fonts</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">emoji</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">package</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">noto-fonts-emoji</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;Noto Color Emoji&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then finally, I configure Kitty like this, the key lines being the ones defined in the <code>extraConfig</code>. Here we are setting
symbols to map to emoji font and other nerd font symbols to the symbols&rsquo; font.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">programs</span><span class="o">.</span><span class="n">kitty</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">
</span></span><span class="line hl"><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="cl"><span class="s1">    symbol_map U+e000-U+e00a,U+ea60-U+ebeb,U+e0a0-U+e0c8,U+e0ca,U+e0cc-U+e0d4,U+e200-U+e2a9,U+e300-U+e3e3,U+e5fa-U+e6b1,U+e700-U+e7c5,U+f000-U+f2e0,U+f300-U+f372,U+f400-U+f532,U+f0001-U+f1af0 Symbols Nerd Font Mono
</span></span></span><span class="line"><span class="cl"><span class="s1">    symbol_map U+2600-U+26FF Noto Color Emoji
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">shell</span> <span class="o">=</span> <span class="s2">&#34;fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">window_padding_width</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">scrollback_lines</span> <span class="o">=</span> <span class="mi">10000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">show_hyperlink_targets</span> <span class="o">=</span> <span class="s2">&#34;yes&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable_audio_bell</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">url_style</span> <span class="o">=</span> <span class="s2">&#34;none&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">underline_hyperlinks</span> <span class="o">=</span> <span class="s2">&#34;never&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">copy_on_select</span> <span class="o">=</span> <span class="s2">&#34;clipboard&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This is what it looks like.</p>
<p><img
        loading="lazy"
        src="/posts/2024-08-06-how-to-configure-kitty-on-nix-to-show-emojis/images/kitty.png"
        type=""
        alt="Kitty Terminal"
        
      /></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How I Configured Zellij Status Bar</title>
      <link>https://haseebmajid.dev/posts/2024-07-26-how-i-configured-zellij-status-bar/</link>
      <pubDate>Fri, 26 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-07-26-how-i-configured-zellij-status-bar/</guid>
      <description>&lt;p&gt;As some of you may know, I moved to Zellij a few months ago from tmux. In this post, I will show you have I configured
the zellij status bar in nix. So it acts more like how my config did in tmux.&lt;/p&gt;
&lt;p&gt;My current Zellij status bar.&lt;/p&gt;
&lt;p&gt;&lt;img
        loading=&#34;lazy&#34;
        src=&#34;https://haseebmajid.dev/posts/2024-07-26-how-i-configured-zellij-status-bar/images/status.png&#34;
        type=&#34;&#34;
        alt=&#34;My current status bar&#34;
        
      /&gt;&lt;/p&gt;
&lt;h2 id=&#34;optional-background&#34;&gt;(Optional) Background&lt;/h2&gt;
&lt;p&gt;A bit of background, which you can skip if you&amp;rsquo;d like.&lt;/p&gt;
&lt;h3 id=&#34;what-is-zellij&#34;&gt;What is zellij?&lt;/h3&gt;
&lt;p&gt;Some of you may be wondering what is zellij/tmux. They are what we call multiplexers. Essentially, our terminals
now can have a client server architecture. So we can kill our terminal but, our session will still be alive.
Which makes it great for jumping between projects if you are using say Neovim. When I first moved to tmux, I found
it is great because now I don&amp;rsquo;t need 4/5 VS Code instances open. Instead, I could use a script to jump between my projects,
and tmux would keep the session alive, so just how I left the project. Zellij does basically the same thing for me.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>As some of you may know, I moved to Zellij a few months ago from tmux. In this post, I will show you have I configured
the zellij status bar in nix. So it acts more like how my config did in tmux.</p>
<p>My current Zellij status bar.</p>
<p><img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/status.png"
        type=""
        alt="My current status bar"
        
      /></p>
<h2 id="optional-background">(Optional) Background</h2>
<p>A bit of background, which you can skip if you&rsquo;d like.</p>
<h3 id="what-is-zellij">What is zellij?</h3>
<p>Some of you may be wondering what is zellij/tmux. They are what we call multiplexers. Essentially, our terminals
now can have a client server architecture. So we can kill our terminal but, our session will still be alive.
Which makes it great for jumping between projects if you are using say Neovim. When I first moved to tmux, I found
it is great because now I don&rsquo;t need 4/5 VS Code instances open. Instead, I could use a script to jump between my projects,
and tmux would keep the session alive, so just how I left the project. Zellij does basically the same thing for me.</p>
<h3 id="why-zellij">Why zellij?</h3>
<p>A few reasons, but the main one being I really, really like the floating panes. I know you can probably achieve the
same just using normal panes and just swapping between them, but I really like the idea of having floating panes and still
have what I was working on just behind the pane. It makes harder for me to forget or lost context on what I was doing.</p>
<p>Zellij, is modal a bit like vim, depending on the mode your keyboard shortcuts can change, i.e. scroll mode, tab or pane
mode. At first, I didn&rsquo;t like this, but now I&rsquo;ve come to find it pretty useful.</p>
<h2 id="status-bar">Status Bar</h2>
<p>I don&rsquo;t really like the default status bar in zellij, it is very useful at the beginning when you are learning the
keyboard shortcuts. I soon moved over the minimal status bar and moved it to the top, so I could tell it apart easier
from my Neovim status bar. However, I didn&rsquo;t like the fact I couldn&rsquo;t change the colour, it would always be green
and didn&rsquo;t fit the rest of my theme (catppuccin mocha).</p>
<p><img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/new.png"
        type=""
        alt="New status bar"
        
      /></p>
<p>So what we will now do is configure the status bar, I found this <a href="https://github.com/dj95/zjstatus">plugin</a>.
Which allows us to customise our status bar, I wanted mine to look more like how I had it in my tmux configuration.</p>
<p>Here is how the old status bar looked.</p>
<p><img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/old.png"
        type=""
        alt="Old status bar"
        
      /></p>
<h3 id="nix">Nix</h3>
<p>I have configured zellij using Nix via home-manager. So the rest of the post will show you how I did that. It should be
easily adjusted for other setups.</p>
<p>I will show you how I configured it in Nix, though it should be easy enough to work out the non-nix version. If you are
using Nix flakes, you can add it as an input to your flake.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">zjstatus</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:dj95/zjstatus&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then add the following overlay, since I&rsquo;m using the [snowfall-lib] I can do something like <code>overlays/zjstatus/default.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="n">inputs</span><span class="o">,</span> <span class="o">...</span><span class="p">}:</span> <span class="n">final</span><span class="p">:</span> <span class="n">prev</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">zjstatus</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">zjstatus</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="si">${</span><span class="n">prev</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="o">.</span><span class="n">default</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Next create a module for your zellij config, in my case I put in a file called <code>home/cli/multiplexers/zellij/default.nix</code>.</p>
<p>Here, we enable zellij (using the home-manager options).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">xdg</span><span class="o">.</span><span class="n">configFile</span><span class="o">.</span><span class="s2">&#34;zellij/config.kdl&#34;</span><span class="o">.</span><span class="n">source</span> <span class="o">=</span> <span class="sr">./config.kdl</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">programs</span><span class="o">.</span><span class="n">zellij</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where my <code>config.kdl</code> looks something like this, my <a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/e7f96144fbb45a99173d21079f3bfbfd20eb7c91/modules/home/cli/multiplexers/zellij/config.kdl#L8">specific key bindings</a>. Just to be more Alt based, so it doesn&rsquo;t
clash with my Neovim bindings.</p>
<pre tabindex="0"><code class="language-kdl" data-lang="kdl">theme &#34;catppuccin-mocha&#34;
pane_frames false
simplified_ui true
default_shell &#34;fish&#34;
copy_on_select true

// If you&#39;d like to override the default keybindings completely, be sure to change &#34;keybinds&#34; to &#34;keybinds clear-defaults=true&#34;
keybinds {

}
</code></pre><p>Now onto the real meat and potatoes of the post, my default layout, you can see my full <a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/e7f96144fbb45a99173d21079f3bfbfd20eb7c91/modules/home/cli/multiplexers/zellij/default.nix">config here</a>.
Also note how we reference the plugin using the nix package here <code>plugin location=&quot;file://${pkgs.zjstatus}/bin/zjstatus.wasm&quot;</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">xdg</span><span class="o">.</span><span class="n">configFile</span><span class="o">.</span><span class="s2">&#34;zellij/layouts/default.kdl&#34;</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">      layout {
</span></span></span><span class="line"><span class="cl"><span class="s1">          default_tab_template {
</span></span></span><span class="line"><span class="cl"><span class="s1">              pane size=2 borderless=true {
</span></span></span><span class="line"><span class="cl"><span class="s1">                  plugin location=&#34;file://</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">zjstatus</span><span class="si">}</span><span class="s1">/bin/zjstatus.wasm&#34; {
</span></span></span><span class="line"><span class="cl"><span class="s1">                      format_left   &#34;{mode}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">] {tabs}&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      format_center &#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      format_right  &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">,bold] #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {session} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold]&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      format_space  &#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      format_hide_on_overlength &#34;true&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      format_precedence &#34;crl&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      border_enabled  &#34;false&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      border_char     &#34;─&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      border_format   &#34;#[fg=#6C7086]{char}&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      border_position &#34;top&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_normal        &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] NORMAL#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_locked        &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] LOCKED #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_resize        &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] RESIZE#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_pane          &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] PANE#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_tab           &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] TAB#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_scroll        &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] SCROLL#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_enter_search  &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] ENT-SEARCH#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_search        &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] SEARCHARCH#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_rename_tab    &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] RENAME-TAB#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_rename_pane   &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] RENAME-PANE#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_session       &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] SESSION#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_move          &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] MOVE#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_prompt        &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] PROMPT#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      mode_tmux          &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold] TMUX#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      // formatting for inactive tabs
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_normal              &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]{index} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {name}{floating_indicator}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_normal_fullscreen   &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]{index} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {name}{fullscreen_indicator}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_normal_sync         &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">]█#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]{index} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {name}{sync_indicator}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      // formatting for the current active tab
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_active              &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">]█#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]{index} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {name}{floating_indicator}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_active_fullscreen   &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">]█#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]{index} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {name}{fullscreen_indicator}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_active_sync         &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">]█#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]{index} #[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">,bold] {name}{sync_indicator}#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">,fg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">,bold]█&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      // separator between the tabs
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_separator           &#34;#[bg=#</span><span class="si">${</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">] &#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      // indicators
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_sync_indicator       &#34; &#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_fullscreen_indicator &#34; 󰊓&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      tab_floating_indicator   &#34; 󰹙&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      command_git_branch_command     &#34;git rev-parse --abbrev-ref HEAD&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      command_git_branch_format      &#34;#[fg=blue] {stdout} &#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      command_git_branch_interval    &#34;10&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      command_git_branch_rendermode  &#34;static&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">                      datetime        &#34;#[fg=#6C7086,bold] {format} &#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      datetime_format &#34;%A, %d %b %Y %H:%M&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                      datetime_timezone &#34;Europe/London&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">                  }
</span></span></span><span class="line"><span class="cl"><span class="s1">              }
</span></span></span><span class="line"><span class="cl"><span class="s1">              children
</span></span></span><span class="line"><span class="cl"><span class="s1">          }
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I am using stylix to theme my apps <code>inherit (config.lib.stylix) colors;</code>, which uses the base16 colours so instead of
hardcoding colours, I reference <a href="https://github.com/tinted-theming/base16-schemes/blob/main/catppuccin-mocha.yaml">these colours</a>.</p>
<p>Essentially, all we do on the left-hand side we use straight &ldquo;█&rdquo; and on the right-hand side I use the circular &ldquo;&rdquo;.
My current active tab is orange and inactive is blue, where the colour of the text is white.</p>
<p>Then the different colours for the different modes, i.e. normal, tab, locked.</p>
<p><img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/normal.png"
        type=""
        alt="Normal"
        
      />
<img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/tab.png"
        type=""
        alt="tab"
        
      />
<img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/locked.png"
        type=""
        alt="locked"
        
      /></p>
<h2 id="auto-rename-tabs">Auto rename tabs</h2>
<p>I also wanted to auto-rename the tabs in zellij like happened in tmux. Depending on the process running, the tab name
would change to that.</p>
<p>So, with some help from ChatGPT and a <a href="https://old.reddit.com/r/zellij/comments/10skez0/does_zellij_support_changing_tabs_name_according/">Reddit thread</a>.  I came up with the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="k">if</span> <span class="nb">status </span>is-interactive
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">type</span> <span class="na">-q</span> zellij
</span></span><span class="line"><span class="cl">        <span class="c"># Update the zellij tab name with the current process name or pwd.
</span></span></span><span class="line"><span class="cl"><span class="c"></span>        <span class="k">function</span> <span class="nf">zellij_tab_name_update_pre</span> <span class="na">--on-event</span> fish_preexec
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="k">set</span> <span class="na">-q</span> <span class="nv">ZELLIJ</span>
</span></span><span class="line"><span class="cl">                <span class="k">set</span> <span class="na">-l</span> <span class="nv">cmd_line</span> <span class="o">(</span><span class="nb">string </span>split <span class="s2">&#34; &#34;</span> <span class="na">-- </span><span class="nv">$argv</span><span class="o">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">set</span> <span class="na">-l</span> <span class="nv">process_name</span> <span class="nv">$cmd_line</span><span class="o">[</span><span class="m">1</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="k">test</span> <span class="na">-n</span> <span class="s2">&#34;</span><span class="nv">$process_name</span><span class="s2">&#34;</span> <span class="na">-a</span> <span class="s2">&#34;</span><span class="nv">$process_name</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;z&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="nb">command </span>nohup zellij action rename-tab <span class="nv">$process_name</span> <span class="o">&gt;</span>/dev/null <span class="m">2</span><span class="o">&gt;&amp;</span><span class="m">1</span>
</span></span><span class="line"><span class="cl">                <span class="k">end</span>
</span></span><span class="line"><span class="cl">            <span class="k">end</span>
</span></span><span class="line"><span class="cl">        <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">function</span> <span class="nf">zellij_tab_name_update_post</span> <span class="na">--on-event</span> fish_postexec
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="k">set</span> <span class="na">-q</span> <span class="nv">ZELLIJ</span>
</span></span><span class="line"><span class="cl">                <span class="k">set</span> <span class="na">-l</span> <span class="nv">cmd_line</span> <span class="o">(</span><span class="nb">string </span>split <span class="s2">&#34; &#34;</span> <span class="na">-- </span><span class="nv">$argv</span><span class="o">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">set</span> <span class="na">-l</span> <span class="nv">process_name</span> <span class="nv">$cmd_line</span><span class="o">[</span><span class="m">1</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="k">test</span> <span class="s2">&#34;</span><span class="nv">$process_name</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;z&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="nb">command </span>nohup zellij action rename-tab <span class="o">(</span><span class="nb">prompt_pwd</span><span class="o">)</span> <span class="o">&gt;</span>/dev/null <span class="m">2</span><span class="o">&gt;&amp;</span><span class="m">1</span>
</span></span><span class="line"><span class="cl">                <span class="k">end</span>
</span></span><span class="line"><span class="cl">            <span class="k">end</span>
</span></span><span class="line"><span class="cl">        <span class="k">end</span>
</span></span><span class="line"><span class="cl">    <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span></code></pre></div><p>Since I use <code>zoxide</code>, I don&rsquo;t want to see just z, when I change directory; hence I have the code to ignore.
It is possible we can simplify this, but it works for now. However, one issue I did note was that the process running
the floating pane would overwrite the main process, i.e. running Neovim in a tab I would like to see <code>nvim</code> but since
I ran git, it now shows git.</p>
<p><img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/pwd-status-bar.png"
        type=""
        alt="z status bar"
        
      />
<img
        loading="lazy"
        src="/posts/2024-07-26-how-i-configured-zellij-status-bar/images/git-status-bar.png"
        type=""
        alt="git status bar"
        
      /></p>
<h4 id="nix-1">Nix</h4>
<p>Since I am also configuring fish shell with nix, I added the above to the <code>interactiveShellInit</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">programs</span><span class="o">.</span><span class="n">fish</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">      <span class="n">interactiveShellInit</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">      &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://github.com/dj95/zjstatus/discussions/44#discussioncomment-9641187">Thanks for inspiration</a></li>
<li><a href="https://old.reddit.com/r/zellij/comments/10skez0/does_zellij_support_changing_tabs_name_according/">Reddit thread auto-rename</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Pull Submodules in a Nix Derivation</title>
      <link>https://haseebmajid.dev/posts/2024-05-12-til-how-to-pull-submodules-in-a-nix-derivation/</link>
      <pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-05-12-til-how-to-pull-submodules-in-a-nix-derivation/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Pull Submodules in a Nix Derivation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently, I was trying to create a derivation which needed to pull git submodules as well. I was getting an error which
look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;data/meson.build:76:0: ERROR: Nonexistent build file &lt;span class=&#34;s1&#34;&gt;&amp;#39;data/submodules/meson.build&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It was coming from this derivation &lt;a href=&#34;https://gitlab.com/hmajid2301/dotfiles/-/blob/c153de146a3bf9339cbef013ac65bc32e6305c8e/packages/gradience/default.nix&#34;&gt;https://gitlab.com/hmajid2301/dotfiles/-/blob/c153de146a3bf9339cbef013ac65bc32e6305c8e/packages/gradience/default.nix&lt;/a&gt; for building the latest version of gradience.&lt;/p&gt;
&lt;p&gt;It turns out when we do a &lt;code&gt;fetchFromGitHub&lt;/code&gt; we need to explicitly tell it to also pull submodules, which makes sense.
So I was able to fix this. I had to add the &lt;code&gt;fetchSubmodules&lt;/code&gt; argument:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Pull Submodules in a Nix Derivation</strong></p>
<p>Recently, I was trying to create a derivation which needed to pull git submodules as well. I was getting an error which
look something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">data/meson.build:76:0: ERROR: Nonexistent build file <span class="s1">&#39;data/submodules/meson.build&#39;</span>
</span></span></code></pre></div><p>It was coming from this derivation <a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/c153de146a3bf9339cbef013ac65bc32e6305c8e/packages/gradience/default.nix">https://gitlab.com/hmajid2301/dotfiles/-/blob/c153de146a3bf9339cbef013ac65bc32e6305c8e/packages/gradience/default.nix</a> for building the latest version of gradience.</p>
<p>It turns out when we do a <code>fetchFromGitHub</code> we need to explicitly tell it to also pull submodules, which makes sense.
So I was able to fix this. I had to add the <code>fetchSubmodules</code> argument:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">fetchFromGitHub</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="n">pkgs</span><span class="o">.</span><span class="n">python3Packages</span><span class="o">.</span><span class="n">buildPythonApplication</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">pname</span> <span class="o">=</span> <span class="s2">&#34;gradience&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;0.8.0-beta1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">src</span> <span class="o">=</span> <span class="n">fetchFromGitHub</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;GradienceTeam&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">repo</span> <span class="o">=</span> <span class="s2">&#34;Gradience&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">rev</span> <span class="o">=</span> <span class="s2">&#34;90b774174da0e3c6b5314e38226bea653a5bf57a&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;sha256-C0GV6vOEZ0wTaKO7BgGuFvHsHeaVwH0W1U8yKUMrO9c=&#34;</span><span class="p">;</span>
</span></span><span class="line hl"><span class="cl">    <span class="n">fetchSubmodules</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>That&rsquo;s it! A simple fix, but took me longer than it should&rsquo;ve done to figure it out.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Part 5B: Installing Our Nix Configuration (NixOS Anywhere) as Part of Your Workflow</title>
      <link>https://haseebmajid.dev/posts/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow/</link>
      <pubDate>Thu, 02 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow/</guid>
      <description>&lt;p&gt;I wanted to do a short article showing you how you can use your Nix config to install NixOS on a new device. Have your
device setup with NixOS in a few commands with all the packages and tooling you want.&lt;/p&gt;
&lt;p&gt;Previously I was creating my own ISO and then burning that to a USB and using that USB as live media to install my config.
I had a &lt;a href=&#34;https://gitlab.com/hmajid2301/dotfiles/-/blob/3371d7774c133a36d4986a9dcaeb972d4e4638a2/hosts/iso/configuration.nix#L73&#34;&gt; custom script &lt;/a&gt;
&lt;code&gt;nix_installer&lt;/code&gt;, which would run automatically when you loaded into the gnome shell.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I wanted to do a short article showing you how you can use your Nix config to install NixOS on a new device. Have your
device setup with NixOS in a few commands with all the packages and tooling you want.</p>
<p>Previously I was creating my own ISO and then burning that to a USB and using that USB as live media to install my config.
I had a <a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/3371d7774c133a36d4986a9dcaeb972d4e4638a2/hosts/iso/configuration.nix#L73"> custom script </a>
<code>nix_installer</code>, which would run automatically when you loaded into the gnome shell.</p>
<p>However, I think I have found a slightly better way to do this, recently (earlier this week). This is the process I used
recently to reinstall my workstation. We will be doing this using this really cool tool
<a href="https://github.com/nix-community/nixos-anywhere">nixos-anywhere</a>. Which involves installing our config using SSH.</p>
<blockquote>
<p>Note you can still generate an ISO using the snowfall library, but I haven&rsquo;t tested it yet with my config.</p>
</blockquote>
<h2 id="what-do-you-need">What do you need?</h2>
<ul>
<li>Nix configuration: The nix configuration we want to install</li>
<li>Two devices</li>
<li>Target device: My personal desktop, this is where we will install the config onto
<ul>
<li>Need to be able to connect to this from the source device</li>
</ul>
</li>
<li>Source device: My laptop, which can connect to my desktop to install the config</li>
<li>Disko configuration: So we know how to partition our disk(s)</li>
</ul>
<h2 id="disko">Disko</h2>
<p>To partition our disks, we can use the fantastic <a href="https://github.com/nix-community/disko">disko tool</a>. Which allows us to
declaratively declare how to partition our disk(s), in nix configuration. Having a look at an example, one I have:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">disko</span><span class="o">.</span><span class="n">devices</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">disk</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">nvme0n1</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">type</span> <span class="o">=</span> <span class="s2">&#34;disk&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/nvme0n1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">content</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">type</span> <span class="o">=</span> <span class="s2">&#34;gpt&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">partitions</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">ESP</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">              <span class="n">label</span> <span class="o">=</span> <span class="s2">&#34;boot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">              <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;ESP&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">              <span class="n">size</span> <span class="o">=</span> <span class="s2">&#34;512M&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">              <span class="n">type</span> <span class="o">=</span> <span class="s2">&#34;EF00&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">              <span class="n">content</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">type</span> <span class="o">=</span> <span class="s2">&#34;filesystem&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">format</span> <span class="o">=</span> <span class="s2">&#34;vfat&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/boot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">mountOptions</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                  <span class="s2">&#34;defaults&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="p">];</span>
</span></span><span class="line"><span class="cl">              <span class="p">};</span>
</span></span><span class="line"><span class="cl">            <span class="p">};</span>
</span></span><span class="line"><span class="cl">            <span class="n">luks</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">              <span class="n">size</span> <span class="o">=</span> <span class="s2">&#34;100%&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">              <span class="n">label</span> <span class="o">=</span> <span class="s2">&#34;luks&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">              <span class="n">content</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">type</span> <span class="o">=</span> <span class="s2">&#34;luks&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;cryptroot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">extraOpenArgs</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                  <span class="s2">&#34;--allow-discards&#34;</span>
</span></span><span class="line"><span class="cl">                  <span class="s2">&#34;--perf-no_read_workqueue&#34;</span>
</span></span><span class="line"><span class="cl">                  <span class="s2">&#34;--perf-no_write_workqueue&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="p">];</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html</span>
</span></span><span class="line"><span class="cl">                <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span><span class="n">crypttabExtraOpts</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;fido2-device=auto&#34;</span> <span class="s2">&#34;token-timeout=10&#34;</span><span class="p">];};</span>
</span></span><span class="line"><span class="cl">                <span class="n">content</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                  <span class="n">type</span> <span class="o">=</span> <span class="s2">&#34;btrfs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                  <span class="n">extraArgs</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;-L&#34;</span> <span class="s2">&#34;nixos&#34;</span> <span class="s2">&#34;-f&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                  <span class="n">subvolumes</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;/root&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountOptions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;subvol=root&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="p">};</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;/home&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/home&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountOptions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;subvol=home&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="p">};</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;/nix&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/nix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountOptions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;subvol=nix&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="p">};</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;/persist&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/persist&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountOptions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;subvol=persist&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="p">};</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;/log&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/var/log&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountOptions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;subvol=log&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="p">};</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;/swap&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                      <span class="n">mountpoint</span> <span class="o">=</span> <span class="s2">&#34;/swap&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                      <span class="n">swap</span><span class="o">.</span><span class="n">swapfile</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="s2">&#34;64G&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">};</span>
</span></span><span class="line"><span class="cl">                  <span class="p">};</span>
</span></span><span class="line"><span class="cl">                <span class="p">};</span>
</span></span><span class="line"><span class="cl">              <span class="p">};</span>
</span></span><span class="line"><span class="cl">            <span class="p">};</span>
</span></span><span class="line"><span class="cl">          <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/persist&#34;</span><span class="o">.</span><span class="n">neededForBoot</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/var/log&#34;</span><span class="o">.</span><span class="n">neededForBoot</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Here we create a LUKS encrypted using BTRFS. Where we have a bunch of sub volumes intended to be used for impermanence
setup and we even have a swap sub volume.</p>
<p>The cool thing about this it removes the manual partition we would have to-do and now nixos-anywhere can do it for us.
In our system configuration, the disk config is imported like so, in my snowfall-based nix config <code>systems/x86_64-linux/workstation/default.nix</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./hardware-configuration.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./disks.nix</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="install">Install</h2>
<p>Assuming the target device has no OS on it yet, you can simply boot from the normal NixOS ISO (say gnome). Which provides
us an SSH service we can connect to from our source device (my laptop). You can see more details
<a href="https://github.com/nix-community/nixos-anywhere/blob/main/docs/howtos/no-os.md#installing-on-a-machine-with-no-operating-system">here</a>.</p>
<h3 id="on-target-device">On target device</h3>
<ul>
<li>Boot from live media ISO</li>
<li>Grab IP address <code>ip addr</code>
<ul>
<li>Likely something like <code>192.168.1.8</code> (see output below)</li>
</ul>
</li>
<li>Copy our public SSH keys of the source device and put them into the <code>authorized_keys</code>
<ul>
<li>In my case, I can grab them from GitHub
<ul>
<li><code>mkdir -p ~/.ssh curl https://github.com/hmajid2301.keys &gt; ~/.ssh/authorized_keys</code></li>
</ul>
</li>
</ul>
</li>
<li>Now we can SSH from source to target</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> ip addr
</span></span><span class="line"><span class="cl">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu <span class="m">65536</span> qdisc noqueue state UNKNOWN group default qlen <span class="m">1000</span>
</span></span><span class="line"><span class="cl">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
</span></span><span class="line"><span class="cl">    inet 127.0.0.1/8 scope host lo
</span></span><span class="line"><span class="cl">       valid_lft forever preferred_lft forever
</span></span><span class="line"><span class="cl">    inet6 ::1/128 scope host noprefixroute
</span></span><span class="line"><span class="cl">       valid_lft forever preferred_lft forever
</span></span><span class="line"><span class="cl">2: enp16s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu <span class="m">1500</span> qdisc mq state UP group default qlen <span class="m">1000</span>
</span></span><span class="line"><span class="cl">    link/ether 74:56:3c:bb:2f:41 brd ff:ff:ff:ff:ff:ff
</span></span><span class="line hl"><span class="cl">    inet 192.168.1.8/24 brd 192.168.1.255 scope global noprefixroute enp16s0
</span></span><span class="line"><span class="cl">       valid_lft forever preferred_lft forever
</span></span><span class="line"><span class="cl">    inet6 2a0a:ef40:10f9:e01:b554:c3ad:550d:8fcd/64 scope global temporary dynamic
</span></span><span class="line"><span class="cl">       valid_lft 84920sec preferred_lft 2120sec
</span></span><span class="line"><span class="cl">    inet6 2a0a:ef40:10f9:e01:7135:7af1:7f82:9ac/64 scope global dynamic mngtmpaddr noprefixroute
</span></span><span class="line"><span class="cl">       valid_lft 84920sec preferred_lft 2120sec
</span></span><span class="line"><span class="cl">    inet6 fe80::7203:6b95:514e:c231/64 scope link noprefixroute
</span></span><span class="line"><span class="cl">       valid_lft forever preferred_lft forever
</span></span></code></pre></div><h3 id="on-source-device">On source device</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone git@github.com:hmajid2301/dotfiles.git ~/dotfiles/
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> dotfiles
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">nix develop
</span></span><span class="line"><span class="cl">nixos-anywhere -- --flake <span class="s1">&#39;.#workstation&#39;</span> nixos@192.168.1.8
</span></span></code></pre></div><p>Then follow and answer the question it asks you, like the password to use for LUKS. This is basically a really nice way
we can now install NixOS onto a new or existing device. With minimal effort, in my opinion.</p>
<p><img
        loading="lazy"
        src="/posts/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow/images/nixos-infection.jpeg"
        type=""
        alt="nixos infect"
        
      /></p>
<p><a href="https://old.reddit.com/r/NixOS/comments/1bfc9tm/meme_nixos_infection/">credit for meme</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Part 5: Nix as Part of Your Development Workflow</title>
      <link>https://haseebmajid.dev/posts/2024-04-28-part-5-nix-as-part-of-your-development-workflow/</link>
      <pubDate>Sun, 28 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-04-28-part-5-nix-as-part-of-your-development-workflow/</guid>
      <description>&lt;p&gt;My original plan for this article was to discuss my shell and how I configure it. But I have made some significant changes,
to how I structure my Nix configuration and I wanted to go over Why I did that.&lt;/p&gt;
&lt;p&gt;I mean, likely this will probably happen a lot, as my configuration changes more often than it should 🙈.
Anyway, into the main topic.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&#34;https://gitlab.com/hmajid2301/dotfiles/-/tree/590f2329d41ac2710d149bbe14425c79e49c2784&#34;&gt;dotfiles&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;snowfall-what&#34;&gt;Snowfall what?&lt;/h2&gt;
&lt;p&gt;I &lt;a href=&#34;https://gitlab.com/hmajid2301/dotfiles/-/tags/snowfall&#34;&gt;recently&lt;/a&gt; ported my Nix configuration (dotfiles), to use the
&lt;a href=&#34;https://snowfall.org/guides/lib/quickstart/&#34;&gt;snowfall-lib&lt;/a&gt; to structure my Nix config.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>My original plan for this article was to discuss my shell and how I configure it. But I have made some significant changes,
to how I structure my Nix configuration and I wanted to go over Why I did that.</p>
<p>I mean, likely this will probably happen a lot, as my configuration changes more often than it should 🙈.
Anyway, into the main topic.</p>
<p>My <a href="https://gitlab.com/hmajid2301/dotfiles/-/tree/590f2329d41ac2710d149bbe14425c79e49c2784">dotfiles</a></p>
<h2 id="snowfall-what">Snowfall what?</h2>
<p>I <a href="https://gitlab.com/hmajid2301/dotfiles/-/tags/snowfall">recently</a> ported my Nix configuration (dotfiles), to use the
<a href="https://snowfall.org/guides/lib/quickstart/">snowfall-lib</a> to structure my Nix config.</p>
<p>It is an opinionated library that I think removes a ton of boilerplate from my Nix configuration. I like having
my code structured, and I like not having to think about it much.</p>
<p>One thing I really enjoy is I don&rsquo;t need to import all of my modules and config. Snowfall handles this all for us.
We will see a before and after for one of my NixOS system configuration files. Basically less boilerplate, as I said above.</p>
<h2 id="structure">Structure</h2>
<p>Let&rsquo;s have a look at the structure and explain briefly what&rsquo;s in it</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
</span></span><span class="line"><span class="cl">├── flake.lock
</span></span><span class="line"><span class="cl">├── flake.nix
</span></span><span class="line"><span class="cl">├── homes
</span></span><span class="line"><span class="cl">│  ├── x86-64-install-iso
</span></span><span class="line"><span class="cl">│  └── x86_64-linux
</span></span><span class="line"><span class="cl">├── lib
</span></span><span class="line"><span class="cl">│  └── module
</span></span><span class="line"><span class="cl">├── modules
</span></span><span class="line"><span class="cl">│  ├── home
</span></span><span class="line"><span class="cl">│  │  ├── browsers
</span></span><span class="line"><span class="cl">│  │  ├── cli
</span></span><span class="line"><span class="cl">│  │  ├── desktops
</span></span><span class="line"><span class="cl">│  │  ├── programs
</span></span><span class="line"><span class="cl">│  │  ├── secrets.yaml
</span></span><span class="line"><span class="cl">│  │  ├── security
</span></span><span class="line"><span class="cl">│  │  ├── services
</span></span><span class="line"><span class="cl">│  │  ├── suites
</span></span><span class="line"><span class="cl">│  │  ├── systems
</span></span><span class="line"><span class="cl">│  │  └── user
</span></span><span class="line"><span class="cl">│  └── nixos
</span></span><span class="line"><span class="cl">│     ├── cli
</span></span><span class="line"><span class="cl">│     ├── hardware
</span></span><span class="line"><span class="cl">│     ├── secrets.yaml
</span></span><span class="line"><span class="cl">│     ├── security
</span></span><span class="line"><span class="cl">│     ├── services
</span></span><span class="line"><span class="cl">│     ├── suites
</span></span><span class="line"><span class="cl">│     ├── system
</span></span><span class="line"><span class="cl">│     └── user
</span></span><span class="line"><span class="cl">├── packages
</span></span><span class="line"><span class="cl">├── shells
</span></span><span class="line"><span class="cl">└── systems
</span></span><span class="line"><span class="cl">   ├── x86_64-install-iso
</span></span><span class="line"><span class="cl">   └── x86_64-linux
</span></span><span class="line"><span class="cl">      ├── framework
</span></span><span class="line"><span class="cl">      ├── vm
</span></span><span class="line"><span class="cl">      └── workstation
</span></span></code></pre></div><ul>
<li>flake.nix: Entry point for the configuration</li>
<li>homes: home manager configuration for each device</li>
<li>modules: Specific Nix configuration, anything shared between multiple devices split into home-manager and NixOS modules</li>
<li>packages: Nix packages specific to me, some of these are those not available on nixpkgs yet. Some are specific to me, like wallpaper or fonts</li>
<li>shell: The devshell for this project</li>
<li>systems: The NixOS configuration for each device</li>
</ul>
<p>Taking a deeper dive into my configuration into what is going on each folder.</p>
<h3 id="modules">Modules</h3>
<p>The main part of my configuration, contains all the re-usable bits of my config. That can be shared, between
multiple devices. Let&rsquo;s see what I mean.</p>
<p>First of all, it is broken down into two parts, one for my NixOS specific config and one for home-manager. As before
I try to put as much of my config into the <code>modules/home</code> part because it means I can configure more of my machine
using Nix that doesn&rsquo;t use NixOS. Like my Ubuntu work laptop.</p>
<h4 id="nixos">NixOS</h4>
<p>I tried to split into various sub folders relating to what that config is related to, for example CLI tooling.
<code>moudles/nixos/cli/programs/nh/default.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="o">.</span><span class="n">nixicle</span><span class="p">;</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">cfg</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">cli</span><span class="o">.</span><span class="n">programs</span><span class="o">.</span><span class="n">nh</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">cli</span><span class="o">.</span><span class="n">programs</span><span class="o">.</span><span class="n">nh</span> <span class="o">=</span> <span class="k">with</span> <span class="n">types</span><span class="p">;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable</span> <span class="o">=</span> <span class="n">mkBoolOpt</span> <span class="no">false</span> <span class="s2">&#34;Whether or not to enable nh.&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">mkIf</span> <span class="n">cfg</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">programs</span><span class="o">.</span><span class="n">nh</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">      <span class="n">clean</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="cl">      <span class="n">clean</span><span class="o">.</span><span class="n">extraArgs</span> <span class="o">=</span> <span class="s2">&#34;--keep-since 4d --keep 3&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">flake</span> <span class="o">=</span> <span class="s2">&#34;/home/</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">/dotfiles&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This is the general format of all of my files. Where we need to manually enable all the various modules we want to use.
To reduce boilerplate because often similar devices will want the same modules, think of them as &ldquo;features&rdquo;. I have
the concept of <code>suites</code>. I don&rsquo;t have many suites, but if we have a look at the common and desktop suites as an example.
<code>modules/nixos/suites/common/default.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="p">;</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">cfg</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">suites</span><span class="o">.</span><span class="n">common</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">suites</span><span class="o">.</span><span class="n">common</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable</span> <span class="o">=</span> <span class="n">mkEnableOption</span> <span class="s2">&#34;Enable common configuration&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">mkIf</span> <span class="n">cfg</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">nix</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="cl">    <span class="n">hardware</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">audio</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="cl">      <span class="n">bluetooth</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="cl">      <span class="n">networking</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">services</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">openssh</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">security</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">sops</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="cl">      <span class="n">yubikey</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">system</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">boot</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">        <span class="n">plymouth</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">fonts</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="cl">      <span class="n">locale</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>These are modules that most of my devices will enable and use. Which enable modules similar to the one we saw for <code>nh</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="o">.</span><span class="n">nixicle</span><span class="p">;</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">cfg</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">suites</span><span class="o">.</span><span class="n">desktop</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">suites</span><span class="o">.</span><span class="n">desktop</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable</span> <span class="o">=</span> <span class="n">mkEnableOption</span> <span class="s2">&#34;Enable desktop configuration&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">mkIf</span> <span class="n">cfg</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">suites</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">common</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="cl">
</span></span><span class="line"><span class="cl">      <span class="n">desktop</span><span class="o">.</span><span class="n">addons</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">nautilus</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">hardware</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">logitechMouse</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="cl">      <span class="n">zsa</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">services</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">nixicle</span><span class="o">.</span><span class="n">avahi</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="cl">      <span class="n">backup</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="cl">      <span class="n">vpn</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="cl">      <span class="n">virtualisation</span><span class="o">.</span><span class="n">podman</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">cli</span><span class="o">.</span><span class="n">programs</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">nh</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="cl">      <span class="n">nix-ld</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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">user</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">initialPassword</span> <span class="o">=</span> <span class="s2">&#34;1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then we can also see, the <code>desktop</code> suite using the common suite and extending with more config modules I will want.
Like enabling Podman, backups and a VPN. Things I want across all of my Desktops.</p>
<p>That&rsquo;s the main bit! These are just modules that are then imported, and we will see this a bit later. The NixOS stuff
doesn&rsquo;t tend to change much, and it mostly the same across all of my devices that run NixOS.</p>
<h4 id="home">home</h4>
<p>The main bit of my config as with my old config relates to home-manager, again so I can use this config also on non
NixOS devices. The structure here is much the same. Except there is a lot more choice and modules not turned on.</p>
<p>Such as <code>modules/home/cli/terminals/</code> contains all the terminals I could use on my device. Though usually, we only
have one enabled at a time, but the choice is there if we want it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">  alacritty/
</span></span><span class="line"><span class="cl">  foot/
</span></span><span class="line"><span class="cl">  kitty/
</span></span><span class="line"><span class="cl">  wezterm/
</span></span></code></pre></div><p>Each config looks pretty similar to other ones we saw above:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="o">.</span><span class="n">nixicle</span><span class="p">;</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">cfg</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">cli</span><span class="o">.</span><span class="n">terminals</span><span class="o">.</span><span class="n">foot</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">cli</span><span class="o">.</span><span class="n">terminals</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="k">with</span> <span class="n">types</span><span class="p">;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable</span> <span class="o">=</span> <span class="n">mkBoolOpt</span> <span class="no">false</span> <span class="s2">&#34;enable foot terminal emulator&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">mkIf</span> <span class="n">cfg</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">programs</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">      <span class="n">catppuccin</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="cl">
</span></span><span class="line"><span class="cl">      <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">main</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">term</span> <span class="o">=</span> <span class="s2">&#34;foot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">font</span> <span class="o">=</span> <span class="s2">&#34;MonoLisa Nerd Font:size=14; Noto Color Emoji:size=20&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">shell</span> <span class="o">=</span> <span class="s2">&#34;fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">pad</span> <span class="o">=</span> <span class="s2">&#34;30x30&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">selection-target</span> <span class="o">=</span> <span class="s2">&#34;clipboard&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">scrollback</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">lines</span> <span class="o">=</span> <span class="mi">10000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>We can enable it using <code>cli.terminals.foot.enable = true;</code>, in our home-manager config. We also have a bunch of suites
we can use with this config.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">  common/
</span></span><span class="line"><span class="cl">  desktop/
</span></span><span class="line"><span class="cl">  development/
</span></span><span class="line"><span class="cl">  gaming/
</span></span><span class="line"><span class="cl">  guis/
</span></span><span class="line"><span class="cl">  streaming/
</span></span></code></pre></div><p>We can turn them on depending on the device. Such as on my work laptop, I will not use the gaming suite. If we look
at the <code>modules/home/suites/development/default.nix</code> file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="p">;</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">cfg</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">suites</span><span class="o">.</span><span class="n">development</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">suites</span><span class="o">.</span><span class="n">development</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable</span> <span class="o">=</span> <span class="n">mkEnableOption</span> <span class="s2">&#34;Enable development configuration&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">mkIf</span> <span class="n">cfg</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">suites</span><span class="o">.</span><span class="n">common</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="cl">
</span></span><span class="line"><span class="cl">    <span class="n">cli</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">editors</span><span class="o">.</span><span class="n">nvim</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="cl">      <span class="n">multiplexers</span><span class="o">.</span><span class="n">zellij</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="cl">
</span></span><span class="line"><span class="cl">      <span class="n">programs</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">attic</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="cl">        <span class="n">atuin</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="cl">        <span class="n">bat</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="cl">        <span class="n">bottom</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="cl">        <span class="n">direnv</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="cl">        <span class="n">eza</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="cl">        <span class="n">fzf</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="cl">        <span class="n">git</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="cl">        <span class="n">gpg</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="cl">        <span class="n">k8s</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="cl">        <span class="n">modern-unix</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="cl">        <span class="n">network-tools</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="cl">        <span class="n">nix-index</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="cl">        <span class="n">podman</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="cl">        <span class="n">ssh</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="cl">        <span class="n">starship</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="cl">        <span class="n">yazi</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="cl">        <span class="n">zoxide</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>We can see here I am enabling most of the CLI tooling I want available one by one. This allows us to turn them off
on certain machines, if we want to overwrite this, in a specific device config.</p>
<h5 id="neovim">Neovim</h5>
<p>A decent part of my home-manager config is configuring Neovim. I use Neovim btw!!!! ;) And I use NixOS btw!!!! And I
used to use Arch btw!!!! Okay, with those important details out of the way. As I said before, I had a bunch of imports
but now in each folder we have a <code>default.nix</code> which contains this import:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">snowfall</span><span class="o">.</span><span class="n">fs</span><span class="o">.</span><span class="n">get-non-default-nix-files</span> <span class="sr">./.</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>So we may have something <code>nvim/editor/default.nix</code> and this will import everything in <code>nvim/editor/</code> folder.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">  default.nix
</span></span><span class="line"><span class="cl">  focus.nix
</span></span><span class="line"><span class="cl">  telescope.nix
</span></span><span class="line"><span class="cl">  trouble.nix
</span></span></code></pre></div><h3 id="shell">Shell</h3>
<p>We can set up development shells as well, for example to create a default devshell we can do this at <code>shells/default/default.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span><span class="p">}:</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">json2nix</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">writeScriptBin</span> <span class="s2">&#34;json2nix&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">python3</span><span class="si">}</span><span class="s1">/bin/python </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fetchurl</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://gitlab.com/-/snippets/3613708/raw/main/json2nix.py&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">hash</span> <span class="o">=</span> <span class="s2">&#34;sha256-zZeL3JwwD8gmrf+fG/SPP51vOOUuhsfcQuMj6HNfppU=&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span><span class="si">}</span><span class="s1"> $@
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">yaml2nix</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">writeScriptBin</span> <span class="s2">&#34;yaml2nix&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    nix run github:euank/yaml2nix &#39;.args&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">.</span><span class="n">mkShell</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">NIX_CONFIG</span> <span class="o">=</span> <span class="s2">&#34;extra-experimental-features = nix-command flakes repl-flake&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <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></span><span class="line"><span class="cl">      <span class="n">yaml2nix</span>
</span></span><span class="line"><span class="cl">      <span class="n">json2nix</span>
</span></span><span class="line"><span class="cl">      <span class="n">statix</span>
</span></span><span class="line"><span class="cl">      <span class="n">deadnix</span>
</span></span><span class="line"><span class="cl">      <span class="n">alejandra</span>
</span></span><span class="line"><span class="cl">      <span class="n">home-manager</span>
</span></span><span class="line"><span class="cl">      <span class="n">git</span>
</span></span><span class="line"><span class="cl">      <span class="n">sops</span>
</span></span><span class="line"><span class="cl">      <span class="n">ssh-to-age</span>
</span></span><span class="line"><span class="cl">      <span class="n">gnupg</span>
</span></span><span class="line"><span class="cl">      <span class="n">age</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span></code></pre></div><p>We can then load into this using <code>nix develop</code>, or use direnv. Where we have a <code>.envrc</code> file with the contents:</p>
<pre tabindex="0"><code>use flake
</code></pre><p>Which will load into our devshell for us when we change into this folder. We will have all of the above packages made
available for this project.</p>
<h3 id="systems">Systems</h3>
<p>These are first split into by architecture, then the hostname of the machine <code>systems/x86_64-linux/workstation/default.nix</code>:</p>
<p>Before, my specific system configuration look something like this</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hardware</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">framework-12th-gen-intel</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">disko</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">disko</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">./hardware-configuration.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./disks.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/global</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/users/haseeb.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/backup.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/fingerprint.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/docker.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/fonts.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/pipewire.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/greetd.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/quietboot.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/vfio.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/vpn.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/pam.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/grub.nix</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">networking</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">hostName</span> <span class="o">=</span> <span class="s2">&#34;framework&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><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;23.05&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>And now it looks like, we can see far fewer imports, and then I turn on some specific modules to this system.
I like this approach because is it easier to make changes per system if I want. Such as not turning on the gaming suite
on my Laptop, say just my PC.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./hardware-configuration.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./disks.nix</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">services</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">virtualisation</span><span class="o">.</span><span class="n">kvm</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="cl">    <span class="n">hardware</span><span class="o">.</span><span class="n">openrgb</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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">suites</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">gaming</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="cl">    <span class="n">desktop</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">      <span class="n">addons</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">hyprland</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><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;workstation&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><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;23.11&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="homes">homes</h3>
<p>This is very similar to the systems <code>homes/x86_64-linux/haseeb@workstation/default.nix</code>, now we split using <code>username@hostname</code>.
When we build our NixOS config it will either match on <code>workstation</code> or the username we are logged in as, i.e. <code>haseeb</code>.</p>
<p>Having a look at before and after, here I was already using modules options to enable and disable certain packages/tools.
Unliked in our NixOS specific config above (systems).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">lib</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../home-manager</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../home-manager/programs/gaming.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../home-manager/programs/discord</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">modules</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">browsers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">firefox</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">editors</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">nvim</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">multiplexers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">zellij</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">shells</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">fish</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">wms</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">hyprland</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">terminals</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">wezterm</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">my</span><span class="o">.</span><span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">wallpaper</span> <span class="o">=</span> <span class="s2">&#34;~/dotfiles/home-manager/wallpapers/Kurzgesagt-Galaxy_2.png&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">host</span> <span class="o">=</span> <span class="s2">&#34;desktop&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">default</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">shell</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="si">}</span><span class="s2">/bin/fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">terminal</span> <span class="o">=</span> <span class="s2">&#34;wezterm&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">browser</span> <span class="o">=</span> <span class="s2">&#34;firefox&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">editor</span> <span class="o">=</span> <span class="s2">&#34;nvim&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">colorscheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">catppuccin-mocha</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">home</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">username</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">homeDirectory</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;/home/</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">home</span><span class="o">.</span><span class="n">username</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">stateVersion</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;23.11&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The new version looks something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">cli</span><span class="o">.</span><span class="n">programs</span><span class="o">.</span><span class="n">git</span><span class="o">.</span><span class="n">allowedSigners</span> <span class="o">=</span> <span class="s2">&#34;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINP5gqbEEj+pykK58djSI1vtMtFiaYcygqhHd3mzPbSt hello@haseebmajid.dev&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">suites</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">desktop</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="cl">    <span class="n">gaming</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="cl">    <span class="n">streaming</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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">desktops</span><span class="o">.</span><span class="n">hyprland</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="cl">
</span></span><span class="line"><span class="cl">  <span class="n">nixicle</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">&#34;23.11&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Here we could again use something <code>my.settings</code> though so we can change the default terminal in one place and reference
it everywhere. However, we could overwrite some of these setting as well, such as on certain devices I am using an older
version of Hyprland and don&rsquo;t have <code>bindi</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">waybar</span><span class="o">.</span><span class="n">package</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">waybar</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">waybar</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">keyBinds</span><span class="o">.</span><span class="n">bindi</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkForce</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Or tying waybar to a specific version of our inputs, again because I&rsquo;m using an older version of Hyprland.</p>
<h2 id="summary">Summary</h2>
<p>So to summarise I migrated my config to use snowfall-lib, which remove boilerplate and gives me a super opinionated
layout for my config. Alongside this, using some of the example config below, I made all of my modules now into something
we need to enable. Making it way easier to turn on &ldquo;features&rdquo; in my nix config.</p>
<p><img
        loading="lazy"
        src="/posts/2024-04-28-part-5-nix-as-part-of-your-development-workflow/images/i-use-nix-btw.jpg"
        type=""
        alt="I use Nix btw"
        
      /></p>
<h2 id="example-configuration">Example Configuration</h2>
<p>Some example configurations that I used as inspiration and to help me update my config.</p>
<ul>
<li><a href="https://github.com/jakehamilton/config">https://github.com/jakehamilton/config</a></li>
<li><a href="https://github.com/IogaMaster/dotfiles">https://github.com/IogaMaster/dotfiles</a></li>
<li><a href="https://github.com/khaneliman/khanelinix">https://github.com/khaneliman/khanelinix</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Fix Neorg Metadata Treesitter Issues With Nixvim</title>
      <link>https://haseebmajid.dev/posts/2024-04-21-til-how-to-fix-neorg-metadata-treesitter-issues-with-nixvim/</link>
      <pubDate>Sun, 21 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-04-21-til-how-to-fix-neorg-metadata-treesitter-issues-with-nixvim/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Fix Neorg Metadata Tree Sitter Issues With NixVim&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are like me, you may be configuring your Neovim configuration using NixVim. Which is a &amp;ldquo;framework&amp;rdquo; making it
easier to configure Neovim using mostly Nix configuration. Allowing us to keep most of our config in one language,
at least in my case.&lt;/p&gt;
&lt;p&gt;I started using Neorg to manage my notes and to-do lists in my &amp;ldquo;second-brain&amp;rdquo;, but noticed that the metadata part
was not being highlighted as I expected.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Fix Neorg Metadata Tree Sitter Issues With NixVim</strong></p>
<p>If you are like me, you may be configuring your Neovim configuration using NixVim. Which is a &ldquo;framework&rdquo; making it
easier to configure Neovim using mostly Nix configuration. Allowing us to keep most of our config in one language,
at least in my case.</p>
<p>I started using Neorg to manage my notes and to-do lists in my &ldquo;second-brain&rdquo;, but noticed that the metadata part
was not being highlighted as I expected.</p>
<p>My config looked something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">nixvim</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugins</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">neorg</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">        <span class="n">lazyLoading</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">treesitter</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">grammarPackages</span> <span class="o">=</span> <span class="k">with</span> <span class="n">config</span><span class="o">.</span><span class="n">programs</span><span class="o">.</span><span class="n">nixvim</span><span class="o">.</span><span class="n">plugins</span><span class="o">.</span><span class="n">treesitter</span><span class="o">.</span><span class="n">package</span><span class="o">.</span><span class="n">builtGrammars</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="n">norg</span>
</span></span><span class="line"><span class="cl">        <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Turns out there is another tree sitter package for the n
Neorg metadata, but this is not available with nvim-treesitter.
Hence, also not available with Nixvim. I was able to resolve my issue my using the tree-sitter specific grammar like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">nixvim</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugins</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">neorg</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">        <span class="n">lazyLoading</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">treesitter</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl">        <span class="n">grammarPackages</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">tree-sitter-grammars</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line hl"><span class="cl">          <span class="n">tree-sitter-norg</span>
</span></span><span class="line hl"><span class="cl">          <span class="n">tree-sitter-norg-meta</span>
</span></span><span class="line hl"><span class="cl">        <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>It looks like this. That&rsquo;s it!</p>
<p><img
        loading="lazy"
        src="/posts/2024-04-21-til-how-to-fix-neorg-metadata-treesitter-issues-with-nixvim/images/neorg-metadata.png"
        type=""
        alt="Neorg Metadata"
        
      /></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Set up Layouts in Zellij That Use Direnv and Nix</title>
      <link>https://haseebmajid.dev/posts/2024-03-18-til-how-to-setup-layouts-in-zellij-that-use-direnv-and-nix/</link>
      <pubDate>Mon, 18 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-03-18-til-how-to-setup-layouts-in-zellij-that-use-direnv-and-nix/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Set up Layouts in Zellij That Use Direnv and Nix&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have been using &lt;a href=&#34;https://github.com/zellij-org/zellij&#34;&gt;Zellij&lt;/a&gt; for a while now. I tried to set up layouts for
one of my personal projects. So that we could have tests and linting running and any other tasks we may want
whilst doing development &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;However, I had an issue working out how to call commands that required direnv and nix to set up development environments.
In my case, my nix dev shell installed the go-task tool to run tasks such as &lt;code&gt;task lint&lt;/code&gt; or &lt;code&gt;task tests&lt;/code&gt;. However
the shell that zellij was running the commands in for the layout did not load my Nix dev shell, so the go-task binary
was not available.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Set up Layouts in Zellij That Use Direnv and Nix</strong></p>
<p>I have been using <a href="https://github.com/zellij-org/zellij">Zellij</a> for a while now. I tried to set up layouts for
one of my personal projects. So that we could have tests and linting running and any other tasks we may want
whilst doing development <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>However, I had an issue working out how to call commands that required direnv and nix to set up development environments.
In my case, my nix dev shell installed the go-task tool to run tasks such as <code>task lint</code> or <code>task tests</code>. However
the shell that zellij was running the commands in for the layout did not load my Nix dev shell, so the go-task binary
was not available.</p>
<p>So to fix this, we need to do something like this <code>layout.kdl</code>:</p>
<pre tabindex="0"><code class="language-kdl" data-lang="kdl">layout {
    pane size=1 borderless=true {
        plugin location=&#34;zellij:tab-bar&#34;
    }
    pane {
        command &#34;fish&#34;
        args &#34;-c&#34; &#34;direnv exec . task lint&#34;
    }
    pane {
        command &#34;fish&#34;
        args &#34;-c&#34; &#34;direnv exec . task tests&#34;
    }
    pane {
        command &#34;docker-compose&#34;
        args &#34;up&#34; &#34;--build -d&#34;
    }
}
</code></pre><p>Where the key being we need to execute the direnv environment i.e. <code>direnv exec .</code>, then we can run commands like
normal. Where direnv <code>.envrc</code> file contains <code>use flake</code>. That&rsquo;s it! If you want Zellij to use direnv and load your
nix flake dev shell, you have to add a bit of boilerplate, which is not ideal but</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://github.com/zellij-org/zellij/issues/2294">https://github.com/zellij-org/zellij/issues/2294</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: Clean Up Tmux Service When Removed by Home Manager</title>
      <link>https://haseebmajid.dev/posts/2024-03-10-til-clean-up-tmux-service-when-removed-by-home-manager/</link>
      <pubDate>Sun, 10 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-03-10-til-clean-up-tmux-service-when-removed-by-home-manager/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: Clean Up Tmux Service When Removed by Home Manager&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently I stopped using tmux to try zellij, however I noticed when I removed tmux from my nix config. I was getting
the following error, when rebuilding my home-manager config:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;The user systemd session is degraded:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UNIT         LOAD   ACTIVE SUB    DESCRIPTION
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;● tmux.service loaded failed failed tmux default session &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;detached&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Legend: LOAD   → Reflects whether the unit definition was properly loaded.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        SUB    → The low-level unit activation state, values depend on unit type.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was wondering where this error was coming from, turns it the symlink to tmux.service has not been deleted that
nix would create.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: Clean Up Tmux Service When Removed by Home Manager</strong></p>
<p>Recently I stopped using tmux to try zellij, however I noticed when I removed tmux from my nix config. I was getting
the following error, when rebuilding my home-manager config:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">The user systemd session is degraded:
</span></span><span class="line"><span class="cl">  UNIT         LOAD   ACTIVE SUB    DESCRIPTION
</span></span><span class="line"><span class="cl">● tmux.service loaded failed failed tmux default session <span class="o">(</span>detached<span class="o">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Legend: LOAD   → Reflects whether the unit definition was properly loaded.
</span></span><span class="line"><span class="cl">        ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
</span></span><span class="line"><span class="cl">        SUB    → The low-level unit activation state, values depend on unit type.
</span></span></code></pre></div><p>I was wondering where this error was coming from, turns it the symlink to tmux.service has not been deleted that
nix would create.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ls -al ~/.config/systemd/user/tmux.service
</span></span><span class="line"><span class="cl">Permissions Size User        Group       Date Modified Name
</span></span><span class="line"><span class="cl">.rw-rw-r--   <span class="m">453</span> haseebmajid haseebmajid <span class="m">22</span> Aug  <span class="m">2023</span>   /home/haseebmajid/.config/systemd/user/tmux.service
</span></span></code></pre></div><p>If we look at other systemd services we can see them symlinked to a nix package in the nix store.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ls -al ~/.config/systemd/user
</span></span><span class="line"><span class="cl">lrwxrwxrwx     - haseebmajid haseebmajid <span class="m">20</span> Feb 17:04   spotifyd.service -&gt; /nix/store/7v52bpcyi0zqv012rrmd7s2r742hb2cy-home-manager-files/.config/systemd/user/spotifyd.service
</span></span><span class="line"><span class="cl">lrwxrwxrwx     - haseebmajid haseebmajid <span class="m">20</span> Feb 17:04   swayidle.service -&gt; /nix/store/7v52bpcyi0zqv012rrmd7s2r742hb2cy-home-manager-files/.config/systemd/user/swayidle.service
</span></span></code></pre></div><p>So we can simply remove the tmux file, <code>rm ~/.config/systemd/user/tmux.service</code>. I should look into why this symlink
is not removed.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Add New Vim Plugins to nixpkgs Repository</title>
      <link>https://haseebmajid.dev/posts/2024-02-20-til-how-to-add-new-vim-plugins-to-nixpkgs-repository/</link>
      <pubDate>Tue, 20 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-02-20-til-how-to-add-new-vim-plugins-to-nixpkgs-repository/</guid>
      <description>&lt;p&gt;Recently, I wanted to add a Neovim plugin to nixpkgs, so I can then add it to NixVim. I tried following the guide
from the &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/vim.section.md#adding-new-plugins-to-nixpkgs-adding-new-plugins-to-nixpkgs&#34;&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, I kept getting the following errors:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nix-shell -p vimPluginsUpdater --run vim-plugins-updater
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;error:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       … &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; calling the &lt;span class=&#34;s1&#34;&gt;&amp;#39;derivationStrict&amp;#39;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;builtin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         at /builtin/derivation.nix:9:12: &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; not available&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       … &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; evaluating derivation &lt;span class=&#34;s1&#34;&gt;&amp;#39;shell&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         whose name attribute is located at /nix/store/whhzjfgalghpm34irclh01c0afynmyll-nixpkgs/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:300:7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       … &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; evaluating attribute &lt;span class=&#34;s1&#34;&gt;&amp;#39;buildInputs&amp;#39;&lt;/span&gt; of derivation &lt;span class=&#34;s1&#34;&gt;&amp;#39;shell&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         at /nix/store/whhzjfgalghpm34irclh01c0afynmyll-nixpkgs/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:347:7:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          346&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;       &lt;span class=&#34;nv&#34;&gt;depsHostHost&lt;/span&gt;                &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; lib.elemAt &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;lib.elemAt dependencies 1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 0&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          347&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;       &lt;span class=&#34;nv&#34;&gt;buildInputs&lt;/span&gt;                 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; lib.elemAt &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;lib.elemAt dependencies 1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 1&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;       ^
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          348&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;       &lt;span class=&#34;nv&#34;&gt;depsTargetTarget&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; lib.elemAt &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;lib.elemAt dependencies 2&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 0&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       error: undefined variable &lt;span class=&#34;s1&#34;&gt;&amp;#39;vimPluginsUpdater&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       at «string»:1:107:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            1&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;...&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;@args: with import &amp;lt;nixpkgs&amp;gt; args&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pkgs.runCommandCC or pkgs.runCommand&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;shell&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;buildInputs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;vimPluginsUpdater&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or I was getting 429 network errors, too many requests to GitHub.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently, I wanted to add a Neovim plugin to nixpkgs, so I can then add it to NixVim. I tried following the guide
from the <a href="https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/vim.section.md#adding-new-plugins-to-nixpkgs-adding-new-plugins-to-nixpkgs">docs</a>.</p>
<p>However, I kept getting the following errors:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nix-shell -p vimPluginsUpdater --run vim-plugins-updater
</span></span><span class="line"><span class="cl">error:
</span></span><span class="line"><span class="cl">       … <span class="k">while</span> calling the <span class="s1">&#39;derivationStrict&#39;</span> <span class="nb">builtin</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">         at /builtin/derivation.nix:9:12: <span class="o">(</span><span class="nb">source</span> not available<span class="o">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">       … <span class="k">while</span> evaluating derivation <span class="s1">&#39;shell&#39;</span>
</span></span><span class="line"><span class="cl">         whose name attribute is located at /nix/store/whhzjfgalghpm34irclh01c0afynmyll-nixpkgs/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:300:7
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">       … <span class="k">while</span> evaluating attribute <span class="s1">&#39;buildInputs&#39;</span> of derivation <span class="s1">&#39;shell&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">         at /nix/store/whhzjfgalghpm34irclh01c0afynmyll-nixpkgs/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:347:7:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">          346<span class="p">|</span>       <span class="nv">depsHostHost</span>                <span class="o">=</span> lib.elemAt <span class="o">(</span>lib.elemAt dependencies 1<span class="o">)</span> 0<span class="p">;</span>
</span></span><span class="line"><span class="cl">          347<span class="p">|</span>       <span class="nv">buildInputs</span>                 <span class="o">=</span> lib.elemAt <span class="o">(</span>lib.elemAt dependencies 1<span class="o">)</span> 1<span class="p">;</span>
</span></span><span class="line"><span class="cl">             <span class="p">|</span>       ^
</span></span><span class="line"><span class="cl">          348<span class="p">|</span>       <span class="nv">depsTargetTarget</span>            <span class="o">=</span> lib.elemAt <span class="o">(</span>lib.elemAt dependencies 2<span class="o">)</span> 0<span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">       error: undefined variable <span class="s1">&#39;vimPluginsUpdater&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">       at «string»:1:107:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            1<span class="p">|</span> <span class="o">{</span>...<span class="o">}</span>@args: with import &lt;nixpkgs&gt; args<span class="p">;</span> <span class="o">(</span>pkgs.runCommandCC or pkgs.runCommand<span class="o">)</span> <span class="s2">&#34;shell&#34;</span> <span class="o">{</span> <span class="nv">buildInputs</span> <span class="o">=</span> <span class="o">[</span> <span class="o">(</span>vimPluginsUpdater<span class="o">)</span> <span class="o">]</span><span class="p">;</span> <span class="o">}</span> <span class="s2">&#34;&#34;</span>
</span></span></code></pre></div><p>Or I was getting 429 network errors, too many requests to GitHub.</p>
<h2 id="solution">Solution</h2>
<p>I found this great person who was able to solve my issue on <a href="https://discourse.nixos.org/t/adding-new-neovim-to-nixpkgs/34834/2">discourse</a>.
Assuming you have a fork of nixpkgs and have to clone it locally, i.e. <code>git clone https://github.com/hmajid2301/nixpkgs.git</code></p>
<ol>
<li>Update <code>nixpkgs/pkgs/applications/editors/vim/plugins/vim-plugin-names</code></li>
<li>Can do this using the <code>./update.py add &quot;gbprod/yanky.nvim&quot;</code> (where <code>gbprod/yanky.nvim</code> is the path to git repository)</li>
<li>Export your GitHub Personal Token</li>
<li>You can create one by following <a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic">this link</a></li>
<li><code>export GITHUB_API_TOKEN=your_token</code></li>
<li>I will do a post in the future about how you can do this in fish shell and keep secrets out of your shell history.</li>
<li><code>nix-shell -I nixpkgs=channel:nixpkgs-unstable -p vimPluginsUpdater --run vim-plugins-updater</code></li>
<li>Make sure to run this in the repository root</li>
<li>Push your changes and create a PR with nixpkgs repo</li>
<li>You will likely need to rebase your commits to follow the contribution guidelines, check those when creating the PR</li>
</ol>
<p>That&rsquo;s it! I am not sure if this will be useful for others (I will most likely reference this myself in the future), but
that&rsquo;s the easiest way I found to add new vim plugins to nixpkgs.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Get sops-nix Working with home-manager Modules</title>
      <link>https://haseebmajid.dev/posts/2024-01-28-how-to-get-sops-nix-working-with-home-manager-modules/</link>
      <pubDate>Sun, 28 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2024-01-28-how-to-get-sops-nix-working-with-home-manager-modules/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this article, I will go over how to get &lt;a href=&#34;https://github.com/Mic92/sops-nix&#34;&gt;sops-nix&lt;/a&gt; to work properly with
home-manager. One issue I noticed was that when I used with home-manager modules/options, I would see a string
like &amp;ldquo;%r/secrets/haseeb/&amp;hellip;&amp;rdquo;. The &lt;code&gt;%r&lt;/code&gt; would not be replaced.&lt;/p&gt;
&lt;p&gt;Relevant Issue: &lt;a href=&#34;https://github.com/Mic92/sops-nix/issues/28&#34;&gt;https://github.com/Mic92/sops-nix/issues/28&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;assumption&#34;&gt;Assumption&lt;/h2&gt;
&lt;p&gt;I will assume you have already setup sops-nix and are using it. In the sense, you have a &lt;code&gt;.sops.yaml&lt;/code&gt; file and are already
using it with NixOS. The instructions in the README is mostly pretty clear how to get setup, but I may in future
create another article how I set up sops-nix. But in this post, we will simply go over how we can make it work with
home-manager. I will also assume you are using nix flakes and have passed sops-nix as an input.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In this article, I will go over how to get <a href="https://github.com/Mic92/sops-nix">sops-nix</a> to work properly with
home-manager. One issue I noticed was that when I used with home-manager modules/options, I would see a string
like &ldquo;%r/secrets/haseeb/&hellip;&rdquo;. The <code>%r</code> would not be replaced.</p>
<p>Relevant Issue: <a href="https://github.com/Mic92/sops-nix/issues/28">https://github.com/Mic92/sops-nix/issues/28</a></p>
<h2 id="assumption">Assumption</h2>
<p>I will assume you have already setup sops-nix and are using it. In the sense, you have a <code>.sops.yaml</code> file and are already
using it with NixOS. The instructions in the README is mostly pretty clear how to get setup, but I may in future
create another article how I set up sops-nix. But in this post, we will simply go over how we can make it work with
home-manager. I will also assume you are using nix flakes and have passed sops-nix as an input.</p>
<h2 id="solution">Solution</h2>
<p>So I have a file called <code>home-manager/security/sops.nix</code> which looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">sops-nix</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">sops</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">sops</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">gnupg</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">home</span> <span class="o">=</span> <span class="s2">&#34;~/.gnupg&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">sshKeyPaths</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">defaultSymlinkPath</span> <span class="o">=</span> <span class="s2">&#34;/run/user/1000/secrets&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">defaultSecretsMountPoint</span> <span class="o">=</span> <span class="s2">&#34;/run/user/1000/secrets.d&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</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></span><span class="line"><span class="cl">    <span class="n">sops</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where the key bit to making it work is the <code>default</code> values here, which tell sops where to mount the secret in tmpfs.
The temporary file-system where are secrets will be stored in files.</p>
<pre tabindex="0"><code>ls -al /run/user/1000/secrets/atuin_key

Permissions Size User   Group Date Modified Name
.r--------   146 haseeb users 28 Jan 09:26   /run/user/1000/secrets/atuin_key
</code></pre><p>Other than that, we install sops so we can use the CLI tool to edit our sops files and add secrets. Where I have
a <code>home-manager/secrets.yaml</code> file for storing all secrets related to home-manager.</p>
<h3 id="atuin">Atuin</h3>
<p>So first I do <code>sops home-manager/secrets.yaml</code>, and add my Atuin secret encryption key to this file.
Having a look at how I use it in one of my modules, say <code>home-manager/programs/atuin.nix</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">atuin</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">      <span class="n">key_path</span> <span class="o">=</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">atuin_key</span><span class="o">.</span><span class="n">path</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">sops</span><span class="o">.</span><span class="n">secrets</span><span class="o">.</span><span class="n">atuin_key</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">sopsFile</span> <span class="o">=</span> <span class="sr">../secrets.yaml</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where we reference this secret in this module. Once this has been built using home manager, if we look at the config
for Atuin that is generated by nix. It will point to that <code>/run/user/1000/secrets/atuin_key</code> file.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Append to a Config Option String in Nix</title>
      <link>https://haseebmajid.dev/posts/2023-12-01-til-how-to-append-to-a-config-option-string-in-nix/</link>
      <pubDate>Fri, 01 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-12-01-til-how-to-append-to-a-config-option-string-in-nix/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Append to a Config Option String in Nix&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently on my laptop I had to add some extra config settings to my Hyprland config. Rather than polluting my
&lt;code&gt;hyprland.nix&lt;/code&gt; file with if, else depending on the host. I wanted to add the extra config in the &lt;code&gt;home.nix&lt;/code&gt; of the
host. So it&amp;rsquo;s contained within that host. Where my &lt;code&gt;home.nix&lt;/code&gt; is the entry point for my
home-manager config for that host.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Append to a Config Option String in Nix</strong></p>
<p>Recently on my laptop I had to add some extra config settings to my Hyprland config. Rather than polluting my
<code>hyprland.nix</code> file with if, else depending on the host. I wanted to add the extra config in the <code>home.nix</code> of the
host. So it&rsquo;s contained within that host. Where my <code>home.nix</code> is the entry point for my
home-manager config for that host.</p>
<p>My <code>hyprland.nix</code> looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">hyprland</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">  <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">     input {
</span></span></span><span class="line"><span class="cl"><span class="s1">        kb_layout = gb
</span></span></span><span class="line"><span class="cl"><span class="s1">        touchpad {
</span></span></span><span class="line"><span class="cl"><span class="s1">            disable_while_typing=false
</span></span></span><span class="line"><span class="cl"><span class="s1">        }
</span></span></span><span class="line"><span class="cl"><span class="s1">     }
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I want to add some extra config to the <code>extraConfig</code> option/attribute of this attribute set.
Then in my <code>home.nix</code> I added the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">extraConfig</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkAfter</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">  exec-once = /usr/libexec/geoclue-2.0/demos/agent
</span></span></span><span class="line"><span class="cl"><span class="s1">  exec-once = warp-taskbar
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">  bind=,XF86Launch5,exec,/usr/local/bin/swaylock -S
</span></span></span><span class="line"><span class="cl"><span class="s1">  bind=,XF86Launch4,exec,/usr/local/bin/swaylock -S
</span></span></span><span class="line"><span class="cl"><span class="s1">  bind=SUPER,backspace,exec,/usr/local/bin/swaylock -S
</span></span></span><span class="line"><span class="cl"><span class="s1">&#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>In this case we want to start some processes on this host, like showing warp in my taskbar.
The key line here being <code>lib.mkAfter</code>. Which will append the content after the existing config options we defined in <code>hyprland.nix</code></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Set the Path Variable When Using Ubuntu With Nix (Home Manager)</title>
      <link>https://haseebmajid.dev/posts/2023-11-25-til-how-to-set-the-path-variable-when-using-ubuntu-with-nix-home-manager/</link>
      <pubDate>Sat, 25 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-11-25-til-how-to-set-the-path-variable-when-using-ubuntu-with-nix-home-manager/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Set the Path Variable When Using Ubuntu With Nix (Home Manager)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As per some of my recent articles, you will be aware I am using Hyprland (tiling manager) on Ubuntu and managing the
config using nix (home-manager). I was having issues where for some reason it wouldn&amp;rsquo;t set the &lt;code&gt;PATH&lt;/code&gt; variable correctly.&lt;/p&gt;
&lt;p&gt;On my NixOS machine, the following would be fine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;,XF86AudioRaiseVolume,exec, volume --inc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;,XF86AudioLowerVolume,exec, volume --dec
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, on Ubuntu I needed to provide the full path:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Set the Path Variable When Using Ubuntu With Nix (Home Manager)</strong></p>
<p>As per some of my recent articles, you will be aware I am using Hyprland (tiling manager) on Ubuntu and managing the
config using nix (home-manager). I was having issues where for some reason it wouldn&rsquo;t set the <code>PATH</code> variable correctly.</p>
<p>On my NixOS machine, the following would be fine:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">bind</span><span class="o">=</span>,XF86AudioRaiseVolume,exec, volume --inc
</span></span><span class="line"><span class="cl"><span class="nv">bind</span><span class="o">=</span>,XF86AudioLowerVolume,exec, volume --dec
</span></span></code></pre></div><p>However, on Ubuntu I needed to provide the full path:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">bind</span><span class="o">=</span>,XF86AudioRaiseVolume,exec, <span class="si">${</span><span class="nv">volume</span><span class="si">}</span>/bin/volume --inc
</span></span></code></pre></div><p>So in the Hyprland config it would look like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">bind</span><span class="o">=</span>,XF86AudioRaiseVolume,exec, /nix/store/q1wm84g65smaq4agq7zp40q57x3534ni-volume/bin/volume --inc
</span></span></code></pre></div><p>It was because the session was being started by GDM (gnome), and the <code>PATH</code> variable was not being set properly.
In Wayland GDM picks up environment variables from <code>~/.config/environment.d/envvars.conf</code> <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> so we can add it here.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">❯ bat ~/.config/environment.d/envvars.conf --plain
</span></span><span class="line"><span class="cl"><span class="nv">PATH</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$PATH</span><span class="s2">:/home/haseebmajid/.nix-profile/bin&#34;</span>
</span></span></code></pre></div><p>Replace <code>haseebmajid</code> with your username (or I guess <code>$HOME</code> should work). This means when we run scripts now, it will
source them from this nix-profile folder. Where the binaries get symlinked, including the volume script above. So
now you don&rsquo;t need to specify the full path (though maybe you should 🤷)</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/9561a21fed329f25802290621a54588e314af1ee/home-manager/desktops/wms/hyprland.nix">Hyprland Config</a></li>
<li><a href="https://old.reddit.com/r/NixOS/comments/17rilhc/hyprlandsway_needs_full_path_to_scripts_on/">Reddit Thread</a></li>
<li><a href="https://discourse.nixos.org/t/hyprland-sway-need-full-path-to-scripts-on-non-nixos/35233">Discourse Thread</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://wiki.archlinux.org/title/environment_variables#Graphical_environment">https://wiki.archlinux.org/title/environment_variables#Graphical_environment</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>Part 3: Hyprland as Part of Your Development Workflow</title>
      <link>https://haseebmajid.dev/posts/2023-11-15-part-3-hyprland-as-part-of-your-development-workflow/</link>
      <pubDate>Wed, 15 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-11-15-part-3-hyprland-as-part-of-your-development-workflow/</guid>
      <description>&lt;h2 id=&#34;preamble&#34;&gt;Preamble&lt;/h2&gt;
&lt;p&gt;Now we have looked at our choice of hardware, which OS to use and specifically, how to configure NixOS (at a high-level),
using a git repository.&lt;/p&gt;
&lt;p&gt;In this part, we will go over which window manager to use. There are two main types we could use here. Either a desktop
environment like Gnome or KDE. Which comes with batteries included, it provides us with everything we need and we
don&amp;rsquo;t need to configure much to get stuff working. Things like a notification daemon, polkit (for auth).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="preamble">Preamble</h2>
<p>Now we have looked at our choice of hardware, which OS to use and specifically, how to configure NixOS (at a high-level),
using a git repository.</p>
<p>In this part, we will go over which window manager to use. There are two main types we could use here. Either a desktop
environment like Gnome or KDE. Which comes with batteries included, it provides us with everything we need and we
don&rsquo;t need to configure much to get stuff working. Things like a notification daemon, polkit (for auth).</p>
<p>Whereas in a more bare-bones window manager such as Hyprland, i3, Sway they are far more bare bones and we need to
setup a lot more things ourselves. They are more customisable but more effort to set up, they also tend to be more light
weight on resources.</p>
<p>In this section, we will look at using a tiling window manager <a href="https://wiki.hyprland.org/">Hyprland</a>,
though, you could also look at using <a href="https://swaywm.org/">Sway</a>.</p>
<h2 id="why-a-tiling-manager">Why a tiling manager?</h2>
<p>A tiling window manager is great because it handles placing our window automatically for us. This allows for more
efficient usage of our space. Rather than multiple overlapping windows, each window has its own space on the display.</p>
<p></p>
<p>It also makes it much easier to be keyboard-driven, so we need to rely on our mouse a lot less. We can use the keyboard
to swap between open windows. We can also open apps using a tool like <code>rofi</code> again from the keyboard. This just helps
us be quicker, not wasting time needing to reach for the mouse.</p>
<h2 id="why-hyprland">Why Hyprland?</h2>
<p>I mean, between Sway and Hyprland I don&rsquo;t think there is much difference, the main reason I chose to use Hyprland was because
I saw plenty of people ricing it on unixporn, especially with NixOS. So I used some of their setups as inspiration.</p>
<p>Hyprland also has a few nice compositor tweaks like transparency and animations. Which I think makes things more interesting.
But any other Wayland tiling manager will do, such as Sway or River. I don&rsquo;t have a super strong reason to use Hyprland.</p>
<p>Saying that, since plenty of people seem to be using it, it&rsquo;s easy to find example setups and copy them or nick bits I like.</p>
<h2 id="how-do-i-use-hyprland">How do I use Hyprland?</h2>
<p>So you may be wondering how does a window manager fits in to our development workflow. Specifically, a tiling window manager.
Typically, I will have 5–6 workspaces in use:</p>
<ul>
<li>1: Coding (main monitor)
<ul>
<li>Entirely dedicated to my code editor (Neovim in my terminal)
<ul>
<li>Usually has a few splits for different buffers</li>
</ul>
</li>
</ul>
</li>
<li>2: Firefox (secondary monitor)
<ul>
<li>Two Firefox windows
<ul>
<li>One playing random YouTube videos</li>
<li>The other with documentation or related to the work I am currently doing</li>
</ul>
</li>
</ul>
</li>
<li>3: Secondary project
<ul>
<li>Contains terminal with Neovim</li>
<li>Firefox window related to project</li>
</ul>
</li>
<li>4: Monkeytype
<ul>
<li>Firefox for me to practice my typing when I get bored</li>
</ul>
</li>
<li>5: Social Apps
<ul>
<li>Ferdi</li>
<li>Discord</li>
</ul>
</li>
<li>6: Gaming
<ul>
<li>Steam</li>
<li>Lutris</li>
</ul>
</li>
</ul>
<p>I mainly use workspace 1 &amp; 2, I also use <a href="https://github.com/ofirgall/tmux-browser">tmux-browser</a> which means
I can manage my browser tabs per tmux session (more on this in a future post). Where the open Firefox window will often
be one managed by tmux-browser.</p>
<h2 id="wayland">Wayland</h2>
<p>I have personally decided to try to use Wayland compilable window managers. I know people have issues with Wayland.
But for the most part, Wayland just seems to work fine for me. I originally swapped to Wayland because I had two monitors
and I wanted to set the refresh rate of each separately. Whereas XServer treats them as one display, so I had to set it
60Hz, but now I can have one monitor on 144Hz and another on 60Hz.</p>
<p>Note your mileage may vary, and you may well have issues with Wayland, especially if you are using an Nvidia GPU.</p>
<h1 id="setup">Setup</h1>
<p>One of the things I like about NixOS is it makes it straightforward to add new packages and config.</p>
<h2 id="flake-input">flake input</h2>
<p>First, update our flake inputs to add Hyprland.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">hyprland</span><span class="o">.</span><span class="n">url</span> <span class="err">=</span> <span class="s2">&#34;github:hyprwm/Hyprland&#34;</span><span class="p">;</span>
</span></span></code></pre></div><h2 id="home-manager">home-manager</h2>
<p>So, having a look at my <code>hyprland.nix</code> file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">config</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">pkgs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">laptop_lid_switch</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">writeShellScriptBin</span> <span class="s2">&#34;laptop_lid_switch&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    #!/usr/bin/env bash
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">    if grep open /proc/acpi/button/lid/LID0/state; then
</span></span></span><span class="line"><span class="cl"><span class="s1">        hyprctl keyword monitor &#34;eDP-1, 2256x1504@60, 0x0, 1&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">    else
</span></span></span><span class="line"><span class="cl"><span class="s1">        if [[ `hyprctl monitors | grep &#34;Monitor&#34; | wc -l` != 1 ]]; then
</span></span></span><span class="line"><span class="cl"><span class="s1">            hyprctl keyword monitor &#34;eDP-1, disable&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">        fi
</span></span></span><span class="line"><span class="cl"><span class="s1">    fi
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./common</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hypr-contrib</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="o">.</span><span class="n">grimblast</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="o">.</span><span class="n">xdg-desktop-portal-hyprland</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">nix</span><span class="o">.</span><span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">substituters</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;https://hyprland.cachix.org&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">trusted-public-keys</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">hyprland</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="c1"># TODO: move to https://github.com/spikespaz/hyprland-nix</span>
</span></span><span class="line"><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="cl"><span class="s1">      # ASCII Art from https://fsymbols.com/generators/carty/
</span></span></span><span class="line"><span class="cl"><span class="s1">      input {
</span></span></span><span class="line"><span class="cl"><span class="s1">      	kb_layout = gb
</span></span></span><span class="line"><span class="cl"><span class="s1">      	touchpad {
</span></span></span><span class="line"><span class="cl"><span class="s1">      		disable_while_typing=false
</span></span></span><span class="line"><span class="cl"><span class="s1">      	}
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      general {
</span></span></span><span class="line"><span class="cl"><span class="s1">      	gaps_in = 3
</span></span></span><span class="line"><span class="cl"><span class="s1">      	gaps_out = 5
</span></span></span><span class="line"><span class="cl"><span class="s1">      	border_size = 3
</span></span></span><span class="line"><span class="cl"><span class="s1">      	col.active_border=0xff</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorscheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      	col.inactive_border=0xff</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorscheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      decoration {
</span></span></span><span class="line"><span class="cl"><span class="s1">      	rounding=5
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      misc {
</span></span></span><span class="line"><span class="cl"><span class="s1">       vrr = 2
</span></span></span><span class="line"><span class="cl"><span class="s1">       disable_hyprland_logo = 1;
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      $notifycmd = notify-send -h string:x-canonical-private-synchronous:hypr-cfg -u low
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      # █▀ █░█ █▀█ █▀█ ▀█▀ █▀▀ █░█ ▀█▀ █▀
</span></span></span><span class="line"><span class="cl"><span class="s1">      # ▄█ █▀█ █▄█ █▀▄ ░█░ █▄▄ █▄█ ░█░ ▄█
</span></span></span><span class="line"><span class="cl"><span class="s1">      bind = SUPER, Return, exec, </span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">my</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">default</span><span class="o">.</span><span class="n">terminal</span><span class="si">}</span><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      bind = SUPER, b, exec, </span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">my</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">default</span><span class="o">.</span><span class="n">browser</span><span class="si">}</span><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">      bind = SUPER, a, exec, rofi -show drun -modi drun
</span></span></span><span class="line"><span class="cl"><span class="s1">      bind = ALT, Tab, exec, rofi -show window
</span></span></span><span class="line"><span class="cl"><span class="s1">      bind = SUPER, w, exec, makoctl dismiss
</span></span></span><span class="line"><span class="cl"><span class="s1">      # ...
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I cut out some config so it&rsquo;s easier to follow the file above. By going over it section by section:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">laptop_lid_switch</span> <span class="err">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">writeShellScriptBin</span> <span class="s2">&#34;laptop_lid_switch&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    #!/usr/bin/env bash
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">    if grep open /proc/acpi/button/lid/LID0/state; then
</span></span></span><span class="line"><span class="cl"><span class="s1">        hyprctl keyword monitor &#34;eDP-1, 2256x1504@60, 0x0, 1&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">    else
</span></span></span><span class="line"><span class="cl"><span class="s1">        if [[ `hyprctl monitors | grep &#34;Monitor&#34; | wc -l` != 1 ]]; then
</span></span></span><span class="line"><span class="cl"><span class="s1">            hyprctl keyword monitor &#34;eDP-1, disable&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">        fi
</span></span></span><span class="line"><span class="cl"><span class="s1">    fi
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span></code></pre></div><p>This first bit, a simple bash script which is used to switch off the display on a laptop when the lid is closed. We will
see how it is used later, we give it the name <code>laptop_lid_switch</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">imports</span> <span class="err">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./common</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="err">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="o">.</span><span class="n">xdg-desktop-portal-hyprland</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">nix</span><span class="o">.</span><span class="n">settings</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">substituters</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;https://hyprland.cachix.org&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">trusted-public-keys</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>The next bit, we import our packages <code>inputs.hyprland.homeManagerModules.default</code>, using the input we defined before.
Which handles things like creating a config file for us. I also have some common settings I like to share between
my window managers, like GTK settings.</p>
<p>Next, we install <code>xdg-desktop-portal-hyprland</code>, which lets other apps communicate with the compositor through d-bus.
Think for use cases like screen sharing.</p>
<blockquote>
<p>An XDG Desktop Portal (later called XDP) is a program that lets other applications communicate swiftly with the compositor through D-Bus.</p>
</blockquote>
<p>Then finally we set some nix settings, to point to a new binary cache to pull Hyprland dependencies from as they aren&rsquo;t
built on the normal nix cache. This saves us time building the Hyprland deps locally.</p>
<p>The next bit, we specify our Hyprland options in Nix:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">hyprland</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">      # ASCII Art from https://fsymbols.com/generators/carty/
</span></span></span><span class="line"><span class="cl"><span class="s1">      input {
</span></span></span><span class="line"><span class="cl"><span class="s1">      	kb_layout = gb
</span></span></span><span class="line"><span class="cl"><span class="s1">      	touchpad {
</span></span></span><span class="line"><span class="cl"><span class="s1">      		disable_while_typing=false
</span></span></span><span class="line"><span class="cl"><span class="s1">      	}
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>For now, using the options available in home-manager, I enable Hyprland. Then basically the rest of the config is in
<code>extraConfig</code>, we just pass it a string, and it writes it to the <code>~/.config/hypr/hyprland.conf</code>.
More options here: <a href="https://mipmip.github.io/home-manager-option-search/?query=hyprland">https://mipmip.github.io/home-manager-option-search/?query=hyprland</a></p>
<blockquote>
<p>At some point Hyprland may be configured differently using, <a href="https://github.com/spikespaz/hyprland-nix">https://github.com/spikespaz/hyprland-nix</a></p>
</blockquote>
<h4 id="config">config</h4>
<p>Going over the most interesting bits of my Hyprland config:</p>
<pre tabindex="0"><code>bind = SUPER, Return, exec, ${config.my.settings.default.terminal}
bind = SUPER, b, exec, ${config.my.settings.default.browser}
bind = SUPER, a, exec, rofi -show drun -modi drun
bind = ALT, Tab, exec, rofi -show window
</code></pre><p>Here we set some key bindings such as how to open my terminal and Rofi my app launcher. Probably my two most key bindings,
especially Rofi, how I open new apps in Hyprland.</p>
<pre tabindex="0"><code>windowrulev2 = fullscreen, title:^(Guild Wars 2)$
windowrulev2 = idleinhibit focus, class:^(mpv)$
windowrulev2 = idleinhibit fullscreen, class:^(firefox)$
</code></pre><p>Next, we define some exceptions to our rules, such as Guild Wars 2 (video game) starting in full-screen mode by default.
Then, if Firefox is in full screen, i.e. when watching a video, stop idling from occurring.</p>
<pre tabindex="0"><code>exec-once = swaync &amp;
exec-once = kanshi &amp;
exec-once = sway-audio-idle-inhibit -w &amp;
exec-once = waybar &amp;
exec-once = gammastep-indicator &amp;
exec-once = swaybg -i ${config.my.settings.wallpaper} --mode fill &amp;
</code></pre><p>Next we define a bunch of apps we want to be run on startup, such as swaync for notifications, swaybg for wallpaper
and gammastep-indicator to tell us when our blue light filter is on.</p>
<pre tabindex="0"><code>bindl=,switch:Lid Switch, exec, ${laptop_lid_switch}
</code></pre><p>Here, we use it to run our laptop lid switch script every time our laptop lid status changes.</p>
<pre tabindex="0"><code>bind=,XF86MonBrightnessUp,exec, brightness --inc
bind=,XF86MonBrightnessDown,exec, brightness --dec
bind=,XF86AudioRaiseVolume,exec, volume --inc
bind=,XF86AudioLowerVolume,exec, volume --dec
bind=,XF86AudioMute,exec, volume --toggle
bind=,XF86AudioMicMute,exec, volume --toggle-mic
bind=,XF86AudioNext,exec,playerctl next
bind=,XF86AudioPrev,exec,playerctl previous
bind=,XF86AudioPlay,exec,playerctl play-pause
bind=,XF86AudioStop,exec,playerctl stop
bind=ALT,XF86AudioNext,exec,playerctld shift
bind=ALT,XF86AudioPrev,exec,playerctld unshift
bind=ALT,XF86AudioPlay,exec,systemctl --user restart playerctld
</code></pre><p>The rest of the config is just key bindings, this bit is around &ldquo;special&rdquo; keys on my keyboard either the volume control
knob or laptop function keys to increase volume and brightness. Where <code>brightness</code> and <code>volume</code> are custom scripts
I have defined myself. We will see them a bit later.</p>
<pre tabindex="0"><code>bind=SUPER,h,movefocus,l
bind=SUPER,l,movefocus,r
bind=SUPER,k,movefocus,u
bind=SUPER,j,movefocus,d
</code></pre><p>The next bit of my config is all around window management. Note all of these bits will use a combination of the vim
keys to do various things, i.e. here pressing super+l changes the focus to the window to the right. To simplify I will
just show the first key binding, but there will be 4 key bindings for each of the following.</p>
<ul>
<li><code>bind=SUPER,h,movefocus,l</code>: Pressing <code>SUPER+h</code> will change focus to a window on the left of the current focused one.</li>
<li><code>bind=SUPERSHIFT,h,swapwindow,l</code>: Pressing <code>SHIFT+SUPER+h</code> will swap the current focused window with the one to the left of it</li>
<li><code>bind=SUPERCONTROL,h,focusmonitor,l</code>: Pressing <code>CTRL+SUPER+h</code> will swap the focus to the monitor on the left</li>
<li><code>bind=SUPERALT,h,movecurrentworkspacetomonitor,l</code>: Pressing <code>ALT+SUPER+h</code> will move the current workspace (all the windows) to the monitor on the left</li>
<li><code>bind=SUPERALT,h,movecurrentworkspacetomonitor,l</code>: Pressing <code>ALT+SUPER+h</code> will move the current workspace (all the windows) to the monitor on the left</li>
</ul>
<pre tabindex="0"><code> bind=SUPER,1,workspace,01
</code></pre><p>One of our most important commands, changes to that workspace when pressing <code>SUPER+1</code>. I have workspaces from 0 to 9.
Again, assume, for the following commands, it goes from workspace 1 - 10.</p>
<pre tabindex="0"><code>bind=SUPERSHIFT,1,movetoworkspacesilent,01
</code></pre><p>This command moves the current focused window to a specific workspace, i.e. <code>SUPER+SHIFT+1</code> moves the window to workspace 1.</p>
<pre tabindex="0"><code>bind = SUPER, Q, killactive,
bind = SUPER, F, fullscreen, 0
bind = SUPER, F, exec, $notifycmd &#39;Fullscreen Mode&#39;
bind = SUPER, S, pseudo,
bind = SUPER, S, exec, $notifycmd &#39;Pseudo Mode&#39;
bind = SUPER, Space, togglefloating,
bind = SUPER, Space, centerwindow,
</code></pre><p>These commands can be used to change our windows, I use <code>SUPER + Q</code> a lot to kill the focused window.
The other can be used to turn an app full screen, or let it float or even move it centre. Which can be useful in
specific circumstances.</p>
<pre tabindex="0"><code>bindm=SUPER, mouse:272, movewindow
bindm=SUPER, mouse:273, resizewindow

binde = SUPERALT, h, resizeactive, -20 0
binde = SUPERALT, l, resizeactive, 20 0
binde = SUPERALT, k, resizeactive, 0 -20
binde = SUPERALT, j, resizeactive, 0 20
</code></pre><p>Finally, we have a bunch of commands for resizing windows, either using the keyboard or our mouse (sometimes we all feel lazy).</p>
<h2 id="nixos">NixOS</h2>
<p>Setting up Hyprland using home-manager is not enough, we also need to set it in NixOS. The main thing being is we need
to import <code>inputs.hyprland.nixosModules.default</code>. This sets up a bunch of stuff we will need, such as polkit etc.</p>
<h3 id="greetd">greetd</h3>
<p>Then finally, we need a way to launch Hyprland when we log in, I decided to use <code>greetd</code> to do that for us.
Here, we tell it to run the <code>Hyprland</code> command for the user <code>haseeb</code> (I have set up auto-login).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">services</span><span class="o">.</span><span class="n">greetd</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="k">rec</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">initial_session</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">command</span> <span class="o">=</span> <span class="s2">&#34;Hyprland&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">user</span> <span class="o">=</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="n">default_session</span> <span class="o">=</span> <span class="n">initial_session</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="n">environment</span><span class="o">.</span><span class="n">etc</span><span class="o">.</span><span class="s2">&#34;greetd/environments&#34;</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    Hyprland
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="other-apps">Other Apps</h2>
<p>That&rsquo;s it in terms of setting up Hyprland; however, there are some tools that we should look at setting up with Hyprland
to make it more usable and closer to a desktop environment such as Gnome.</p>
<ul>
<li>rofi: Mainly used to launch apps</li>
<li>grimblast: Used to take screenshots</li>
<li>gammastep-indicator: Blue light filter</li>
<li>waybar: The top bar, which shows useful information like internet connection, volume and memory usage</li>
<li>kanshi: Used to set up display layouts</li>
<li>swaync: Used to receive notifications</li>
<li>swaybg: Used to set the wallpaper</li>
</ul>
<p>In a future article, I will do a deeper dive into these apps and how I use them in my workflow. But this post has
gone on long enough for now! In the next main part, we will look at which terminal emulator I use.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/59bf75086353721f1c6902e5811ac30b6148faff/home-manager/desktops/wms/hyprland.nix">My Hyprland Nix Config, at the time of writing</a></li>
<li><a href="https://wiki.hyprland.org/0.19.1beta">Hyprland Wiki</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Install Neovim Nightly Using Nix Home Manager (and NixVim)</title>
      <link>https://haseebmajid.dev/posts/2023-11-15-til-how-to-install-neovim-nightly-using-nix-home-manager/</link>
      <pubDate>Wed, 15 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-11-15-til-how-to-install-neovim-nightly-using-nix-home-manager/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Install Neovim Nightly Using Nix Home Manager (and NixVim)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently, I wanted to install the nightly version of Neovim (version 0.10) because it supports inlay hints.
However, on nixpkgs the latest version of Neovim as of writing is 0.9.4. So how can we get the nightly release?
Using nix/home-manager.&lt;/p&gt;
&lt;p&gt;Simple, we can use an overlay that will add the Neovim nightly package with the nightly. Assuming we are using nix flakes.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Install Neovim Nightly Using Nix Home Manager (and NixVim)</strong></p>
<p>Recently, I wanted to install the nightly version of Neovim (version 0.10) because it supports inlay hints.
However, on nixpkgs the latest version of Neovim as of writing is 0.9.4. So how can we get the nightly release?
Using nix/home-manager.</p>
<p>Simple, we can use an overlay that will add the Neovim nightly package with the nightly. Assuming we are using nix flakes.</p>
<p>Add the nightly Neovim as an input:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">neovim-nightly-overlay</span><span class="o">.</span><span class="n">url</span> <span class="err">=</span> <span class="s2">&#34;github:nix-community/neovim-nightly-overlay&#34;</span><span class="p">;</span>
</span></span></code></pre></div><p>Then add the actual overlay, I do this in my home manager config <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">nixpkgs</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">overlays</span> <span class="o">=</span>  <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="n">inputs</span><span class="o">.</span><span class="n">neovim-nightly-overlay</span><span class="o">.</span><span class="n">overlay</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>Then in another module we can do something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="err">=</span> <span class="k">with</span> <span class="n">pkgs</span> <span class="p">[</span><span class="n">neovim-nightly</span><span class="p">]</span>
</span></span></code></pre></div><p>or if you are using NixVim <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> like me:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">nixvim</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">extraPlugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span> <span class="n">plenary-nvim</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">package</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">neovim-nightly</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/ed8f60b6f27980508161d337e0a75ebb655cb19b/home-manager/default.nix#L52">https://gitlab.com/hmajid2301/dotfiles/-/blob/ed8f60b6f27980508161d337e0a75ebb655cb19b/home-manager/default.nix#L52</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://github.com/nix-community/nixvim">https://github.com/nix-community/nixvim</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>A Simple Way to Convert JSON to Nix Attribute Sets</title>
      <link>https://haseebmajid.dev/posts/2023-11-06-a-simple-way-to-convert-json-to-nix-attribute-sets/</link>
      <pubDate>Mon, 06 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-11-06-a-simple-way-to-convert-json-to-nix-attribute-sets/</guid>
      <description>&lt;p&gt;In this post, I will show you how you can take some JSON and convert it into a Nix attribute set.
This was particularly useful when I was creating my waybar configuration. Which is usually in JSON, but defined in my
home-manager Nix config it has to be in nixlang.&lt;/p&gt;
&lt;p&gt;So given this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;custom/notification&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;{icon}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;format-icons&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;notification&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;span foreground=&amp;#39;red&amp;#39;&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;dnd-notification&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;span foreground=&amp;#39;red&amp;#39;&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;dnd-none&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;inhibited-notification&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;span foreground=&amp;#39;red&amp;#39;&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;inhibited-none&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;dnd-inhibited-notification&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;span foreground=&amp;#39;red&amp;#39;&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;dnd-inhibited-none&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;return-type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;exec-if&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;which swaync-client&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;exec&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;swaync-client -swb&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;on-click&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;swaync-client -t -sw&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;on-click-right&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;swaync-client -d -sw&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;escape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We want it to look something like:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this post, I will show you how you can take some JSON and convert it into a Nix attribute set.
This was particularly useful when I was creating my waybar configuration. Which is usually in JSON, but defined in my
home-manager Nix config it has to be in nixlang.</p>
<p>So given this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl">  <span class="s2">&#34;custom/notification&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;tooltip&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;format&#34;</span><span class="p">:</span> <span class="s2">&#34;{icon}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;format-icons&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;notification&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;none&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;dnd-notification&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;dnd-none&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;inhibited-notification&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;inhibited-none&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;dnd-inhibited-notification&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;dnd-inhibited-none&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;return-type&#34;</span><span class="p">:</span> <span class="s2">&#34;json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exec-if&#34;</span><span class="p">:</span> <span class="s2">&#34;which swaync-client&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exec&#34;</span><span class="p">:</span> <span class="s2">&#34;swaync-client -swb&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;on-click&#34;</span><span class="p">:</span> <span class="s2">&#34;swaync-client -t -sw&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;on-click-right&#34;</span><span class="p">:</span> <span class="s2">&#34;swaync-client -d -sw&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;escape&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span><span class="err">,</span>
</span></span></code></pre></div><p>We want it to look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="s2">&#34;custom/notification&#34;</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">tooltip</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">format</span> <span class="o">=</span> <span class="s2">&#34;{} {icon} &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;format-icons&#34;</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">notification</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f0a2&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;</span><span class="se">\u</span><span class="s2">f444&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">none</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f0a2&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;dnd-notification&#34;</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f1f7&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;</span><span class="se">\u</span><span class="s2">f444&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;dnd-none&#34;</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f1f7&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;inhibited-notification&#34;</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f0a2&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;</span><span class="se">\u</span><span class="s2">f444&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;inhibited-none&#34;</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f0a2&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;dnd-inhibited-notification&#34;</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f1f7&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;</span><span class="se">\u</span><span class="s2">f444&lt;/sup&gt;&lt;/span&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;dnd-inhibited-none&#34;</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\u</span><span class="s2">f1f7&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;return-type&#34;</span> <span class="o">=</span> <span class="s2">&#34;json&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;exec-if&#34;</span> <span class="o">=</span> <span class="s2">&#34;which swaync-client&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">exec</span> <span class="o">=</span> <span class="s2">&#34;swaync-client -swb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;on-click&#34;</span> <span class="o">=</span> <span class="s2">&#34;swaync-client -t -sw&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;on-click-right&#34;</span> <span class="o">=</span> <span class="s2">&#34;swaync-client -d -sw&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">escape</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>As you can see, it looks very similar, but there are enough differences to make it annoying by hand.
I originally came across
<a href="https://gist.githubusercontent.com/Scoder12/0538252ed4b82d65e59115075369d34d/raw/e86d1d64d1373a497118beb1259dab149cea951d/json2nix.py">this script</a>.</p>
<p>Which basically did everything I needed. I ended up improving a few things like needing to surround the block in <code>{}</code>
for it to be valid JSON. I also removed a comma if it existed, because JSON will complain about that as well.</p>
<p>My version of the <a href="https://gitlab.com/-/snippets/3613708">script can be found here</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How Can You Export Your Atuin History to Fish History?</title>
      <link>https://haseebmajid.dev/posts/2023-11-05-how-can-you-export-your-atuin-history-to-fish-history/</link>
      <pubDate>Sun, 05 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-11-05-how-can-you-export-your-atuin-history-to-fish-history/</guid>
      <description>&lt;p&gt;I have made an &lt;a href=&#34;https://haseebmajid.dev/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix/&#34;&gt;post in the past&lt;/a&gt; about how you can set up
&lt;a href=&#34;https://atuin.sh/&#34;&gt;Atuin&lt;/a&gt; to sync share history across multiple devices.&lt;/p&gt;
&lt;p&gt;Whilst this works great and does the job, fish shell doesn&amp;rsquo;t have the same history that Atuin does. Sometimes
we want to have better suggestions in Fish. For example, when you start to type fish shell will suggest the last command
in your history that best matches what you are typing (see example below).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I have made an <a href="/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix/">post in the past</a> about how you can set up
<a href="https://atuin.sh/">Atuin</a> to sync share history across multiple devices.</p>
<p>Whilst this works great and does the job, fish shell doesn&rsquo;t have the same history that Atuin does. Sometimes
we want to have better suggestions in Fish. For example, when you start to type fish shell will suggest the last command
in your history that best matches what you are typing (see example below).</p>
<p></p>
<p>To resolve this issue, we can use a go script that I
<a href="https://github.com/atuinsh/atuin/issues/1073#issuecomment-1610861147">came across here</a> that can be used to export
the Atuin data (in a sqlite db), to our fish history file. Which is typically found in <code>~/.local/state/fish/fish_history</code>.</p>
<p>I then put this on my <a href="https://gitlab.com/hmajid2301/atuin-export-fish-history">GitLab here</a>.
To run the script, we could do something like <code>go install gitlab.com/hmajid2301/atuin-export-fish-history</code>. Then run
<code>atuin-export-fish-history</code>.</p>
<p>However, if you&rsquo;re running NixOS or Nix package manager, you might want to install it using Nix like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">lib</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">buildGoModule</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">fetchFromGitLab</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">buildGoModule</span> <span class="k">rec</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">pname</span> <span class="o">=</span> <span class="s2">&#34;atuin-export-fish-history&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;0.1.0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">src</span> <span class="o">=</span> <span class="n">fetchFromGitLab</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;hmajid2301&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">repo</span> <span class="o">=</span> <span class="n">pname</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">rev</span> <span class="o">=</span> <span class="s2">&#34;v</span><span class="si">${</span><span class="n">version</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;sha256-2egZYLnaekcYm2IzPdWAluAZogdi4Nf/oXWLw8+AnMk=&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">vendorHash</span> <span class="o">=</span> <span class="s2">&#34;sha256-hLEmRq7Iw0hHEAla0Ehwk1EfmpBv6ddBuYtq12XdhVc=&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">ldflags</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;-s&#34;</span> <span class="s2">&#34;-w&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then we can use it like <code>atuin-export-fish-history</code> like normal.</p>
<p>That&rsquo;s it! We could probably do to automate this a bit more to run it on a schedule as cronjob or run it on system startup.
However, that&rsquo;s for another blog post!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Setup a Go Development Shell With Nix Flakes</title>
      <link>https://haseebmajid.dev/posts/2023-10-26-how-to-setup-a-go-development-shell-with-nix-flakes/</link>
      <pubDate>Thu, 26 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-10-26-how-to-setup-a-go-development-shell-with-nix-flakes/</guid>
      <description>&lt;p&gt;As you may know, I have been using Nix/NixOS for the last few months. I finally started doing some development, after
spending lots and lots and lots of time tweaking my setup (and neovim).&lt;/p&gt;
&lt;p&gt;As part of starting to do some real development work, I am now trying to leverage devshells with Nix flakes.
I like the concept of Nix devshells, I have tried using Docker dev containers in the past, but the issue I had
with those was adding my tools such as shell (fish) or cli tools was not easy. Whereas Nix shells just add
tools and scripts to our existing shell.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>As you may know, I have been using Nix/NixOS for the last few months. I finally started doing some development, after
spending lots and lots and lots of time tweaking my setup (and neovim).</p>
<p>As part of starting to do some real development work, I am now trying to leverage devshells with Nix flakes.
I like the concept of Nix devshells, I have tried using Docker dev containers in the past, but the issue I had
with those was adding my tools such as shell (fish) or cli tools was not easy. Whereas Nix shells just add
tools and scripts to our existing shell.</p>
<p>By using Nix flakes we can guarantee (or close to) that developers will be using the same versions of all the tools,
provided in the devshell.</p>
<h2 id="flake-template">Flake Template</h2>
<p>First, we make sure you have support for Nix flakes <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. To get started let&rsquo;s use a flake template to create a new flake
in our go project. First, make sure you are in the root of your project i.e. where <code>go.mod</code> is and then run
<code>nix flake init -t github:nix-community/gomod2nix#app</code> <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<details
  class="notice warning"
  open="true"
>
    <summary class="notice-title">Fix</summary>
  
  <p>At the moment the created flake is broken, on line 25 we have to fix this.
Remove <code>buildGoApplication</code> so the line looks like <code>inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;</code>.</p>
<p>See this <a href="https://github.com/nix-community/gomod2nix/pull/133/files">PR</a> for more information.</p>

</details>

<h3 id="direnv">direnv</h3>
<p>I would recommend enabling <code>direnv</code> which is a tool that allows us to run commands automatically when entering a
directory there is a version available for <a href="https://github.com/nix-community/nix-direnv">nix</a>. This will cache our Nix
development shell and make it much faster to run after the first run. Also prevents the garbage collector from removing
build dependencies we need for our nix shells.</p>
<p>We can enable nix-direnv in home-manager like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">direnv</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">nix-direnv</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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="gomod2nix">gomod2nix</h3>
<p>Then after entering the development shell either via <code>direnv</code> or running <code>nix develop</code>, run the following command:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gomod2nix generate
</span></span></code></pre></div><p>This will populate the <code>gomod2nix.toml</code> file with information about our dependencies:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">schema</span> <span class="p">=</span> <span class="mi">3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">mod</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">mod</span><span class="p">.</span><span class="s2">&#34;github.com/PuerkitoBio/goquery&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;v1.8.1&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">hash</span> <span class="p">=</span> <span class="s2">&#34;sha256-z2RaB8PVPEzSJdMUfkfNjT616yXWTjW2gkhNOh989ZU=&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">mod</span><span class="p">.</span><span class="s2">&#34;github.com/andybalholm/cascadia&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;v1.3.1&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">hash</span> <span class="p">=</span> <span class="s2">&#34;sha256-M0u22DXSeXUaYtl1KoW1qWL46niFpycFkraCEQ/luYA=&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">mod</span><span class="p">.</span><span class="s2">&#34;github.com/davecgh/go-spew&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;v1.1.1&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">hash</span> <span class="p">=</span> <span class="s2">&#34;sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI=&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">mod</span><span class="p">.</span><span class="s2">&#34;github.com/pmezard/go-difflib&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;v1.0.0&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">hash</span> <span class="p">=</span> <span class="s2">&#34;sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA=&#34;</span>
</span></span></code></pre></div><h2 id="adding-extra-packages">Adding extra packages</h2>
<p>Now how we can add extra packages to our Nix shell? Simply go to our <code>shell.nix</code> file and find the bit where
we specify the <code>pkgs.mkShell</code>. Then here we can add the packages we want available, such as say <code>golangci-lint</code> or
<code>gotools</code> to have goimports tool available.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">pkgs</span><span class="o">.</span><span class="n">mkShell</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">hardeningDisable</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;all&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="n">packages</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">goEnv</span>
</span></span><span class="line"><span class="cl">    <span class="n">gomod2nix</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">golangci-lint</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">go_1_21</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">gotools</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">go-junit-report</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">go-task</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">delve</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Now our nix shell will have these tools available including go version 1.21. It&rsquo;d be nice to find a way to specify
the go version in the go.mod file and just use that version.</p>
<h3 id="flakelock">flake.lock</h3>
<p>We can check the flake.lock which makes sure that
when we share this repository other developers will get the same version of the tools we did. As the flake.lock
specifies a specific git revision until we do a flake update, this will include nixpkgs which are a set of nix
expressions git repo.</p>
<p>So updating the flake will update the revision of nixpkgs, which may then include the expression
to build a newer version of say <code>golangci-lint</code>. However again this will be the same for all developers once they have
pulled in our changes and rebuilt their dev shell. Which makes our development environment far more reproducible.</p>
<h2 id="pre-commit">pre-commit</h2>
<p>Now that we have packages available, we can also add pre-commit hooks to our development shell. Using the popular
pre-commit tool. First, we need to add a new input to our flake.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><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-unstable&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">inputs</span><span class="o">.</span><span class="n">flake-utils</span><span class="o">.</span><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="cl"><span class="n">inputs</span><span class="o">.</span><span class="n">gomod2nix</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nix-community/gomod2nix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">inputs</span><span class="o">.</span><span class="n">gomod2nix</span><span class="o">.</span><span class="n">inputs</span><span class="o">.</span><span class="n">nixpkgs</span><span class="o">.</span><span class="n">follows</span> <span class="o">=</span> <span class="s2">&#34;nixpkgs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">inputs</span><span class="o">.</span><span class="n">gomod2nix</span><span class="o">.</span><span class="n">inputs</span><span class="o">.</span><span class="n">flake-utils</span><span class="o">.</span><span class="n">follows</span> <span class="o">=</span> <span class="s2">&#34;flake-utils&#34;</span><span class="p">;</span>
</span></span><span class="line hl"><span class="cl"><span class="n">inputs</span><span class="o">.</span><span class="n">pre-commit-hooks</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:cachix/pre-commit-hooks.nix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then add the pre-commits as an argument to our outputs and make sure its accessible to our <code>devShell</code>, this is where
we will set up our pre-commit hooks.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">outputs</span> <span class="err">=</span> <span class="p">{</span> <span class="n">self</span><span class="o">,</span> <span class="n">nixpkgs</span><span class="o">,</span> <span class="n">flake-utils</span><span class="o">,</span> <span class="n">gomod2nix</span><span class="o">,</span> <span class="n">pre-commit-hooks</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">devShells</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span> <span class="n">callPackage</span> <span class="sr">./shell.nix</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">inherit</span> <span class="p">(</span><span class="n">gomod2nix</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 class="n">mkGoEnv</span> <span class="n">gomod2nix</span><span class="p">;</span>
</span></span><span class="line hl"><span class="cl">    <span class="k">inherit</span> <span class="n">pre-commit-hooks</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then in our <code>shell.nix</code> file we want it to look something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span> 
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">mkGoEnv</span> <span class="o">?</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">mkGoEnv</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">gomod2nix</span> <span class="o">?</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">gomod2nix</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">pre-commit-hooks</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">pre-commit-check</span> <span class="o">=</span> <span class="n">pre-commit-hooks</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="o">.</span><span class="n">run</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">hooks</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">gofmt</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="cl">      <span class="n">golangci-lint</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">        <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;golangci-lint&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Lint my golang code&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">files</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\.</span><span class="s2">go$&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">entry</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">golangci-lint</span><span class="si">}</span><span class="s2">/bin/golangci-lint run --new-from-rev HEAD --fix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">require_serial</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">pass_filenames</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="n">goimports</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">        <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;goimports&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Format my golang code&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">files</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\.</span><span class="s2">go$&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">entry</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">          <span class="k">let</span>
</span></span><span class="line"><span class="cl">            <span class="n">script</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">writeShellScript</span> <span class="s2">&#34;precommit-goimports&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">              set -e
</span></span></span><span class="line"><span class="cl"><span class="s1">              failed=false
</span></span></span><span class="line"><span class="cl"><span class="s1">              for file in &#34;$@&#34;; do
</span></span></span><span class="line"><span class="cl"><span class="s1">                  # redirect stderr so that violations and summaries are properly interleaved.
</span></span></span><span class="line"><span class="cl"><span class="s1">                  if ! </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">gotools</span><span class="si">}</span><span class="s1">/bin/goimports -l -d &#34;$file&#34; 2&gt;&amp;1
</span></span></span><span class="line"><span class="cl"><span class="s1">                  then
</span></span></span><span class="line"><span class="cl"><span class="s1">                      failed=true
</span></span></span><span class="line"><span class="cl"><span class="s1">                  fi
</span></span></span><span class="line"><span class="cl"><span class="s1">              done
</span></span></span><span class="line"><span class="cl"><span class="s1">              if [[ $failed == &#34;true&#34; ]]; then
</span></span></span><span class="line"><span class="cl"><span class="s1">                  exit 1
</span></span></span><span class="line"><span class="cl"><span class="s1">              fi
</span></span></span><span class="line"><span class="cl"><span class="s1">            &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="k">in</span>
</span></span><span class="line"><span class="cl">          <span class="nb">builtins</span><span class="o">.</span><span class="nb">toString</span> <span class="n">script</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">pkgs</span><span class="o">.</span><span class="n">mkShell</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">inherit</span> <span class="p">(</span><span class="n">pre-commit-check</span><span class="p">)</span> <span class="n">shellHook</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>When we enter our nix shell it will automatically install pre-commit hooks and the yaml file <code>.pre-commit-config.yaml</code>
(We should add this file to a gitignore). That&rsquo;s all we need to get our pre-commit.</p>
<h2 id="build-go-binary">Build go binary</h2>
<p>To build our binary using Nix we can simply run <code>nix run</code>, where we can see how this works in our <code>default.nix</code>
file. Particularly the part with <code>buildGoApplication</code> <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">buildGoApplication</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">  <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;0.1&#34;</span><span class="p">;</span>
</span></span><span class="line"><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="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="cl">  <span class="n">modules</span> <span class="o">=</span> <span class="sr">./gomod2nix.toml</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>That&rsquo;s it! We set up a development shell using Nix flakes for our go project. Including adding pre-commits and how
we can build our Go binary using nix. Leveraging the <code>gomod2nix</code> tool.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://nixos.wiki/wiki/Flakes">https://nixos.wiki/wiki/Flakes</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://www.tweag.io/blog/2021-03-04-gomod2nix/">https://www.tweag.io/blog/2021-03-04-gomod2nix/</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://github.com/nix-community/gomod2nix/blob/master/docs/nix-reference.md">https://github.com/nix-community/gomod2nix/blob/master/docs/nix-reference.md</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>Part 2: How to Setup Nixos as Part of Your Development Workflow</title>
      <link>https://haseebmajid.dev/posts/2023-10-24-part-2-how-to-setup-nixos-as-part-of-your-development-workflow/</link>
      <pubDate>Tue, 24 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-10-24-part-2-how-to-setup-nixos-as-part-of-your-development-workflow/</guid>
      <description>&lt;h2 id=&#34;premable&#34;&gt;Premable&lt;/h2&gt;
&lt;p&gt;In this second part of the series, we will look at how we can not set up NixOS past installation. How we can install
software and various other tools. After part 1 we should have NixOS installed, mind you since I&amp;rsquo;ve written that blog
post I found a way to create a custom ISO image from my Nix config. This ISO contains a custom install script,
the main advantage being able to use a tool called &lt;a href=&#34;https://github.com/diskonauts/disko&#34;&gt;disko&lt;/a&gt; to partition our disks.
Anyway, I will probably write another post in the future going over how you can do this in another blog post.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="premable">Premable</h2>
<p>In this second part of the series, we will look at how we can not set up NixOS past installation. How we can install
software and various other tools. After part 1 we should have NixOS installed, mind you since I&rsquo;ve written that blog
post I found a way to create a custom ISO image from my Nix config. This ISO contains a custom install script,
the main advantage being able to use a tool called <a href="https://github.com/diskonauts/disko">disko</a> to partition our disks.
Anyway, I will probably write another post in the future going over how you can do this in another blog post.</p>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">My NixOS Config Explored</summary>
  
  <p>I will also do a more detailed series into my Nix config at some point. This post will be a more general post about
one possible way you can structure your NixOS config.</p>
<p>Heavily inspired by <a href="https://github.com/Misterio77/nix-config">Misterio77</a></p>

</details>

<h2 id="introduction">Introduction</h2>
<p>Currently, we have a single configuration file at <code>/etc/nixos/configuration.nix</code>. However, to edit this file we need sudo
permissions, we also cannot easily put it into a git repository and share this configuration with other machines.
One potential to this solution is to use <a href="https://nixos.org/flake-manual.html">Nix Flakes</a>.</p>
<h2 id="flakes">Flakes</h2>
<p>Nix Flakes exist to improve reproducibility, composability and usability in the Nix ecosystem. What do we mean by that,
well in general they make it easier <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<ul>
<li>Lock file: They lock all of our dependencies to specific git revisions, so if we try to use the config on another machine it should produce the same &ldquo;outputs&rdquo;</li>
<li>Entry point: The entry point to every nix flake is the <code>flake.nix</code> file, kinda a main function where everything starts from</li>
<li>Share: We can put our flake wherever we want on our system and therefore it is super easy to turn it into a git repo and share it with others</li>
</ul>
<h3 id="getting-started">Getting Started</h3>
<p>So in my case, I did this by creating a new folder in my home directory <code>mkdir $HOME/dotfiles</code>, then going into that
directory <code>cd $HOME/dotfiles</code>, and finally creating a new nix flake <code>nix flake init</code>.</p>
<p>We may need to add the following to our <code>configuration.nix</code>
<code>nix.settings.experimental-features = [ &quot;nix-command&quot; &quot;flakes&quot; ];</code> to allow us to use <code>nix flake</code> command(s).</p>
<p>Now we have a new flake in a git repo. We will now have a <code>flake.nix</code> file which contains three main sections.</p>
<h3 id="inputs">inputs</h3>
<p>Specifies dependencies of this flake, usually other flakes. Usually, I add dependencies you cannot find on <code>nixpkgs</code>,
such as <code>nixvim</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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-unstable&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">nixvim</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:pta2002/nixvim&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>One of the imports that is important is the nixpkgs, this will determine which versions of packages we will get.
Essentially nixpkgs is just a repo full of different nix derivations which tell Nix how to install a package.
Where a Nix derivation is a specific build of a package, which includes all the necessary information, build steps
and dependencies for that package.</p>
<h4 id="flakelock">flake.lock</h4>
<p>In our <code>flake.lock</code> file, we have something like this:</p>
<pre tabindex="0"><code>&#34;nixpkgs_11&#34;: {
  &#34;locked&#34;: {
    &#34;lastModified&#34;: 1693844670,
    &#34;narHash&#34;: &#34;sha256-t69F2nBB8DNQUWHD809oJZJVE+23XBrth4QZuVd6IE0=&#34;,
    &#34;owner&#34;: &#34;nixos&#34;,
    &#34;repo&#34;: &#34;nixpkgs&#34;,
    &#34;rev&#34;: &#34;3c15feef7770eb5500a4b8792623e2d6f598c9c1&#34;,
    &#34;type&#34;: &#34;github&#34;
  },
  &#34;original&#34;: {
    &#34;owner&#34;: &#34;nixos&#34;,
    &#34;ref&#34;: &#34;nixos-unstable&#34;,
    &#34;repo&#34;: &#34;nixpkgs&#34;,
    &#34;type&#34;: &#34;github&#34;
  }
},
</code></pre><p>Where we can see <code>rev</code> is a <a href="https://github.com/NixOS/nixpkgs/commit/3c15feef7770eb5500a4b8792623e2d6f598c9c1">git sha</a>.
In this case, we are looking at a specific branch <code>ref</code>: <code>nixos-unstable</code> so we use the unstable channel,
<a href="https://search.nixos.org/packages?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=ag">https://search.nixos.org/packages?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=ag</a>.</p>
<p>So if we don&rsquo;t ever update our <code>flake.lock</code> we will forever be tied to this version of the unstable channel at that
moment. Of course, that branch is getting updated multiple times a day. So to update our tools/apps etc. we need to update
this lock file. We can do this by running <code>nix flake update</code>, in our dotfiles repo.
The <code>unstable</code> is just a branch on the nixpkgs repo where the packages are updated more often. So when we update
our flakes (using a <code>nix flake update</code>).</p>
<h3 id="outputs">outputs</h3>
<p>The output you can think of it as the different devices we want to configure.
Which includes our actual NixOS config to set up our machine, such as where to backup our files to, and setting up VPNs.
Notice how we are pointing the framework configuration to a configuration file. Which we can build our config using
<code>sudo nixos-rebuild switch --flake ~/dotfiles#framework</code>, using <code>#framework</code> to specify which device to build for.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">outputs</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">nixosConfigurations</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Laptops</span>
</span></span><span class="line"><span class="cl">        <span class="n">framework</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">nixosSystem</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">modules</span> <span class="o">=</span> <span class="p">[</span> <span class="sr">./hosts/framework/configuration.nix</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">          <span class="n">specialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">inputs</span> <span class="n">outputs</span><span class="p">;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="configuring-nixos">Configuring NixOS</h2>
<p>Now that we have the basic format of what our NixOS config will look like how do we go about actually configuring
our system? We split our config into two main bits. Some key bits of my config, I like as much config to be shared
between my devices as possible but I also want it to be modular, as not every device needs to use every feature.
Some devices don&rsquo;t even run NixOS and only use home-manager.</p>
<h3 id="nixos">NixOS</h3>
<p>The first bit is our NixOS config which we will use to configure our device. Think of anything we need &ldquo;sudo&rdquo; permissions
to do. Again this code block:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">outputs</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">nixosConfigurations</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Laptops</span>
</span></span><span class="line"><span class="cl">        <span class="n">framework</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">nixosSystem</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">modules</span> <span class="o">=</span> <span class="p">[</span> <span class="sr">./hosts/framework/configuration.nix</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">          <span class="n">specialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">inputs</span> <span class="n">outputs</span><span class="p">;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Essentially what we are doing is pointing the flake to use the framework specific <code>configuration.nix</code> file. Then giving
it access to the inputs (and outputs). Which we can access in our configuration.</p>
<h4 id="configurationnix">configuration.nix</h4>
<p>Where the <code>configuration.nix</code> looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hardware</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">framework-12th-gen-intel</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">disko</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">disko</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">./hardware-configuration.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./disks.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/global</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/users/haseeb.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/backup.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/fingerprint.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/docker.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/fonts.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/pipewire.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/greetd.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/quietboot.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/vfio.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/vpn.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/pam.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/grub.nix</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">networking</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">hostName</span> <span class="o">=</span> <span class="s2">&#34;framework&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><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;23.05&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Some things shared between all of my configs is:</p>
<ul>
<li>inputs (we discussed above)</li>
<li>hardware-configuration</li>
<li>disks (used to partition drives)</li>
</ul>
<h5 id="global">global</h5>
<p>The global config set up the following, which I think I will need in all of my devices. Such as:</p>
<ul>
<li>locale</li>
<li>nix settings</li>
<li>pam auth</li>
<li>opengl</li>
<li>persistence</li>
</ul>
<p>For example, <code>pam.nix</code> looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">security</span><span class="o">.</span><span class="n">pam</span><span class="o">.</span><span class="n">services</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">swaylock</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">u2fAuth</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">login</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">u2fAuth</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">sudo</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">u2fAuth</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Allow us to use a Yubikey to login, unlock Swaylock and to grant sudo permissions.</p>
<h5 id="usershaseebnix">users/haseeb.nix</h5>
<p>Then we decide which users we want to configure on that device, which for now is always <code>haseeb</code> but could change.
Perhaps you want multiple users on a specific device. Where we set up things like:</p>
<ul>
<li>default shell</li>
<li>groups</li>
<li>docker</li>
<li>libvirt</li>
<li>etc &hellip;</li>
<li>home-manager config
<ul>
<li>so a NixOS rebuild also rebuilds the home manager config</li>
</ul>
</li>
<li>hashed password stored using sops-nix (encrypted)</li>
</ul>
<h5 id="optional-features">optional features</h5>
<p>Then alongside the &ldquo;global&rdquo; features, we have a bunch of features/config options which can optionally be turned on by
importing. I think I will likely move to a system I have with my home manager config where you don&rsquo;t turn it on by importing
but by setting an option in an attribute set (you will see this a bit later). However for now you simply import the optional feature.
Which include:</p>
<ul>
<li>backups</li>
<li>fingerprint (not all my devices have fingerprint readers)</li>
<li>enabling thunderbolt</li>
<li>quierboot/grub (could also use systemd-boot)</li>
<li>pipewire</li>
</ul>
<p>You can find a full list of <a href="https://search.nixos.org/options?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages">options here</a></p>
<h2 id="home-manager">Home Manager</h2>
<p>Home Manager is a tool we can use to help configure apps using Nix in our home folder. This includes managing dotfiles.
This can partly be done using nix expressions, used to generate the dotfiles.</p>
<p>This is the main part of my config, which I use to configure my &ldquo;user&rdquo; space. Basically, everything I can do with my user
that doesn&rsquo;t require root permissions <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. This includes things like:</p>
<ul>
<li>terminal emulator</li>
<li>dotfiles</li>
<li>browsers</li>
<li>editor (nvim)</li>
<li>tmux</li>
</ul>
<p>If I can configure it via home manager I will. You can find a full list of
<a href="https://mipmip.github.io/home-manager-option-search/">home manager options here</a>.</p>
<p>Where the <code>home.nix</code> file acts like a <code>configuration.nix</code> but for home manager.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">pkgs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">lib</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">config</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../home-manager</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">modules</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">browsers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">firefox</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">editors</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">nvim</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">multiplexers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">tmux</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">shells</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">fish</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">terminals</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">alacritty</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="cl">        <span class="n">foot</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">my</span><span class="o">.</span><span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">wallpaper</span> <span class="o">=</span> <span class="s2">&#34;~/dotfiles/home-manager/wallpapers/rainbow-nix.jpg&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">host</span> <span class="o">=</span> <span class="s2">&#34;framework&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">default</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">shell</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="si">}</span><span class="s2">/bin/fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">terminal</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">foot</span><span class="si">}</span><span class="s2">/bin/foot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">browser</span> <span class="o">=</span> <span class="s2">&#34;firefox&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">editor</span> <span class="o">=</span> <span class="s2">&#34;nvim&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">colorscheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">catppuccin-mocha</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">home</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">username</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">homeDirectory</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;/home/</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">home</span><span class="o">.</span><span class="n">username</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">stateVersion</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;23.05&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Here we &ldquo;import&rdquo; all of our options in home-manager and pick and choose what to enable per device:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">config</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">modules</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">browsers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">firefox</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">editors</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">nvim</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">multiplexers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">tmux</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">shells</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">fish</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">terminals</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">alacritty</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="cl">        <span class="n">foot</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="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>You can see here I enable alacritty and foot terminal managers for this device, so I will have access to both.
Then we also have this which are custom options I have defined. Which will determine the default apps to use.</p>
<p>Where <code>foot.nix</code> looks something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">
</span></span><span class="line"><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="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">cfg</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">terminals</span><span class="o">.</span><span class="n">foot</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">terminals</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">enable</span> <span class="o">=</span> <span class="n">mkEnableOption</span> <span class="s2">&#34;enable foot terminal emulator&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span> <span class="o">=</span> <span class="n">mkIf</span> <span class="n">cfg</span><span class="o">.</span><span class="n">enable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">programs</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Here you can see we check if <code>cfg.enable</code> if the foot terminal is enabled then it will be included in our final nix
expression.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">    <span class="n">my</span><span class="o">.</span><span class="n">settings</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">wallpaper</span> <span class="o">=</span> <span class="s2">&#34;~/dotfiles/home-manager/wallpapers/rainbow-nix.jpg&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">host</span> <span class="o">=</span> <span class="s2">&#34;framework&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">default</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">shell</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="si">}</span><span class="s2">/bin/fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">terminal</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">foot</span><span class="si">}</span><span class="s2">/bin/foot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">browser</span> <span class="o">=</span> <span class="s2">&#34;firefox&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">editor</span> <span class="o">=</span> <span class="s2">&#34;nvim&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span></code></pre></div><p>Which looks something like allows us to have custom options:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">lib</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="k">inherit</span> <span class="p">(</span><span class="n">lib</span><span class="p">)</span> <span class="n">types</span> <span class="n">mkOption</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">options</span><span class="o">.</span><span class="n">my</span><span class="o">.</span><span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">default</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">shell</span> <span class="o">=</span> <span class="n">mkOption</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">type</span> <span class="o">=</span> <span class="n">types</span><span class="o">.</span><span class="n">nullOr</span> <span class="p">(</span><span class="n">types</span><span class="o">.</span><span class="n">enum</span> <span class="p">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="si">}</span><span class="s2">/bin/fish&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">zsh</span><span class="si">}</span><span class="s2">/bin/zsh&#34;</span> <span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;The default shell to use&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">default</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="si">}</span><span class="s2">/bin/fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">terminal</span> <span class="o">=</span> <span class="n">mkOption</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">type</span> <span class="o">=</span> <span class="n">types</span><span class="o">.</span><span class="n">nullOr</span> <span class="p">(</span><span class="n">types</span><span class="o">.</span><span class="n">enum</span> <span class="p">[</span> <span class="s2">&#34;alacritty&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">foot</span><span class="si">}</span><span class="s2">/bin/foot&#34;</span> <span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;The default terminal to use&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">default</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">foot</span><span class="si">}</span><span class="s2">/bin/foot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">browser</span> <span class="o">=</span> <span class="n">mkOption</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">type</span> <span class="o">=</span> <span class="n">types</span><span class="o">.</span><span class="n">nullOr</span> <span class="p">(</span><span class="n">types</span><span class="o">.</span><span class="n">enum</span> <span class="p">[</span> <span class="s2">&#34;firefox&#34;</span> <span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;The default browser to use&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">default</span> <span class="o">=</span> <span class="s2">&#34;firefox&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">editor</span> <span class="o">=</span> <span class="n">mkOption</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">type</span> <span class="o">=</span> <span class="n">types</span><span class="o">.</span><span class="n">nullOr</span> <span class="p">(</span><span class="n">types</span><span class="o">.</span><span class="n">enum</span> <span class="p">[</span> <span class="s2">&#34;nvim&#34;</span> <span class="s2">&#34;code&#34;</span> <span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;The default editor to use&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">default</span> <span class="o">=</span> <span class="s2">&#34;nvim&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>These will then get references in other bits of the config like (take from my sway config):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="o">...</span><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ....</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;exec </span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">my</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">default</span><span class="o">.</span><span class="n">browser</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Thats it! We&rsquo;ve gone over how you can setup your NixOS/Nix config, like how I have setup my own!</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/dotfiles">My nix flake</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>A great book about NixOS and flakes https://nixos&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://discourse.nixos.org/t/what-are-the-advantages-of-using-home-manager-with-flake-as-opposed-just-flakes-with-nixos/21628">https://discourse.nixos.org/t/what-are-the-advantages-of-using-home-manager-with-flake-as-opposed-just-flakes-with-nixos/21628</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Create Systemd Services in Nix Home Manager</title>
      <link>https://haseebmajid.dev/posts/2023-10-08-how-to-create-systemd-services-in-nix-home-manager/</link>
      <pubDate>Sun, 08 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-10-08-how-to-create-systemd-services-in-nix-home-manager/</guid>
      <description>&lt;p&gt;I recently learnt in home-manager (Nix) you can run systemd services as your own user. This is nice because we don&amp;rsquo;t need
&amp;ldquo;sudo&amp;rdquo; permissions to do so. I also prefer to have as much of my config as possible in home-manager, again I don&amp;rsquo;t
need to run &amp;ldquo;sudo&amp;rdquo;. Which is probably safer running apps in the least privileged mode.&lt;/p&gt;
&lt;p&gt;In my case, I wanted to run an &lt;code&gt;attic&lt;/code&gt;, a binary cache, watch store command which uploads any changes to &lt;code&gt;/nix/store&lt;/code&gt;
to my binary cache. Previously I had this running as a systemd service running as root i.e. managed my NixOS.
However, I wanted to run the same service, on my non-NixOS machine. So I decided to have a look and see if I could
run it in my home-manager config so I could run it the same way across all my machines. Whilst researching I came across
the &lt;code&gt;systemd.user.services&lt;/code&gt; option which allows us to do exactly this.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I recently learnt in home-manager (Nix) you can run systemd services as your own user. This is nice because we don&rsquo;t need
&ldquo;sudo&rdquo; permissions to do so. I also prefer to have as much of my config as possible in home-manager, again I don&rsquo;t
need to run &ldquo;sudo&rdquo;. Which is probably safer running apps in the least privileged mode.</p>
<p>In my case, I wanted to run an <code>attic</code>, a binary cache, watch store command which uploads any changes to <code>/nix/store</code>
to my binary cache. Previously I had this running as a systemd service running as root i.e. managed my NixOS.
However, I wanted to run the same service, on my non-NixOS machine. So I decided to have a look and see if I could
run it in my home-manager config so I could run it the same way across all my machines. Whilst researching I came across
the <code>systemd.user.services</code> option which allows us to do exactly this.</p>
<p>You can see how I set it below:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">systemd</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">services</span><span class="o">.</span><span class="n">attic-watch-store</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Unit</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">Description</span> <span class="o">=</span> <span class="s2">&#34;Push nix store changes to attic binary cache.&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">Install</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">WantedBy</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;default.target&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">Service</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">ExecStart</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">writeShellScript</span> <span class="s2">&#34;watch-store&#34;</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">        #!/run/current-system/sw/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="s1">        ATTIC_TOKEN=$(cat </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">attic_auth_token</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="cl"><span class="s1">        </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">attic</span><span class="si">}</span><span class="s1">/bin/attic login prod https://majiy00-nix-binary-cache.fly.dev $ATTIC_TOKEN
</span></span></span><span class="line"><span class="cl"><span class="s1">        </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">attic</span><span class="si">}</span><span class="s1">/bin/attic use prod
</span></span></span><span class="line"><span class="cl"><span class="s1">        </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">attic</span><span class="si">}</span><span class="s1">/bin/attic watch-store prod:prod
</span></span></span><span class="line"><span class="cl"><span class="s1">      &#39;&#39;</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>One thing I liked was I didn&rsquo;t need to create an extra binary/shell script for <code>ExecStart</code> to run. i.e.
<code>ExecStart = watch-store.sh</code>. We can simply create a bash script inline and give it a name. home-manager will work out
creating this file and updating the systemd config to point to it for us. One fewer file in our config.</p>
<p>In the example above this is done using the <code>pkgs.writeShellScript</code> function we must provide it with a name (of the file)
i.e. <code>watch-store</code> and then the contents of the file itself.</p>
<p>After running <code>home-manager switch</code> we should be able to see our service running (ignore the fact mine is failing).</p>
<p>The command <code>systemctl --user status attic-watch-store.service</code> could produce the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl --user status attic-watch-store.service
</span></span><span class="line"><span class="cl">× attic-watch-store.service - Push nix store changes to attic binary cache.
</span></span><span class="line"><span class="cl">     Loaded: loaded <span class="o">(</span>/home/haseebmajid/.config/systemd/user/attic-watch-store.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span>
</span></span><span class="line"><span class="cl">     Active: failed <span class="o">(</span>Result: exit-code<span class="o">)</span> since Sat 2023-10-07 23:38:48 BST<span class="p">;</span> 11h ago
</span></span><span class="line"><span class="cl">    Process: <span class="m">1920392</span> <span class="nv">ExecStart</span><span class="o">=</span>/nix/store/2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span>1/FAILURE<span class="o">)</span>
</span></span><span class="line"><span class="cl">   Main PID: <span class="m">1920392</span> <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span>1/FAILURE<span class="o">)</span>
</span></span><span class="line"><span class="cl">        CPU: 85ms
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920443<span class="o">]</span>:     0: error trying to connect: dns error: Devic&gt;
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920443<span class="o">]</span>:     1: dns error: Device or resource busy <span class="o">(</span>os er&gt;
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920443<span class="o">]</span>:     2: Device or resource busy <span class="o">(</span>os error 16<span class="o">)</span>
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920489<span class="o">]</span>: Error: error sending request <span class="k">for</span> url <span class="o">(</span>https://ma&gt;
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920489<span class="o">]</span>: Caused by:
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920489<span class="o">]</span>:     0: error trying to connect: dns error: faile&gt;
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920489<span class="o">]</span>:     1: dns error: failed to lookup address infor&gt;
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix 2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store<span class="o">[</span>1920489<span class="o">]</span>:     2: failed to lookup address information: Tem&gt;
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix systemd<span class="o">[</span>2551<span class="o">]</span>: attic-watch-store.service: Main process exited, <span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span>1/FAILURE
</span></span><span class="line"><span class="cl">Oct <span class="m">07</span> 23:38:48 nix systemd<span class="o">[</span>2551<span class="o">]</span>: attic-watch-store.service: Failed with result <span class="s1">&#39;exit-code&#39;</span>.
</span></span></code></pre></div><p>We can also find the systemd file in <code>~/.config/systemd/user/attic-watch-store.service</code>. Which may look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bat attic-watch-store.service --plain
</span></span><span class="line"><span class="cl"><span class="o">[</span>Install<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">WantedBy</span><span class="o">=</span>default.target
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Service<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">ExecStart</span><span class="o">=</span>/nix/store/2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Unit<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">Description</span><span class="o">=</span>Push nix store changes to attic binary cache.
</span></span></code></pre></div><p>Where the <code>ExecStart</code> file looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bat /nix/store/2z87s2lr68c6vwivphv0hp3nscgqfga6-watch-store --plain
</span></span><span class="line"><span class="cl"><span class="c1">#!/nix/store/xdqlrixlspkks50m9b0mpvag65m3pf2w-bash-5.2-p15/bin/bash</span>
</span></span><span class="line"><span class="cl"><span class="c1">#!/run/current-system/sw/bin/bash</span>
</span></span><span class="line"><span class="cl"><span class="nv">ATTIC_TOKEN</span><span class="o">=</span><span class="k">$(</span>cat %r/secrets/attic_auth_token<span class="k">)</span>
</span></span><span class="line"><span class="cl">/nix/store/sm7wscbpxv4nsxdv7bik39skll81fy5i-attic-0.1.0/bin/attic login prod https://majiy00-nix-binary-cache.fly.dev <span class="nv">$ATTIC_TOKEN</span>
</span></span><span class="line"><span class="cl">/nix/store/sm7wscbpxv4nsxdv7bik39skll81fy5i-attic-0.1.0/bin/attic use prod
</span></span><span class="line"><span class="cl">/nix/store/sm7wscbpxv4nsxdv7bik39skll81fy5i-attic-0.1.0/bin/attic watch-store prod:prod
</span></span></code></pre></div><p>That&rsquo;s about it! How you can manage systemd services via home-manager running as your own user.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Fix Package Binary Collisions on Nix</title>
      <link>https://haseebmajid.dev/posts/2023-10-02-til-how-to-fix-package-binary-collisions-on-nix/</link>
      <pubDate>Mon, 02 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-10-02-til-how-to-fix-package-binary-collisions-on-nix/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Fix Package Binary Collisions on Nix&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently I wanted to use &lt;a href=&#34;https://www.gnu.org/software/parallel/&#34;&gt;GNU parallel&lt;/a&gt;, a nifty little tool we can use
to run tasks in parallel, shock horror I know. I already have the &lt;code&gt;moreutils&lt;/code&gt; package installed using nix (home-manager).&lt;/p&gt;
&lt;p&gt;So I added this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;parallel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;moreutils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I ran the home manager switch like usual, I got the following error.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;error: builder &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;/nix/store/vh6i81xhf6pvybdpall8z8l8y0i6mr8p-home-manager-path.drv&amp;#39;&lt;/span&gt; failed with &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; code 25&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       last &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; log lines:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &amp;gt; error: collision between &lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;/nix/store/slkylri9sbn4w7paaixzc5wj6cwfk83m-moreutils-0.67/bin/parallel&lt;span class=&#34;s1&#34;&gt;&amp;#39; and `/nix/store/fjpnw99zvx2f910s016jrmybc5jxirpn-parallel-20230822/bin/parallel&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       For full logs, run &lt;span class=&#34;s1&#34;&gt;&amp;#39;nix log /nix/store/vh6i81xhf6pvybdpall8z8l8y0i6mr8p-home-manager-path.drv&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;error: &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; dependencies of derivation &lt;span class=&#34;s1&#34;&gt;&amp;#39;/nix/store/m4p56x5lgjfpvdy0xjrbk981sfchpl8c-home-manager-generation.drv&amp;#39;&lt;/span&gt; failed to build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because &lt;code&gt;moreutils&lt;/code&gt; also have a binary called parallel. How do we tell Nix to overwrite the moreutils binary and use
the one in the &lt;code&gt;parallel&lt;/code&gt; packages?  Simple by using &lt;code&gt;lib.hiPrio&lt;/code&gt; like so:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Fix Package Binary Collisions on Nix</strong></p>
<p>Recently I wanted to use <a href="https://www.gnu.org/software/parallel/">GNU parallel</a>, a nifty little tool we can use
to run tasks in parallel, shock horror I know. I already have the <code>moreutils</code> package installed using nix (home-manager).</p>
<p>So I added this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="err">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line hl"><span class="cl">  <span class="n">parallel</span>
</span></span><span class="line"><span class="cl">  <span class="n">moreutils</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></div><p>Then I ran the home manager switch like usual, I got the following error.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">error: builder <span class="k">for</span> <span class="s1">&#39;/nix/store/vh6i81xhf6pvybdpall8z8l8y0i6mr8p-home-manager-path.drv&#39;</span> failed with <span class="nb">exit</span> code 25<span class="p">;</span>
</span></span><span class="line"><span class="cl">       last <span class="m">1</span> log lines:
</span></span><span class="line"><span class="cl">       &gt; error: collision between <span class="sb">`</span>/nix/store/slkylri9sbn4w7paaixzc5wj6cwfk83m-moreutils-0.67/bin/parallel<span class="s1">&#39; and `/nix/store/fjpnw99zvx2f910s016jrmybc5jxirpn-parallel-20230822/bin/parallel&#39;</span>
</span></span><span class="line"><span class="cl">       For full logs, run <span class="s1">&#39;nix log /nix/store/vh6i81xhf6pvybdpall8z8l8y0i6mr8p-home-manager-path.drv&#39;</span>.
</span></span><span class="line"><span class="cl">error: <span class="m">1</span> dependencies of derivation <span class="s1">&#39;/nix/store/m4p56x5lgjfpvdy0xjrbk981sfchpl8c-home-manager-generation.drv&#39;</span> failed to build
</span></span></code></pre></div><p>Because <code>moreutils</code> also have a binary called parallel. How do we tell Nix to overwrite the moreutils binary and use
the one in the <code>parallel</code> packages?  Simple by using <code>lib.hiPrio</code> like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="err">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">[</span>
</span></span><span class="line hl"><span class="cl">  <span class="p">(</span><span class="n">lib</span><span class="o">.</span><span class="n">hiPrio</span> <span class="n">parallel</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">moreutils</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></div><p>This tells Nix to increase the priority of this package you can see
<a href="https://github.com/NixOS/nixpkgs/blob/efdb9b4ee86a3bf3349efa7a23b42cbc18766b90/lib/meta.nix#L52-L69">the code here</a>.</p>
<p>That&rsquo;s it we can still have access to the other binaries moreutils provides like <code>sponge</code> and <code>parallel</code> from parallel
package.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Setup Ventoy on Nixos</title>
      <link>https://haseebmajid.dev/posts/2023-09-29-setup-ventoy-on-nixos/</link>
      <pubDate>Fri, 29 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-09-29-setup-ventoy-on-nixos/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Typically when we want to install a new OS we use an ISO to create a bootable USB drive. We can then plug this into
our device, say laptop, and boot from that USB and install our OS. However, typically you can only put a single ISO on
a USB. So what if wanted a USB with say Window, Arch Linux, TailsOS and NixOS how could we do that?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Typically when we want to install a new OS we use an ISO to create a bootable USB drive. We can then plug this into
our device, say laptop, and boot from that USB and install our OS. However, typically you can only put a single ISO on
a USB. So what if wanted a USB with say Window, Arch Linux, TailsOS and NixOS how could we do that?</p>
<p>I&rsquo;m sure there are other multi-bootable USB tools we could use but I recently came across <a href="https://www.ventoy.net/">ventoy</a>.
All we need to do is format our USB drive with Ventoy, then simply copy our ISO (or other relevant files) onto it.
So we can now have an ISO for windows, arch etc etc. Then we can decide during boot time which ISO ventoy will load
for us.</p>
<p><img
        loading="lazy"
        src="/posts/2023-09-29-setup-ventoy-on-nixos/images/boot.png"
        type=""
        alt="Boot"
        
      /></p>
<h2 id="install-on-nix-nixos">Install on Nix (/NixOS)</h2>
<p>So how do we go about setting it up? Well, I will show you how I set it up on Nix. First plug in a USB that you don&rsquo;t
mind losing all the data on.</p>
<p>If we want to just &ldquo;install&rdquo; ventoy temporarily we can do something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nix-shell -p ventoy-full
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo ventoy-web
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">===============================================================</span>
</span></span><span class="line"><span class="cl">  Ventoy Server 1.0.95 is running ...
</span></span><span class="line"><span class="cl">  Please open your browser and visit http://127.0.0.1:24680
</span></span><span class="line"><span class="cl"><span class="o">===============================================================</span>
</span></span></code></pre></div><ul>
<li>Open the webpage at <code>http://127.0.0.1:24680</code>,</li>
<li>Select the device you would like to flash</li>
<li>Press the install button</li>
</ul>
<p><img
        loading="lazy"
        src="/posts/2023-09-29-setup-ventoy-on-nixos/images/web.png"
        type=""
        alt="Ventoy Web"
        
      /></p>
<p>After its done you should be able to see a drive called Ventoy and copy over your ISOs to it.</p>
<p><img
        loading="lazy"
        src="/posts/2023-09-29-setup-ventoy-on-nixos/images/files.png"
        type=""
        alt="Copy ISOs to Ventoy"
        
      /></p>
<h2 id="summary">Summary</h2>
<p>That&rsquo;s it! You now have a USB that will allow you to boot to multiple different OS. I originally set this up because
I was creating my own ISO file using Nix flakes. To help automate the installation of new devices (or reinstalling of older ones).</p>
<p>But this is quite cool now because I can have an ISO for my custom Nix image, I can also run TailsOS which gives me
access to Linux on any device. Say, I&rsquo;m at the library, which only has Windows machines. It just avoids the hassle of
either carrying multiple USB devices or constantly formatting and reformatting my USB.</p>
<p>Hope you found this useful!!!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Use fzf.fish History Search</title>
      <link>https://haseebmajid.dev/posts/2023-09-19-til-how-to-use-fzf-fish-history-search/</link>
      <pubDate>Tue, 19 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-09-19-til-how-to-use-fzf-fish-history-search/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Use fzf.fish History Search&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I use Fish Shell with fzf and &lt;a href=&#34;https://github.com/PatrickF1/fzf.fish&#34;&gt;fish fzf plugin&lt;/a&gt;.
I installed fzf using nix and home-manager:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;programs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fzf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;enable&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;enableFishIntegration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It adds &lt;code&gt;fzf-history-widget&lt;/code&gt; script, which is bound to &lt;code&gt;ctrl+r&lt;/code&gt;, shell reverse history search.
Which we can see when we run this: &lt;code&gt;bind | grep -e fzf-history-widget -e fzf-file-widget&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Whereas I wanted to use the &lt;code&gt;_fzf_search_history&lt;/code&gt; which is made available by that fish fzf plugin.
Now PatrickF1 recommends running the uninstaller script from fzf, but I found another way we can overwrite
the binding by adding the following lines to our &lt;code&gt;fish.config&lt;/code&gt;:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Use fzf.fish History Search</strong></p>
<p>I use Fish Shell with fzf and <a href="https://github.com/PatrickF1/fzf.fish">fish fzf plugin</a>.
I installed fzf using nix and home-manager:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">fzf</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">enableFishIntegration</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>It adds <code>fzf-history-widget</code> script, which is bound to <code>ctrl+r</code>, shell reverse history search.
Which we can see when we run this: <code>bind | grep -e fzf-history-widget -e fzf-file-widget</code></p>
<p>Whereas I wanted to use the <code>_fzf_search_history</code> which is made available by that fish fzf plugin.
Now PatrickF1 recommends running the uninstaller script from fzf, but I found another way we can overwrite
the binding by adding the following lines to our <code>fish.config</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="nb">bind</span> <span class="se">\c</span>r _fzf_search_history
</span></span><span class="line"><span class="cl"><span class="nb">bind</span> <span class="na">-M</span> insert <span class="se">\c</span>r _fzf_search_history
</span></span></code></pre></div><p>So now when I press <code>ctrl+r</code> in my shell I used to get this (before):</p>
<p><img
        loading="lazy"
        src="/posts/2023-09-19-til-how-to-use-fzf-fish-history-search/images/fzf_original.png"
        type=""
        alt="FZF"
        
      /></p>
<p>but now I get this (after):</p>
<p><img
        loading="lazy"
        src="/posts/2023-09-19-til-how-to-use-fzf-fish-history-search/images/fish_fzf.png"
        type=""
        alt="FZF Fish"
        
      /></p>
<h2 id="appendix">Appendix</h2>
<ul>
<li>[My nix fish shell config](<a href="https://gitlab.com/hmaji%5D(https://gitlab.com/hmajid2301/dotfiles/-/blob/a34417ed452fe068ec4a91fba7ef0a14fca31b76/home-manager/shells/fish.nix#L48-49)">https://gitlab.com/hmaji](https://gitlab.com/hmajid2301/dotfiles/-/blob/a34417ed452fe068ec4a91fba7ef0a14fca31b76/home-manager/shells/fish.nix#L48-49)</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>My NixOS Dotfiles Explained</title>
      <link>https://haseebmajid.dev/posts/2023-09-12-how-i-configure-nixos-as-part-of-my-development-workflow/</link>
      <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-09-12-how-i-configure-nixos-as-part-of-my-development-workflow/</guid>
      <description>&lt;p&gt;In this post, we will just go over the basics of how we can configure our setup using a git repo, nix flakes and
home-manager. I will go over how I structured my nix config.&lt;/p&gt;
&lt;details
  class=&#34;notice Info&#34;
  open=&#34;true&#34;
&gt;
    &lt;summary class=&#34;notice-title&#34;&gt;Not an in-depth tutorial&lt;/summary&gt;
  
  Note this will not be an in-depth guide into NixOS/Home Manager itself. That could well be a series on its own.
We will just go over the main ways I configure NixOS/Nix and why I do it the way I do. I recommend doing some reading
and playing around and figuring out what works for you &amp;#x1f604;
&lt;/details&gt;

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;We will be using two different ways to configure our system, NixOS via a &lt;code&gt;configuration.nix&lt;/code&gt; to configure the machine
itself. Which includes partitions, backups, docker anything that needs to be run system-wide. Anything that
needs &amp;ldquo;sudo&amp;rdquo; permissions is configured via this expression. Note we will of course split our nix expressions into smaller
modules. That will be re-used between multiple hosts.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this post, we will just go over the basics of how we can configure our setup using a git repo, nix flakes and
home-manager. I will go over how I structured my nix config.</p>
<details
  class="notice Info"
  open="true"
>
    <summary class="notice-title">Not an in-depth tutorial</summary>
  
  Note this will not be an in-depth guide into NixOS/Home Manager itself. That could well be a series on its own.
We will just go over the main ways I configure NixOS/Nix and why I do it the way I do. I recommend doing some reading
and playing around and figuring out what works for you &#x1f604;
</details>

<h2 id="introduction">Introduction</h2>
<p>We will be using two different ways to configure our system, NixOS via a <code>configuration.nix</code> to configure the machine
itself. Which includes partitions, backups, docker anything that needs to be run system-wide. Anything that
needs &ldquo;sudo&rdquo; permissions is configured via this expression. Note we will of course split our nix expressions into smaller
modules. That will be re-used between multiple hosts.</p>
<p>The second way we will configure our system (most of our config in fact) will be <code>home-manager</code>. This is a Nix tool
to configure things in userland. Such as dotfiles, and most of my apps. So for example here is where I define my neovim
config, and various cli tools I use (like zoxide, fzf). [^1]</p>
<h2 id="git-repo">Git Repo</h2>
<p>Typically NixOS can be configured using a file at <code>/etc/nixos/configuration.nix</code>, however, to edit this file you need
sudo permissions. We also cannot easily track this file in Git. One of the main benefits of using NixOS/Nix is that
we can use declaratively define our machine state, store that in a git repo and then re-use that across multiple devices.</p>
<p>Here is my <a href="https://gitlab.com/hmajid2301/dotfiles">git repo</a>, when setting up my host mesmer it probably took about
20 minutes to setup my entire machine. Most of which was spent downloading, building, and evaluating nix derivations.</p>
<h3 id="flakes">Flakes</h3>
<p>We will also use Nix flakes alongside our git repo.
I won&rsquo;t go into lots of details of what flakes are [^2]. But nix flakes seem to be the preferred way to define our
nix configs. Flakes improve reproducibility by creating a lock file for our dependencies and also creating a project
so it&rsquo;s easier for new people to navigate our Nix config.</p>
<p>A <code>flake.nix</code> file becomes a bit like <code>package.json</code> file in javascript land. Alongside this flake file, a lock file
will be generated. Which will lock our dependencies to specific values. So if anyone else uses our flake they will get
the same versions of the nix derivations that we have. This includes nixpkgs, so even when these are updated we tie
them to a specific version.</p>
<p>Typically when we start using flakes initially they also go in <code>/etc/nixos/flake.nix</code>. Which causes similar problems
as the configuration file. However, this is an easyish way to create a git repo in say <code>~/dotfiles</code> which is a flake
and can be used to configure both our system and home-manager.</p>
<details
  class="notice warning"
  open="true"
>
    <summary class="notice-title">Experimental</summary>
  
  Whilst lots of people in the Nix community have already adopted flakes. It&rsquo;s important to remember they are still an
experimental feature and are likely to be the cause of breaking changes in the future. So use it with caution if you
are worried about this sort of thing.
</details>

<h2 id="getting-started">Getting Started</h2>
<p>So we want to use a git repo and flakes to configure our system. Even before using Nix/NixOS, I was using a dotfiles repo.
Which would be located in my home directory i.e <code>~/dotfiles</code>. So I kept the same location for my nix dotfiles as well.</p>
<p>Then to enable flakes let&rsquo;s add the following to <code>nix.settings.experimental-features = [ &quot;nix-command&quot; &quot;flakes&quot; ];</code>
to our <code>configuration.nix</code> file. Then run <code>sudo nixos-rebuild switch</code> to rebuild our NixOS config.</p>
<h3 id="repo-structure">Repo Structure</h3>
<p>There are 100 different ways to structure our dotfiles repo. I ended up using this
<a href="https://github.com/Misterio77/nix-starter-configs">starter repo (standard version)</a> and used
<a href="https://github.com/Misterio77/nix-config">Misterio77&rsquo;s main repo</a> for inspiration.</p>
<p>Where my repo looks something like this (simplified):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
</span></span><span class="line"><span class="cl">├── flake.lock
</span></span><span class="line"><span class="cl">├── flake.nix
</span></span><span class="line"><span class="cl">├── home-manager
</span></span><span class="line"><span class="cl">├── hosts
</span></span><span class="line"><span class="cl">│   ├── curve
</span></span><span class="line"><span class="cl">│   │   └── home.nix
</span></span><span class="line"><span class="cl">│   ├── framework
</span></span><span class="line"><span class="cl">│   │   ├── configuration.nix
</span></span><span class="line"><span class="cl">│   │   ├── hardware-configuration.nix
</span></span><span class="line"><span class="cl">│   │   ├── home.nix
</span></span><span class="line"><span class="cl">│   │   ├── secrets.yaml
</span></span><span class="line"><span class="cl">│   │   └── users
</span></span><span class="line"><span class="cl">│   └── mesmer
</span></span><span class="line"><span class="cl">│       ├── configuration.nix
</span></span><span class="line"><span class="cl">│       ├── hardware-configuration.nix
</span></span><span class="line"><span class="cl">│       ├── home.nix
</span></span><span class="line"><span class="cl">│       ├── secrets.yaml
</span></span><span class="line"><span class="cl">│       └── users
</span></span><span class="line"><span class="cl">├── LICENSE.md
</span></span><span class="line"><span class="cl">├── modules
</span></span><span class="line"><span class="cl">├── nixos
</span></span><span class="line"><span class="cl">├── overlays
</span></span><span class="line"><span class="cl">├── pkgs
</span></span><span class="line"><span class="cl">├── README.md
</span></span><span class="line"><span class="cl">└── shell.nix
</span></span></code></pre></div><p>Some key bits are:</p>
<ul>
<li><code>flake.nix</code>: The entry point into the dotfiles, defines all of our NixOS hosts and home-manager hosts, inputs etc</li>
<li><code>nixos</code>: Has most of the re-usable NixOS expressions</li>
<li><code>home-manager</code>: Has most of the re-usable home manager nix expressions</li>
<li><code>hosts</code>: After <code>flake.nix</code> these are the secondary entry points into the configuration for each host</li>
</ul>
<h4 id="flakenix">flake.nix</h4>
<p>Here is a simplified version of my <code>flake.nix</code> file:</p>
<pre tabindex="0"><code>{
  description = &#34;My Nix Config&#34;;

  nixConfig = {
    experimental-features = [ &#34;nix-command&#34; &#34;flakes&#34; ];
  };

  inputs = {
    nixpkgs.url = &#34;github:nixos/nixpkgs/nixos-unstable&#34;;
    home-manager.url = &#34;github:nix-community/home-manager&#34;;
  };

  outputs =
    { self
    , nixpkgs
    , home-manager
    , ...
    } @ inputs:
    {
      nixosConfigurations = {
        # Personal laptop
        framework = lib.nixosSystem {
          modules = [ ./hosts/framework/configuration.nix ];
          specialArgs = { inherit inputs outputs; };
        };
      };

      homeConfigurations = {
        # Laptops
        framework = lib.homeManagerConfiguration {
          modules = [ ./hosts/framework/home.nix ];
          pkgs = nixpkgs.legacyPackages.x86_64-linux;
          extraSpecialArgs = { inherit inputs outputs; };
        };

        curve = lib.homeManagerConfiguration {
          modules = [ ./hosts/curve/home.nix ];
          pkgs = nixpkgs.legacyPackages.x86_64-linux;
          extraSpecialArgs = { inherit inputs outputs; };
        };
      };
    };
}
</code></pre><p>We have:</p>
<ul>
<li><code>description</code>: For what the flake is, not important</li>
<li><code>inputs</code>: Other nix flakes I&rsquo;m using as imports, such as home-manager to install the home-manager binary and nixpkgs to use unstable</li>
<li><code>output</code>: Which contains two main bits
<ul>
<li><code>nixosConfiguration</code>: Uses <code>configuration.nix</code> as an entry point (in a specific host file)</li>
<li><code>homeManagerConfiguration</code>: Uses <code>home.nix</code> as an entry point (in specific host file)
<ul>
<li><code>curve</code>: You will notice this host only has home manager config because it is running Ubuntu so only uses home manager, which to be honest is good enough in my opinion</li>
</ul>
</li>
</ul>
</li>
</ul>
<h5 id="flakelock">flake.lock</h5>
<p>In our <code>flake.lock</code> file, we have something like this:</p>
<pre tabindex="0"><code>&#34;nixpkgs_11&#34;: {
  &#34;locked&#34;: {
    &#34;lastModified&#34;: 1693844670,
    &#34;narHash&#34;: &#34;sha256-t69F2nBB8DNQUWHD809oJZJVE+23XBrth4QZuVd6IE0=&#34;,
    &#34;owner&#34;: &#34;nixos&#34;,
    &#34;repo&#34;: &#34;nixpkgs&#34;,
    &#34;rev&#34;: &#34;3c15feef7770eb5500a4b8792623e2d6f598c9c1&#34;,
    &#34;type&#34;: &#34;github&#34;
  },
  &#34;original&#34;: {
    &#34;owner&#34;: &#34;nixos&#34;,
    &#34;ref&#34;: &#34;nixos-unstable&#34;,
    &#34;repo&#34;: &#34;nixpkgs&#34;,
    &#34;type&#34;: &#34;github&#34;
  }
},
</code></pre><p>Where we can see <code>rev</code> is a <a href="https://github.com/NixOS/nixpkgs/commit/3c15feef7770eb5500a4b8792623e2d6f598c9c1">git sha</a>.
In this case, we are looking at a specific branch <code>ref</code>: <code>nixos-unstable</code> so we use the unstable channel,
<a href="https://search.nixos.org/packages?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=ag">https://search.nixos.org/packages?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=ag</a>.</p>
<p>So if we don&rsquo;t ever update our <code>flake.lock</code> we will forever be tied to this version of the unstable channel at that
moment. Of course, that branch is getting updated multiple times a day. So to update our tools/apps etc. we need to update
this lock file. We can do this by running <code>nix flake update</code>, in our dotfiles repo.</p>
<h4 id="nixos">NixOS</h4>
<p>Let&rsquo;s take a look at how we configure a device using NixOS, so looking at my <code>hosts/framework/configuration.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">pkgs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hardware</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">framework-12th-gen-intel</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">nix-gaming</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">nixosModules</span><span class="o">.</span><span class="n">default</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">./hardware-configuration.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">./users/haseeb</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/global</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/backup.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/greetd.nix</span>
</span></span><span class="line"><span class="cl">    <span class="sr">../../nixos/optional/mullvad.nix</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># Enable networking</span>
</span></span><span class="line"><span class="cl">  <span class="n">networking</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">networkmanager</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">hostName</span> <span class="o">=</span> <span class="s2">&#34;framework&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">boot</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">loader</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">systemd-boot</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="cl">      <span class="n">efi</span><span class="o">.</span><span class="n">canTouchEfiVariables</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">initrd</span><span class="o">.</span><span class="n">luks</span><span class="o">.</span><span class="n">devices</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">root</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-uuid/fc112246-8ce0-47c7-95e5-106be34e9501&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">preLVM</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">kernelPackages</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">linuxPackages_latest</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><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;23.05&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The main thing this acts as an entry point for our NixOS config (system-wide). This allows us to specify which packages we
want to on different devices. Essentially all the imports are re-usable nix expressions, that can be shared across
devices.</p>
<p>Taking a look at an optional expression say <code>greetd.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">services</span><span class="o">.</span><span class="n">greetd</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">initial_session</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">command</span> <span class="o">=</span> <span class="s2">&#34;Hyprland&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">user</span> <span class="o">=</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="n">default_session</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">command</span> <span class="o">=</span> <span class="s2">&#34;initial_session&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="n">environment</span><span class="o">.</span><span class="n">etc</span><span class="o">.</span><span class="s2">&#34;greetd/environments&#34;</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    Hyprland
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Here you can see we define a greetd service to run, which will run Hyprland when we log in (and which user to log us into).</p>
<p>Where we can find a full list of <a href="https://search.nixos.org/options?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=greetd">options here</a>.</p>
<h4 id="home-manager">Home Manager</h4>
<p>Similar to the above section, the <code>hosts/framework/home.nix</code> acts as the entry point to our home-manager config.
Here is where most of my nix expression/config lies. This configures the home directory of a user. But can also be used
to install and configure most of our tools and apps. Let&rsquo;s take a look at an example file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">lib</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">pkgs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">config</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="n">outputs</span>
</span></span><span class="line"><span class="cl"><span class="o">,</span> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
</span></span><span class="line"><span class="cl">      <span class="n">inputs</span><span class="o">.</span><span class="n">nixvim</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">nixvim</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/desktops/hyprland</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/shells/fish.nix</span>
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/terminals/foot.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/browsers/firefox.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/programs/cli</span>
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/editors/nvim</span>
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/programs/multiplexers/tmux.nix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="sr">../../home-manager/games</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">colorscheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">catppuccin-frappe</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">wallpaper</span> <span class="o">=</span> <span class="s2">&#34;~/dotfiles/home-manager/wallpapers/rainbow-nix.jpg&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">host</span> <span class="o">=</span> <span class="s2">&#34;framework&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">nix</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">package</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nix</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">experimental-features</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;nix-command&#34;</span> <span class="s2">&#34;flakes&#34;</span> <span class="s2">&#34;repl-flake&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="n">warn-dirty</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">systemd</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">startServices</span> <span class="o">=</span> <span class="s2">&#34;sd-switch&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">programs</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">home-manager</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="cl">    <span class="n">git</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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">home</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">username</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;haseeb&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">homeDirectory</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;/home/</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">home</span><span class="o">.</span><span class="n">username</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">stateVersion</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;23.05&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">sessionPath</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;$HOME/.local/bin&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">sessionVariables</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">TERMINAL</span> <span class="o">=</span> <span class="s2">&#34;alacritty&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">EDITOR</span> <span class="o">=</span> <span class="s2">&#34;nvim&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">BROWSER</span> <span class="o">=</span> <span class="s2">&#34;firefox&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>You can see the example looks very similar to our <code>configuration.nix</code> file. I try to configure my tooling in home-manager
first, if I can. We don&rsquo;t need sudo permissions to do this. The more that lives in my home directory the easier is it to backup.
For example, we can take a look my <code>programs/fzf.nix</code> expression:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">fzf</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">enableFishIntegration</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>We can find a set of <a href="https://mipmip.github.io/home-manager-option-search/?query=fzf">home-manager options here</a>.
Not everything is here (especially nixvim).</p>
<p>That&rsquo;s It! I didn&rsquo;t go into lots of specifics in this article but more a general view of how I go about configuring
my system. Hopefully, it made it more clear how I use NixOS. And even a bit of Nix on non-NixOS-based machines.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/tree/3e35e17bab99518ba4136c552a9de790daf9ae0d">My dotfiles</a></li>
<li><a href="https://github.com/Misterio77/nix-config">Misterio77&rsquo;s Repo</a></li>
<li><a href="https://mipmip.github.io/home-manager-option-search/?query=fzf">home-manager options super useful</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Check if Another Option Is Set in Home Manager (Nix)</title>
      <link>https://haseebmajid.dev/posts/2023-09-10-til-how-to-check-if-another-option-is-set-in-home-manager-nix/</link>
      <pubDate>Sun, 10 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-09-10-til-how-to-check-if-another-option-is-set-in-home-manager-nix/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Check if Another Option Is Set in Home Manager (Nix)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently I was adding sway to my nix config (setup via home-manager). I already had Hyprland config, I wanted both
sway and Hyprland to use my waybar config with some slight differences. So basically I want to check if the current
host machine is using Sway or Hyprland (I am assuming we will only use one).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The main reason for using Sway is my work laptop uses Ubuntu 22.04, It&amp;rsquo;s not easy to run Hyprland on a &amp;ldquo;stable&amp;rdquo; distro like Ubuntu better suited to Arch or NixOS.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Check if Another Option Is Set in Home Manager (Nix)</strong></p>
<p>Recently I was adding sway to my nix config (setup via home-manager). I already had Hyprland config, I wanted both
sway and Hyprland to use my waybar config with some slight differences. So basically I want to check if the current
host machine is using Sway or Hyprland (I am assuming we will only use one).</p>
<blockquote>
<p>The main reason for using Sway is my work laptop uses Ubuntu 22.04, It&rsquo;s not easy to run Hyprland on a &ldquo;stable&rdquo; distro like Ubuntu better suited to Arch or NixOS.</p>
</blockquote>
<p>If sway is enabled include some specific config in my Waybar config else include the Hyprland config. So first of all
I have a file called <code>sway.nix</code> which looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">sway</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">  <span class="n">package</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">swayfx</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I then have a host file for my work laptop called <code>curve/home.nix</code> which imports this sway expression:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">imports</span> <span class="err">=</span> <span class="p">[</span> <span class="sr">../../home-manager/desktops/sway.nix</span> <span class="p">];</span>
</span></span></code></pre></div><p>Finally, the main part of this article, let&rsquo;s look at my <code>waybar.nix</code> which is imported by <code>sway.nix</code> (and <code>hyprland.nix</code>) expression, which
Check if sway is enabled (which happens if the <code>sway.nix</code> is imported).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">waybar</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules-left</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;custom/launcher&#34;</span>
</span></span><span class="line hl"><span class="cl">          <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">wayland</span><span class="o">.</span><span class="n">windowManager</span><span class="o">.</span><span class="n">sway</span><span class="o">.</span><span class="n">enable</span> <span class="o">==</span> <span class="no">true</span>
</span></span><span class="line"><span class="cl">            <span class="k">then</span> <span class="s2">&#34;sway/workspaces&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span> <span class="s2">&#34;hyprland/workspaces&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;custom/currentplayer&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;custom/player&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;custom/audio_idle_inhibitor&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span></code></pre></div><p>In the example above <code>config.wayland.windowManager.sway.enable == true</code>, we just do a simple if statement check to
Decide which Waybar module to show (sway or Hyprland).</p>
<p>That&rsquo;s it! How we can check if other expressions can use attributes set in other expression files.
If you have suggestions to make this cleaner I&rsquo;m all ears! This is not cleanest way to do something like this.
But since these are just my own dotfiles I know I will only use one of Sway or Hyprland on my devices.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Access System in Home Manager Using Flakes</title>
      <link>https://haseebmajid.dev/posts/2023-09-05-til-how-to-access-system-in-home-manager-using-flakes/</link>
      <pubDate>Tue, 05 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-09-05-til-how-to-access-system-in-home-manager-using-flakes/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Access System in Home Manager Using Flakes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recently I needed to install devenv using flakes in home-manager. One of the things I needed to pass to was the type
of system to install on i.e. &lt;code&gt;&amp;quot;x86_64-linux&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So as I temp hack I had something like: &lt;code&gt;inputs.devenv.packages.&amp;quot;x86_64-linux&amp;quot;.devenv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However I was able to access the system using the &lt;code&gt;pkgs&lt;/code&gt; attribute like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;inputs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;inputs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;devenv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;system&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;devenv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where my &lt;code&gt;flake.nix&lt;/code&gt; looks something like:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Access System in Home Manager Using Flakes</strong></p>
<p>Recently I needed to install devenv using flakes in home-manager. One of the things I needed to pass to was the type
of system to install on i.e. <code>&quot;x86_64-linux&quot;</code>.</p>
<p>So as I temp hack I had something like: <code>inputs.devenv.packages.&quot;x86_64-linux&quot;.devenv</code>.</p>
<p>However I was able to access the system using the <code>pkgs</code> attribute like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">devenv</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">devenv</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where my <code>flake.nix</code> looks something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">outputs</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">self</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">nixpkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">home-manager</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="o">@</span> <span class="n">inputs</span><span class="p">:</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">inherit</span> <span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># Desktops</span>
</span></span><span class="line"><span class="cl">      <span class="n">mesmer</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="o">=</span> <span class="p">[</span><span class="sr">./hosts/mesmer/home.nix</span><span class="p">];</span>
</span></span><span class="line hl"><span class="cl">        <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="n">x86_64-linux</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span><span class="k">inherit</span> <span class="n">inputs</span> <span class="n">outputs</span><span class="p">;};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>You can see here the system is defined with the pkgs, as I guess we need to know for which architecture we should
build for i.e. amd, arch etc. But yeh thats it! For use within home-manager it seems we can use <code>pkgs.system</code>, to
access the architecture, so we don&rsquo;t need to hardcode it.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Fix tmux-resurrect on NixOS</title>
      <link>https://haseebmajid.dev/posts/2023-09-01-til-how-to-fix-tmux-resurrect-on-nixos/</link>
      <pubDate>Fri, 01 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-09-01-til-how-to-fix-tmux-resurrect-on-nixos/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Fix tmux-resurrect on NixOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When I moved to NixOS I noticed that &lt;a href=&#34;https://github.com/tmux-plugins/tmux-resurrect&#34;&gt; tmux-resurrect &lt;/a&gt; stop restoring
some applications such as &lt;code&gt;man&lt;/code&gt; and &lt;code&gt;nvim&lt;/code&gt;. Like it used to on my Arch machine. I recently found a solution to my
problem (thanks to a lovely chap on the nixos discourse).&lt;/p&gt;
&lt;p&gt;By adding the following lines to our tmux config:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-tmux&#34; data-lang=&#34;tmux&#34;&gt;resurrect_dir=&amp;#34;$HOME/.tmux/resurrect&amp;#34;
set -g @resurrect-dir $resurrect_dir
set -g @resurrect-hook-post-save-all &amp;#39;target=$(readlink -f $resurrect_dir/last); sed &amp;#34;s| --cmd .*-vim-pack-dir||g; s|/etc/profiles/per-user/$USER/bin/||g; s|/home/$USER/.nix-profile/bin/||g&amp;#34; $target | sponge $target&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What this does is it edits the tmux-resurrect file from this:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Fix tmux-resurrect on NixOS</strong></p>
<p>When I moved to NixOS I noticed that <a href="https://github.com/tmux-plugins/tmux-resurrect"> tmux-resurrect </a> stop restoring
some applications such as <code>man</code> and <code>nvim</code>. Like it used to on my Arch machine. I recently found a solution to my
problem (thanks to a lovely chap on the nixos discourse).</p>
<p>By adding the following lines to our tmux config:</p>
<pre tabindex="0"><code class="language-tmux" data-lang="tmux">resurrect_dir=&#34;$HOME/.tmux/resurrect&#34;
set -g @resurrect-dir $resurrect_dir
set -g @resurrect-hook-post-save-all &#39;target=$(readlink -f $resurrect_dir/last); sed &#34;s| --cmd .*-vim-pack-dir||g; s|/etc/profiles/per-user/$USER/bin/||g; s|/home/$USER/.nix-profile/bin/||g&#34; $target | sponge $target&#39;
</code></pre><p>What this does is it edits the tmux-resurrect file from this:</p>
<pre tabindex="0"><code># bat ~/.tmux/resurrect/last --plain

pane    dotfiles    0   1   :*  0   nvim ~/dotfiles :/home/haseeb/dotfiles  1   nvim    :/home/haseeb/.nix-profile/bin/nvim --cmd lua vim.g.loaded_node_provider=0;vim.g.loaded_perl_provider=0;vim.g.loaded_python_provider=0;vim.g.python3_host_prog=&#39;/nix/store/4n4d0f1xd14gl4pfymdcqb9pmagcyyfj-neovim-0.9.1/bin/nvim-python3&#39;;vim.g.ruby_host_prog=&#39;/nix/store/4n4d0f1xd14gl4pfymdcqb9pmagcyyfj-neovim-0.9.1/bin/nvim-ruby&#39;
</code></pre><p>to this:</p>
<pre tabindex="0"><code># bat ~/.tmux/resurrect/last --plain

pane    dotfiles    0   1   :*  0   nvim ~/dotfiles :/home/haseeb/dotfiles  1   nvim    :nvim
</code></pre><p>NOTE: we are just left with <code>:nvim</code> as the binary to run (from tmux-resurrect perspective).
Then to restore my neovim session we could use a plugin which creates a <code>Session.vim</code> file in the local directory
of that project, that tmux-resurrect can use to restore the actual neovim session rather than just running neovim.</p>
<p>However I don&rsquo;t want to manage session files like that. So I use <a href="https://github.com/rmagatti/auto-session"> <code>auto-session</code> </a>
which checks if a session exists in a specific directory and if it does it automatically restores the last saved session
when neovim opens.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://discourse.nixos.org/t/how-to-get-tmux-resurrect-to-restore-neovim-sessions/30819/2">Discourse Thread</a></li>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/06bf4ad267beb6693b941ef51d880e4d0fc1df0a/home-manager/programs/multiplexers/tmux.nix#L136-147">My tmux config</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Use Cachix Devenv to Setup Developer Environments</title>
      <link>https://haseebmajid.dev/posts/2023-08-26-how-to-use-cachix-devenv-to-setup-developer-environments/</link>
      <pubDate>Sat, 26 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-08-26-how-to-use-cachix-devenv-to-setup-developer-environments/</guid>
      <description>&lt;p&gt;In this post, I will go over how you can use Cachix&amp;rsquo;s &lt;a href=&#34;https://devenv.sh/&#34;&gt;devenv&lt;/a&gt; tool to help create/set up consistent
repeatable developer environments. You could use nix flakes if you wanted to as well, without needing another tool.
However, I like how devenv provides a few other &amp;ldquo;tools&amp;rdquo; within that we can set up from a single &lt;code&gt;devenv.nix&lt;/code&gt; file. Such as
pre-commit hooks, container support etc.&lt;/p&gt;
&lt;p&gt;This blog leverages devenv to create/set up its developer environment.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this post, I will go over how you can use Cachix&rsquo;s <a href="https://devenv.sh/">devenv</a> tool to help create/set up consistent
repeatable developer environments. You could use nix flakes if you wanted to as well, without needing another tool.
However, I like how devenv provides a few other &ldquo;tools&rdquo; within that we can set up from a single <code>devenv.nix</code> file. Such as
pre-commit hooks, container support etc.</p>
<p>This blog leverages devenv to create/set up its developer environment.</p>
<p><strong>Note:</strong> I&rsquo;m pretty new to using devenv myself so I&rsquo;m probably going to make a follow-up post as my developer workflow
changes.</p>
<h2 id="why-use-devenv">Why Use devenv</h2>
<p>Well, I mainly use it in my projects in two main ways.</p>
<p>To set up pre-commit hooks and to make sure certain binaries and tools are available. Imagine another developer
cloning our project doesn&rsquo;t need to make sure they have say <code>hugo</code> or <code>go-task</code> globally available.
It is set up automatically if they are using <code>devenv</code> and <a href="https://direnv.net/"><code>direnv</code></a>.</p>
<p>It can also be used to manage services like Postgresql.</p>
<h2 id="install-devenv">Install Devenv</h2>
<p>First I will assume you are using home-manager to manage your nix environment and are using nix flakes.
So first let&rsquo;s install devenv, go to <code>flake.nix</code> and add the following input:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">inputs</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">devenv</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:cachix/devenv/latest&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>This will make it available to the rest of our configuration as input. Now my flake config looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">outputs</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">self</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">nixpkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">home-manager</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="o">@</span> <span class="n">inputs</span><span class="p">:</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">    <span class="k">inherit</span> <span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="n">outputs</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">lib</span> <span class="o">=</span> <span class="n">nixpkgs</span><span class="o">.</span><span class="n">lib</span> <span class="o">//</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">systems</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;x86_64-linux&#34;</span> <span class="s2">&#34;aarch64-linux&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">forEachSystem</span> <span class="o">=</span> <span class="n">f</span><span class="p">:</span> <span class="n">lib</span><span class="o">.</span><span class="n">genAttrs</span> <span class="n">systems</span> <span class="p">(</span><span class="n">sys</span><span class="p">:</span> <span class="n">f</span> <span class="n">pkgsFor</span><span class="o">.</span><span class="si">${</span><span class="n">sys</span><span class="si">}</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgsFor</span> <span class="o">=</span> <span class="n">nixpkgs</span><span class="o">.</span><span class="n">legacyPackages</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">in</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">inherit</span> <span class="n">lib</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># Desktops</span>
</span></span><span class="line"><span class="cl">      <span class="n">mesmer</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="o">=</span> <span class="p">[</span><span class="sr">./hosts/mesmer/home.nix</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <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="n">x86_64-linux</span><span class="p">;</span>
</span></span><span class="line hl"><span class="cl">        <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span><span class="k">inherit</span> <span class="n">inputs</span> <span class="n">outputs</span><span class="p">;};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>The home module inherits the inputs from the flake file, so we can access the devenv input in our home-manager
config. Then in in our <code>home.nix</code> module we can add something:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="n">pkgs</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">devenv</span><span class="o">.</span><span class="n">packages</span><span class="o">.</span><span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">system</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">devenv</span>
</span></span><span class="line"><span class="cl">    <span class="n">pkgs</span><span class="o">.</span><span class="n">cachix</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">direnv</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">nix-direnv</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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>In my config, I have this in its module called <code>devenv.nix</code>, because I like to split up my config.
To install devenv we can do <code>inputs.devenv.packages.&quot;${pkgs.system}&quot;.devenv</code>. We also need cachix (I think), so *
installed that from Nix packages. Like we would with any other package.</p>
<p>You will also notice I setup another tool called <code>direnv</code>, which is a generic tool that allows us to create a new shell
env when we change directories if there is a <code>.envrc</code>, where we can load things like env variables etc.</p>
<p>However, we can also leverage it to auto-run out devenv development environment i.e. <code>devenv shell</code> for us.
If set up devenv will create a <code>.envrc</code> file which contains <code>devenv use</code>. So when we change the directory, to one with devenv
setup it will set up our devenv environment automatically.</p>
<p><strong>Note</strong>: The first time we use direnv we need to run <code>direnv allow</code>, the output on your shell will remind you to do this.</p>
<p>After this, you can run your normal command to update your state using home-manager i.e.
<code>home-manager switch --flake ~/dotfiles#mesmer</code>.</p>
<p>Without <code>direnv</code> we could also run <code>devenv shell</code>, however, I found this would change my shell to bash whereas I normally
use fish.</p>
<h2 id="create-an-env">Create an env</h2>
<p>Okay now that we have devenv installed, let&rsquo;s set up our first devenv.
First we run <code>devenv init</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">devenv init
</span></span><span class="line"><span class="cl">Creating .envrc
</span></span><span class="line"><span class="cl">Creating devenv.nix
</span></span><span class="line"><span class="cl">Creating devenv.yaml
</span></span><span class="line"><span class="cl">Appending defaults to .gitignore
</span></span><span class="line"><span class="cl">Done.
</span></span><span class="line"><span class="cl">direnv is installed. Running direnv allow.
</span></span><span class="line"><span class="cl">direnv: loading ~/Downloads/.envrc
</span></span><span class="line"><span class="cl">direnv: loading https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc <span class="o">(</span>sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0<span class="o">=)</span>
</span></span><span class="line"><span class="cl">direnv: using devenv
</span></span><span class="line"><span class="cl">direnv: .envrc changed, reloading
</span></span><span class="line"><span class="cl">Building shell ...
</span></span><span class="line"><span class="cl">warning: creating lock file <span class="s1">&#39;/home/haseeb/Downloads/devenv.lock&#39;</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>1/4 built, 1/0/1 copied <span class="o">(</span>4.2/42.7 MiB<span class="o">)</span>, 4.1/40.5 MiB DL<span class="o">]</span> fetching git-2.41.0-debug from https://cache.nixos.orgdirenv: <span class="o">([</span>/nix/store/h77a0hqm3jcfqq7fgs310rf5l9w9g66y-direnv-2.32.3/bin/direnv <span class="nb">export</span> fish<span class="o">])</span> is taking a <span class="k">while</span> to execute. Use CTRL-C to give up.
</span></span><span class="line"><span class="cl">direnv: updated devenv shell cache
</span></span><span class="line"><span class="cl">hello from devenv
</span></span><span class="line"><span class="cl">git version 2.41.0
</span></span><span class="line"><span class="cl">direnv: <span class="nb">export</span> +C_INCLUDE_PATH +DEVENV_DOTFILE +DEVENV_PROFILE +DEVENV_ROOT +DEVENV_STATE +GREET +IN_NIX_SHELL +LIBRARY_PATH +PKG_CONFIG_PATH +name ~LD_LIBRARY_PATH ~PATH ~XDG_CONFIG_DIRS ~XDG_DATA_DIRS
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ls -al
</span></span></code></pre></div><p>If we explore a bit more:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~/Downloads
</span></span><span class="line"><span class="cl">❯ exa -al
</span></span><span class="line"><span class="cl">drwxr-xr-x    - haseeb <span class="m">25</span> Aug 20:00 .devenv
</span></span><span class="line"><span class="cl">.rw-r--r-- 3.4k haseeb <span class="m">25</span> Aug 19:59 .devenv.flake.nix
</span></span><span class="line"><span class="cl">drwxr-xr-x    - haseeb <span class="m">25</span> Aug 20:00 .direnv
</span></span><span class="line"><span class="cl">.rw-r--r--  <span class="m">176</span> haseeb <span class="m">25</span> Aug 19:59 .envrc
</span></span><span class="line"><span class="cl">.rw-r--r--   <span class="m">93</span> haseeb <span class="m">25</span> Aug 19:59 .gitignore
</span></span><span class="line"><span class="cl">.rw-r--r--  <span class="m">474</span> haseeb <span class="m">23</span> Aug 23:02 config.yml
</span></span><span class="line"><span class="cl">.rw-r--r-- 4.1k haseeb <span class="m">25</span> Aug 19:59 devenv.lock
</span></span><span class="line"><span class="cl">.rw-r--r--  <span class="m">567</span> haseeb <span class="m">25</span> Aug 19:59 devenv.nix
</span></span><span class="line"><span class="cl">.rw-r--r--   <span class="m">66</span> haseeb <span class="m">25</span> Aug 19:59 devenv.yaml
</span></span><span class="line"><span class="cl">direnv: error /home/haseeb/Downloads/a/.envrc is blocked. Run <span class="sb">`</span>direnv allow<span class="sb">`</span> to approve its content
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">~/Downloads
</span></span><span class="line"><span class="cl">❯ direnv allow
</span></span><span class="line"><span class="cl">direnv: loading ~/Downloads/a/.envrc
</span></span><span class="line"><span class="cl">direnv: loading https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc <span class="o">(</span>sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0<span class="o">=)</span>
</span></span><span class="line"><span class="cl">direnv: using devenv
</span></span><span class="line"><span class="cl">direnv: .envrc changed, reloading
</span></span><span class="line"><span class="cl">Building shell ...
</span></span><span class="line"><span class="cl">direnv: updated devenv shell cache
</span></span><span class="line"><span class="cl">hello from devenv
</span></span><span class="line"><span class="cl">git version 2.41.0
</span></span><span class="line"><span class="cl">direnv: <span class="nb">export</span> +C_INCLUDE_PATH +DEVENV_DOTFILE +DEVENV_PROFILE +DEVENV_ROOT +DEVENV_STATE +GREET +IN_NIX_SHELL +LIBRARY_PATH +PKG_CONFIG_PATH +name ~LD_LIBRARY_PATH ~PATH ~XDG_CONFIG_DIRS ~XDG_DATA_DIRS
</span></span></code></pre></div><p>We&rsquo;ve now set up direnv so it will run our devenv env automatically.</p>
<h3 id="devenvnix">devenv.nix</h3>
<p>The meat and potatoes of our environment exist here, so let us open the file it will look like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/basics/</span>
</span></span><span class="line"><span class="cl">  <span class="n">env</span><span class="o">.</span><span class="n">GREET</span> <span class="o">=</span> <span class="s2">&#34;devenv&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/packages/</span>
</span></span><span class="line"><span class="cl">  <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">git</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/scripts/</span>
</span></span><span class="line"><span class="cl">  <span class="n">scripts</span><span class="o">.</span><span class="n">hello</span><span class="o">.</span><span class="n">exec</span> <span class="o">=</span> <span class="s2">&#34;echo hello from $GREET&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">enterShell</span> <span class="o">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    hello
</span></span></span><span class="line"><span class="cl"><span class="s1">    git --version
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/languages/</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># languages.nix.enable = true;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/pre-commit-hooks/</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># pre-commit.hooks.shellcheck.enable = true;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/processes/</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># processes.ping.exec = &#34;ping example.com&#34;;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># See full reference at https://devenv.sh/reference/options/</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h4 id="entershell">enterShell</h4>
<p>This also explains some of the input we saw above i.e</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hello from devenv
</span></span><span class="line"><span class="cl">git version 2.41.0
</span></span></code></pre></div><p>Which matches what&rsquo;s in our <code>enterShell</code>, so this is run when we enter the devenv environment.</p>
<h4 id="env">env</h4>
<p>We can also set ENV variables using the <code>env</code> i.e. <code>env.GREET</code> makes the greet env variable inside the devenv.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="nv">$GREET</span>
</span></span><span class="line"><span class="cl">devenv
</span></span></code></pre></div><h3 id="packages">packages</h3>
<p>These are packages we want to be available in our devenv, that we don&rsquo;t need to globally installed. These are the same
ones available on <a href="https://search.nixos.org/packages?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=git">nixos pkgs</a>.</p>
<p>We can search for packages on the cli using <code>devenv search</code> i.e.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">devenv search go_1_19
</span></span><span class="line"><span class="cl">name          version  description
</span></span><span class="line"><span class="cl">----          -------  -----------
</span></span><span class="line"><span class="cl">pkgs.go_1_19  1.19.12  The Go Programming language
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">No options found <span class="k">for</span> <span class="s1">&#39;go_1_19&#39;</span>.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Found <span class="m">1</span> packages and <span class="m">0</span> options <span class="k">for</span> <span class="s1">&#39;go_1_19&#39;</span>.
</span></span></code></pre></div><p>Now this will guarantee that these packages are available within our devenv. This for me is one of the biggest reasons
to use devenv. So now other devs don&rsquo;t need to make sure they have certain tools installed globally. Such as say
<code>jq</code>, we can just make them available in a devenv.</p>
<h4 id="scripts">scripts</h4>
<p>We can also make shell scripts available in a single location like the <code>hello</code> script above. This works well for simple
one-liners. Then within the devenv we can do:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> hello
</span></span><span class="line"><span class="cl">hello from devenv
</span></span></code></pre></div><p>We can also specify tools to have available for shell script but not make them available in the devenv. We can do
something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">.</span><span class="n">silly-example</span><span class="o">.</span><span class="n">exec</span> <span class="err">=</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">curl</span><span class="si">}</span><span class="s1">/bin/curl &#34;https://httpbin.org/get?$1&#34; | </span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">jq</span><span class="si">}</span><span class="s1">/bin/jq &#39;.args&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span></code></pre></div><p>This means the script can use <code>jq</code> and <code>curl</code>.</p>
<h4 id="pre-commit">pre-commit</h4>
<p>The other main construct I use is pre-commit hooks, this will auto-generate a <code>.pre-commit-config.yaml</code> and add it
to our <code>.gitignore</code>. As it is generated from the <code>devenv.nix</code> file. We can define them like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">pre-commit</span><span class="o">.</span><span class="n">hooks</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># built in</span>
</span></span><span class="line"><span class="cl">    <span class="n">shellcheck</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="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># custom</span>
</span></span><span class="line"><span class="cl">    <span class="n">golangci-lint</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">      <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;golangci-lint&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Lint my golang code&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">files</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\.</span><span class="s2">go$&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">entry</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">golangci-lint</span><span class="si">}</span><span class="s2">/bin/golangci-lint run --new-from-rev HEAD --fix&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">require_serial</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">pass_filenames</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>The <code>spellcheck</code> is a <a href="https://devenv.sh/reference/options/#pre-commithooks">builtin hooks</a>.
Where <code>golangci-lint</code>, is a custom hook we have defined ourselves.</p>
<h4 id="updating">Updating</h4>
<p>Finally, if we want to update the nixpkgs for example, say when a new version of Golang releases. Normally we could
<code>nix flake update</code>, to update all of our nix flake inputs. We can do the same devenv we do <code>devenv update</code>.
This updates the <code>devenv.lock</code>, which is the same as <code>flake.lock</code> file.</p>
<p>The lock files tie us to a specific version of nixpkgs so that means as long as this file stays the same we will install the version of all the tools as anyone else who runs <code>devenv</code>.</p>
<h3 id="why-not-devcontainers">Why not devcontainers?</h3>
<p>So as a slight aside you might be asking why not use <a href="https://containers.dev/">devcontainers</a>. Well, the main reason
for not doing devcontainers is that I lose access to my shell, with all of my tools. I needed to do some funky stuff
with a <a href="https://haseebmajid.dev/posts/2022-12-15-how-to-use-dotbot-to-personalise-your-vscode-devcontainers/">dotfiles repo</a>
and a dotfiles script. It ended up slowing me down more than providing value.</p>
<p>I think Nix Flakes/devenv provides a good middle ground. They are also naturally far more reproducible than docker containers
or dev containers.</p>
<p><strong>P.S:</strong> At some point I will try out <a href="https://www.jetpack.io/devbox/docs/">devbox</a> and normal
<a href="https://github.com/the-nix-way/dev-templates"> nix flakes </a>.</p>
<p>That&rsquo;s It! We set up a devenv!</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/gomodoro-cli">Go Project using devenv</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>How Sync Your Shell History With Atuin in Nix</title>
      <link>https://haseebmajid.dev/posts/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix/</link>
      <pubDate>Sat, 12 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://atuin.sh/docs/&#34;&gt;Atuin&lt;/a&gt; is a great tool I recently discovered that can be used to sync our shell history across
multiple machines. We can either self-host this or use the &amp;ldquo;officially&amp;rdquo; hosted one. In a future article, I will show
you how you can self-host your version of Atuin on fly.io. But for this article, I will assume you have a server
setup. Your history is end-to-end encrypted so the official server is safe to use and store your history on.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://atuin.sh/docs/">Atuin</a> is a great tool I recently discovered that can be used to sync our shell history across
multiple machines. We can either self-host this or use the &ldquo;officially&rdquo; hosted one. In a future article, I will show
you how you can self-host your version of Atuin on fly.io. But for this article, I will assume you have a server
setup. Your history is end-to-end encrypted so the official server is safe to use and store your history on.</p>
<p>It supports the main shells:</p>
<ul>
<li>fish</li>
<li>bash</li>
<li>zsh</li>
<li>nushell</li>
</ul>
<h2 id="setup">Setup</h2>
<p>Now let&rsquo;s see how we can setup this up on our Nix machine, in this example I will be using home-manager. There is a
<a href="https://mipmip.github.io/home-manager-option-search/?query=atuin">home-manager module</a> which makes setting up Atuin a lot easier.</p>
<p>We can create a new file called <code>atuin.nix</code> which looks a bit like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">atuin</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># Uncomment this to use your instance</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># sync_address = &#34;https://majiy00-shell.fly.dev&#34;;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where the settings are the various config options that Atuin lets us set.
You can find more of <a href="https://atuin.sh/docs/config/">them here</a>.</p>
<h3 id="first-machine">First Machine</h3>
<p>On our first machine, before we synced our shell history, we need to create an account. To do run the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">atuin register -u &lt;YOUR_USERNAME&gt; -e &lt;YOUR EMAIL&gt;
</span></span></code></pre></div><p>Then we want to get our key, <code>atuin key</code>. This is our encryption key and should be kept PRIVATE 🔒.
Don&rsquo;t share it with anyone, store it somewhere safe. If you lose this key you won&rsquo;t be able to recover your shell
history from Atuin anymore.</p>
<p>Next, we can import our existing shell history to Atuin by running <code>atuin import auto</code>, which will import history
from our current shell. We can also specify which shell to use <code>atuin import zsh</code> for example.</p>
<h4 id="sops-nix">sops-nix</h4>
<p>If you are using a tool like <a href="https://github.com/Mic92/sops-nix">sops-nix</a> to manage secrets in nix. We can add
the following lines to our code, which contain the Atuin key. So we don&rsquo;t have to manually copy the key between
multiple devices.</p>
<p>Again I&rsquo;ll do another article on how we can set up sops-nix with home-manager at some point.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">atuin</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">key_path</span> <span class="o">=</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">atuin_key</span><span class="o">.</span><span class="n">path</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">sops</span><span class="o">.</span><span class="n">secrets</span><span class="o">.</span><span class="n">atuin_key</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">sopsFile</span> <span class="o">=</span> <span class="sr">../secrets.yaml</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="other-machines">Other Machines</h3>
<p>You will need to have your Atuin key available, either manually copied over or by using a secret manager as I
used with sops-nix. Don&rsquo;t store your Atuin key directly in source control.</p>
<p>Then we can do something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">atuin login -u &lt;USERNAME&gt;
</span></span><span class="line"><span class="cl">atuin sync
</span></span></code></pre></div><h3 id="gotcha">Gotcha</h3>
<p>If you notice an error like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">atuin account register
</span></span><span class="line"><span class="cl">Please enter username: hmajid2301
</span></span><span class="line"><span class="cl">Please enter email: hello@haseebmajid.dev
</span></span><span class="line"><span class="cl">Please enter password:
</span></span><span class="line"><span class="cl">Error: error decoding response body: expected value at line <span class="m">1</span> column <span class="m">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Caused by:
</span></span><span class="line"><span class="cl">    expected value at line <span class="m">1</span> column <span class="m">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Location:
</span></span><span class="line"><span class="cl">    /build/source/atuin-client/src/api_client.rs:63:21
</span></span></code></pre></div><p>Make sure your sync address does not end in <code>/</code> i.e. <code>atuin.dev</code> instead
of <code>atuin.dev/</code></p>
<h3 id="my-config">My config</h3>
<p>Here is my Atuin config, where I am using a self-hosted server. I also set a sync frequency of 15 minutes.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">atuin</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">sync_address</span> <span class="o">=</span> <span class="s2">&#34;https://majiy00-shell.fly.dev&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">sync_frequency</span> <span class="o">=</span> <span class="s2">&#34;15m&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">dialect</span> <span class="o">=</span> <span class="s2">&#34;uk&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">key_path</span> <span class="o">=</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">atuin_key</span><span class="o">.</span><span class="n">path</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">sops</span><span class="o">.</span><span class="n">secrets</span><span class="o">.</span><span class="n">atuin_key</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">sopsFile</span> <span class="o">=</span> <span class="sr">../secrets.yaml</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>That&rsquo;s It! We now have Atuin syncing our shell history between multiple.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://atuin.sh/docs/config/">Atuin</a></li>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/0c12ac20c3ab08fa3e76352c4e352a4adb9c3c9a/home-manager/atuin/default.nix">My nix config</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to get Kanshi to work on NixOS and Hyprland</title>
      <link>https://haseebmajid.dev/posts/2023-07-25-nixos-kanshi-and-hyprland/</link>
      <pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-07-25-nixos-kanshi-and-hyprland/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to get Kanshi to work on NixOS and Hyprland&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have been using Kanshi to setup my monitor setups automagically depending on which monitors are plugged
i.e. if my laptop is docked or not. If it is docked I want my laptop display to be off, when not docked I want
it to be on. So my kanshi config file &lt;code&gt;~/.config/kanshi/config&lt;/code&gt; to look something like:&lt;/p&gt;
&lt;p&gt;I use the name of my monitors as the ports they are plugged into my vary.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to get Kanshi to work on NixOS and Hyprland</strong></p>
<p>I have been using Kanshi to setup my monitor setups automagically depending on which monitors are plugged
i.e. if my laptop is docked or not. If it is docked I want my laptop display to be off, when not docked I want
it to be on. So my kanshi config file <code>~/.config/kanshi/config</code> to look something like:</p>
<p>I use the name of my monitors as the ports they are plugged into my vary.</p>
<pre tabindex="0"><code>profile home_office {
  output &#34;GIGA-BYTE TECHNOLOGY CO., LTD. Gigabyte M32U 21351B000087&#34; mode 3840x2160@60Hz position 3840,0
  output &#34;Dell Inc. DELL G3223Q 82X70P3&#34; mode 3840x2160@60Hz position 0,0
  output &#34;eDP-1&#34; disable
}

profile undocked {
  output &#34;eDP-1&#34; enable scale 1.100000
}
</code></pre><p>To set this up using NixOS/home-manager we can do something like this say a file called <code>kanshi.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">services</span><span class="o">.</span><span class="n">kanshi</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">systemdTarget</span> <span class="o">=</span> <span class="s2">&#34;hyprland-session.target&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">profiles</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">undocked</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">outputs</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">criteria</span> <span class="o">=</span> <span class="s2">&#34;eDP-1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">scale</span> <span class="o">=</span> <span class="mi">1</span><span class="mf">.1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">status</span> <span class="o">=</span> <span class="s2">&#34;enable&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">home_office</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">outputs</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">criteria</span> <span class="o">=</span> <span class="s2">&#34;GIGA-BYTE TECHNOLOGY CO., LTD. Gigabyte M32U 21351B000087&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">position</span> <span class="o">=</span> <span class="s2">&#34;3840,0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">mode</span> <span class="o">=</span> <span class="s2">&#34;3840x2160@60Hz&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">criteria</span> <span class="o">=</span> <span class="s2">&#34;Dell Inc. DELL G3223Q 82X70P3&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">position</span> <span class="o">=</span> <span class="s2">&#34;0,0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">mode</span> <span class="o">=</span> <span class="s2">&#34;3840x2160@60Hz&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">criteria</span> <span class="o">=</span> <span class="s2">&#34;eDP-1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">status</span> <span class="o">=</span> <span class="s2">&#34;disable&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I was unable to get it work until I added this line <code>systemdTarget = &quot;hyprland-session.target&quot;;</code>, this is the
Systemd target to bind to. Since we are using hyprland we need to attach to hyprland the default is sway.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Part 1: NixOS as part of your Development Workflow</title>
      <link>https://haseebmajid.dev/posts/2023-07-20-nixos-as-part-of-your-development-workflow/</link>
      <pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-07-20-nixos-as-part-of-your-development-workflow/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;details
  class=&#34;notice info&#34;
  open=&#34;true&#34;
&gt;
    &lt;summary class=&#34;notice-title&#34;&gt;Dev Machine&lt;/summary&gt;
  
  &lt;p&gt;My main machine for development at the moment is a 12th Generation Intel Framework Laptop.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

&lt;/details&gt;

&lt;p&gt;This series has been inspired by &lt;a href=&#34;https://www.joshmedeski.com/guides/dev-workflow-intro/&#34;&gt;Dev Workflow Intro by Josh Medeski&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this series of posts, I will go over how I have set up my developer workflow
and explain why I have made certain decisions and why I use certain tools. This series aim to make it less daunting for you to start your journey
on improving your developer workflow. Or share with you tools that you made not
have heard of. Most of the tools I used I discovered in videos/blogs talking about
developer workflows.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">Dev Machine</summary>
  
  <p>My main machine for development at the moment is a 12th Generation Intel Framework Laptop.</p>
<p></p>

</details>

<p>This series has been inspired by <a href="https://www.joshmedeski.com/guides/dev-workflow-intro/">Dev Workflow Intro by Josh Medeski</a>.</p>
<p>In this series of posts, I will go over how I have set up my developer workflow
and explain why I have made certain decisions and why I use certain tools. This series aim to make it less daunting for you to start your journey
on improving your developer workflow. Or share with you tools that you made not
have heard of. Most of the tools I used I discovered in videos/blogs talking about
developer workflows.</p>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">My Opinion</summary>
  
  This section is entirely my opinion you are free to use whichever operating system you wish.
Most of my developer workflow can be replicated on any operating system.
</details>

<h2 id="operating-system-os">Operating System (OS)</h2>
<p>In this post, we will go over what I think is the first part of your development workflow which is your operating system.
I use NixOS, so we will go over why I use NixOS but first, let me explain why I don&rsquo;t use Windows or MacOS.</p>
<h3 id="tldr">tl:dr;</h3>
<p>If you like tinkering Linux is the OS for you.</p>
<ul>
<li>Linux is open-source</li>
<li>Linux is super customise</li>
<li>Linux is performant</li>
<li>No telemetry on Linux
<ul>
<li>Improved telemetry</li>
</ul>
</li>
</ul>
<h3 id="why-not-windows">Why not Windows?</h3>
<p>I have used both Windows and MacOS for development. Windows, talking specifically about 11, especially with WSL
works pretty well, you can use the same commands you do on Linux. However, I find the operating system to be
&ldquo;bloated&rdquo;. One example is searching for files seems to take a lot longer, I think there are ways to speed this up
but the last time I used Windows search it just never worked as well as I want it to.</p>
<p>Another example I find opening
applications to just be a lot snappier on Linux as compared with Windows. It is likely not enough to matter to most but
it annoys me enough and just adds to why I find Linux nicer to use. The final straw is all the telemetry Windows
collects about you, again which you can turn off using the registry. I like the idea of using open-source tools where
I can, seeing as I rely on so much open-source for my day-to-day.</p>
<h3 id="why-not-macos">Why not MacOS?</h3>
<p>I&rsquo;ve had to use MacOS for work a few times and each time I get annoyed mainly at the lack of customisability.
I find it very hard to get it to work exactly how I want. I also wasn&rsquo;t able to use Yabai as a tiling window manager,
which didn&rsquo;t help. You can run Linux on any hardware, whereas officially MacOS will only run on select devices.</p>
<p>I don&rsquo;t do any IOS development so I don&rsquo;t need a MacOS device to do that.
As a slight aside I think MacBooks are also very expensive, I have never bought one for myself. But some people love
their Macs and plenty of developers use them, swear by them.</p>
<h3 id="why-linux">Why Linux?</h3>
<p>I like Linux because it is open-source, free to use and secure. It comes in various flavours/distributions so the
desktop experience can vary a lot. However, most flavours will allow you to run most desktop environments, like gnome
can be used with Ubuntu, POP_!OS, Arch or even NixOS.</p>
<p>Most Linux distributions also don&rsquo;t collect any telemetry about the user and there is far more private than other
OS&rsquo;s. The main reason I Linux is choice and freedom, you can use tinker the OS to your liking. There are lots
of desktop environments and window managers which can be tweaked to your liking.</p>
<p>In my case, I am currently using Hyprland with some of my custom config, as my tiling window manager.
Most of which I have configured, such as which tool to use for notifications. We will cover more of this in another
post.</p>
<h3 id="why-nixos">Why NixOS?</h3>
<p>Ok so now we have discussed why I use Linux as my OS there are many distributions. Just in the last 5 years or so I have
used Ubuntu, Fedora, POP!_OS, Arch and finally NixOS. So why am I currently using NixOS, well the answer is simple?
The main feature of NixOS is that you can declare almost the entire state of your machine declaratively in code.
declaratively means we define the end state in code, i.e. what packages we want to be installed then NixOS works out how to
get to that state.</p>
<p>So your desktop environment is reproducible. I could easily share config between multiple devices.</p>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">Why I moved to NixOS</summary>
  
  You can read about <a href="/posts/2023-06-25-why-i-moved-to-nixos/">my article</a>, for more reasons to move to NixOs.
</details>

<h2 id="how-to-set-up-nixos">How to set up NixOS?</h2>
<p>In this section, we will take a look at how we can install NixOS, or rather how I set up NixOS on my devices.
First, we need to burn a USB with our the <a href="https://nixos.org/download.html">NixOS ISO</a>.</p>
<p>Then open a terminal and run the following commands, I want to set up an encrypted disk using btrfs. Mainly so that
we can do <a href="https://mt-caret.github.io/blog/posts/2020-06-29-optin-state.html">opt-in persistance</a>, such that our OS
is erased and rebuilt on startup, to avoid configuration drift between our declarative code and system state.</p>
<p>This script is taken from <a href="https://gist.github.com/hadilq/a491ca53076f38201a8aa48a0c6afef5">here</a>. We
won&rsquo;t use the GUI installer (though we could also do that). I want specific btrfs subvolumes, which we can think of
as logical partitions.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">DISK</span><span class="o">=</span>/dev/nvme0n1
</span></span><span class="line"><span class="cl"><span class="c1"># Format the EFI partition</span>
</span></span><span class="line"><span class="cl">mkfs.vfat -n boot <span class="s2">&#34;</span><span class="nv">$DISK</span><span class="s2">&#34;</span>p1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cryptsetup --verify-passphrase -v luksFormat <span class="s2">&#34;</span><span class="nv">$DISK</span><span class="s2">&#34;</span>p2
</span></span><span class="line"><span class="cl">cryptsetup open <span class="s2">&#34;</span><span class="nv">$DISK</span><span class="s2">&#34;</span>p2 enc
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Creat the swap inside the encrypted partition</span>
</span></span><span class="line"><span class="cl">pvcreate /dev/mapper/enc
</span></span><span class="line"><span class="cl">vgcreate lvm /dev/mapper/enc
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">lvcreate --size 32G --name swap lvm
</span></span><span class="line"><span class="cl"> lvcreate --extents 100%FREE --name root lvm
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkswap -L swap /dev/lvm/swap
</span></span><span class="line"><span class="cl">mkfs.btrfs -L nixos /dev/lvm/root
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">swapon /dev/lvm/swap
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Then create subvolumes</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mount -t btrfs /dev/lvm/root /mnt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># We first create the subvolumes outlined above:</span>
</span></span><span class="line"><span class="cl">btrfs subvolume create /mnt/root
</span></span><span class="line"><span class="cl">btrfs subvolume create /mnt/home
</span></span><span class="line"><span class="cl">btrfs subvolume create /mnt/nix
</span></span><span class="line"><span class="cl">btrfs subvolume create /mnt/persist
</span></span><span class="line"><span class="cl">btrfs subvolume create /mnt/log
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># We then take an empty *readonly* snapshot of the root subvolume,</span>
</span></span><span class="line"><span class="cl"><span class="c1"># which we&#39;ll eventually rollback to on every boot.</span>
</span></span><span class="line"><span class="cl">btrfs subvolume snapshot -r /mnt/root /mnt/root-blank
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">umount /mnt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Mount the directories</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mount -o <span class="nv">subvol</span><span class="o">=</span>root,compress<span class="o">=</span>zstd,noatime /dev/lvm/root /mnt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir /mnt/home
</span></span><span class="line"><span class="cl">mount -o <span class="nv">subvol</span><span class="o">=</span>home,compress<span class="o">=</span>zstd,noatime /dev/lvm/root /mnt/home
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir /mnt/nix
</span></span><span class="line"><span class="cl">mount -o <span class="nv">subvol</span><span class="o">=</span>nix,compress<span class="o">=</span>zstd,noatime /dev/lvm/root /mnt/nix
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir /mnt/persist
</span></span><span class="line"><span class="cl">mount -o <span class="nv">subvol</span><span class="o">=</span>persist,compress<span class="o">=</span>zstd,noatime /dev/lvm/root /mnt/persist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir -p /mnt/var/log
</span></span><span class="line"><span class="cl">mount -o <span class="nv">subvol</span><span class="o">=</span>log,compress<span class="o">=</span>zstd,noatime /dev/lvm/root /mnt/var/log
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># don&#39;t forget this!</span>
</span></span><span class="line"><span class="cl">mkdir /mnt/boot
</span></span><span class="line"><span class="cl">mount <span class="s2">&#34;</span><span class="nv">$DISK</span><span class="s2">&#34;</span>p1 /mnt/boot
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">nixos-generate-config --root /mnt
</span></span></code></pre></div><p>Then in our <code>/mnt/etc/nixos/configuration.nix</code> we edit it to look something like this. Just to give us a simple gnome
desktop environment with a few basic packages installed (in a future post we will install more).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="c1"># Edit this configuration file to define what should be installed on</span>
</span></span><span class="line"><span class="cl"><span class="c1"># your system.  Help is available in the configuration.nix(5) man page</span>
</span></span><span class="line"><span class="cl"><span class="c1"># and in the NixOS manual (accessible by running ‘nixos-help’).</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><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></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span> <span class="c1"># Include the results of the hardware scan.</span>
</span></span><span class="line"><span class="cl">      <span class="sr">./hardware-configuration.nix</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">kernelPackages</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">linuxPackages_latest</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">supportedFilesystems</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;btrfs&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="n">hardware</span><span class="o">.</span><span class="n">enableAllFirmware</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">nixpkgs</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">allowUnfree</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># Use the systemd-boot EFI boot loader.</span>
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">loader</span><span class="o">.</span><span class="n">systemd-boot</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="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">loader</span><span class="o">.</span><span class="n">efi</span><span class="o">.</span><span class="n">canTouchEfiVariables</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">initrd</span><span class="o">.</span><span class="n">luks</span><span class="o">.</span><span class="n">devices</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">root</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Use https://nixos.wiki/wiki/Full_Disk_Encryption</span>
</span></span><span class="line"><span class="cl">        <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-uuid/TO find this hash use lsblk -f. It&#39;s the UUID of nvme0n1p2&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">preLVM</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><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;framework&#34;</span><span class="p">;</span> <span class="c1"># Define your hostname.</span>
</span></span><span class="line"><span class="cl">  <span class="n">networking</span><span class="o">.</span><span class="n">networkmanager</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="cl">  <span class="c1"># networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># Set your time zone.</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># time.timeZone = &#34;Europe/Amsterdam&#34;;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># The global useDHCP flag is deprecated, therefore explicitly set to false here.</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># Per-interface useDHCP will be mandatory in the future, so this generated config</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># replicates the default behaviour.</span>
</span></span><span class="line"><span class="cl">  <span class="n">networking</span><span class="o">.</span><span class="n">useDHCP</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">services</span><span class="o">.</span><span class="n">xserver</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="cl">  <span class="n">services</span><span class="o">.</span><span class="n">xserver</span><span class="o">.</span><span class="n">displayManager</span><span class="o">.</span><span class="n">gdm</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="cl">  <span class="n">services</span><span class="o">.</span><span class="n">xserver</span><span class="o">.</span><span class="n">desktopManager</span><span class="o">.</span><span class="n">gnome</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="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># Define a user account. Don&#39;t forget to set a password with ‘passwd’.</span>
</span></span><span class="line"><span class="cl">  <span class="n">users</span><span class="o">.</span><span class="n">users</span><span class="o">.</span><span class="n">haseeb</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;wheel&#34;</span> <span class="p">];</span> <span class="c1"># Enable ‘sudo’ for the user.</span>
</span></span><span class="line"><span class="cl">    <span class="n">hashedPassword</span> <span class="o">=</span> <span class="s2">&#34;Run mkpasswd -m sha-512 to generate it&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># List packages installed in system profile. To search, run:</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># $ nix search wget</span>
</span></span><span class="line"><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></span><span class="line"><span class="cl">    <span class="n">wget</span> <span class="n">vim</span> <span class="n">git</span> <span class="n">mkpasswd</span>
</span></span><span class="line"><span class="cl">    <span class="n">firefox</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span></code></pre></div><p>Run <code>sudo nixos-generate-config --root /mnt</code> to create a hardware configuration file.
Then edit our <code>/mnt/etc/nixos/hardware-configuration.nix</code>. This is where we utilise the labels that we defined above.
You can only change the file system in your hardware-configuration.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="c1"># Do not modify this file!  It was generated by ‘nixos-generate-config’</span>
</span></span><span class="line"><span class="cl"><span class="c1"># and may be overwritten by future invocations.  Please make changes</span>
</span></span><span class="line"><span class="cl"><span class="c1"># to /etc/nixos/configuration.nix instead.</span>
</span></span><span class="line"><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="n">pkgs</span><span class="o">,</span> <span class="n">modulesPath</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">imports</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="n">modulesPath</span> <span class="o">+</span> <span class="s2">&#34;/installer/scan/not-detected.nix&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">initrd</span><span class="o">.</span><span class="n">availableKernelModules</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;xhci_pci&#34;</span> <span class="s2">&#34;thunderbolt&#34;</span> <span class="s2">&#34;nvme&#34;</span> <span class="s2">&#34;uas&#34;</span> <span class="s2">&#34;usb_storage&#34;</span> <span class="s2">&#34;sd_mod&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">initrd</span><span class="o">.</span><span class="n">kernelModules</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;dm-snapshot&#34;</span> <span class="s2">&#34;amdgpu&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">kernelModules</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;kvm-intel&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="n">boot</span><span class="o">.</span><span class="n">extraModulePackages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/&#34;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/nixos&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">fsType</span> <span class="o">=</span> <span class="s2">&#34;btrfs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">options</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;subvol=root&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/home&#34;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/nixos&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">fsType</span> <span class="o">=</span> <span class="s2">&#34;btrfs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">options</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;subvol=home&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/nix&#34;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/nixos&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">fsType</span> <span class="o">=</span> <span class="s2">&#34;btrfs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">options</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;subvol=nix&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/persist&#34;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/nixos&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">fsType</span> <span class="o">=</span> <span class="s2">&#34;btrfs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">options</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;subvol=persist&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="n">neededForBoot</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/var/log&#34;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/nixos&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">fsType</span> <span class="o">=</span> <span class="s2">&#34;btrfs&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">options</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">&#34;subvol=log&#34;</span> <span class="s2">&#34;compress=zstd&#34;</span> <span class="s2">&#34;noatime&#34;</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="n">neededForBoot</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">fileSystems</span><span class="o">.</span><span class="s2">&#34;/boot&#34;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/boot&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">fsType</span> <span class="o">=</span> <span class="s2">&#34;vfat&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">swapDevices</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">device</span> <span class="o">=</span> <span class="s2">&#34;/dev/disk/by-label/swap&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># Enables DHCP on each ethernet and wireless interface. In case of scripted networking</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># (the default) this is the recommended approach. When using systemd-networkd it&#39;s</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># still possible to use this option, but it&#39;s recommended to use it in conjunction</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># with explicit per-interface declarations with `networking.interfaces.&lt;interface&gt;.useDHCP`.</span>
</span></span><span class="line"><span class="cl">  <span class="n">networking</span><span class="o">.</span><span class="n">useDHCP</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># networking.interfaces.wlp166s0.useDHCP = lib.mkDefault true;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">nixpkgs</span><span class="o">.</span><span class="n">hostPlatform</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;x86_64-linux&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">powerManagement</span><span class="o">.</span><span class="n">cpuFreqGovernor</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="s2">&#34;powersave&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">hardware</span><span class="o">.</span><span class="n">cpu</span><span class="o">.</span><span class="n">intel</span><span class="o">.</span><span class="n">updateMicrocode</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">mkDefault</span> <span class="n">config</span><span class="o">.</span><span class="n">hardware</span><span class="o">.</span><span class="n">enableRedistributableFirmware</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then to install the OS properly on our nvme ssd run <code>sudo nixos-install</code>.</p>
<h2 id="whats-next">What&rsquo;s Next?</h2>
<p>In the next post, we will go over how we can set up our window manager (Hyprland). This will also show us how we can use
NixOS to configure our system.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Update Nix Packages Using update-nix-fetchgit</title>
      <link>https://haseebmajid.dev/posts/2023-07-13-updating-nix-packages-using-update-nix-fetchgit/</link>
      <pubDate>Thu, 13 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-07-13-updating-nix-packages-using-update-nix-fetchgit/</guid>
      <description>&lt;p&gt;Recently I&amp;rsquo;ve been trying to work out how to update packages that I define declaratively in my Nix config.
I think I figured out how to do it using my Nix flake. By running &lt;code&gt;nix flake update&lt;/code&gt; and then
&lt;code&gt;sudo nixos-rebuild switch --flake ~/dotfiles#framework&lt;/code&gt; to update the packages.&lt;/p&gt;
&lt;p&gt;However, I have some plugins say for tmux which are defined like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;t-smart-manager&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tmuxPlugins&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkTmuxPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;pluginName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;t-smart-tmux-session-manager&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;unstable-2023-06-05&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;rtpFilePath&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;t-smart-tmux-session-manager.tmux&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fetchFromGitHub&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;owner&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;joshmedeski&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;repo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;t-smart-tmux-session-manager&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;rev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0a4c77c5c3858814621597a8d3997948b3cdd35d&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sha256&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1dr5w02a0y84q2iw4jp1psxvkyj4g6pr87gc22syw1jd4ibkn925&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the &lt;code&gt;fetchFromGitHub&lt;/code&gt; function, where we specify a specific git revision to get. I was looking at ways we could
update this automatically. Then I came across this tool &lt;a href=&#34;https://github.com/expipiplus1/update-nix-fetchgit&#34;&gt;update-nix-fetchgit&lt;/a&gt;.
When run it will update the &lt;code&gt;rev&lt;/code&gt;, &lt;code&gt;sha256&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt; for us.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently I&rsquo;ve been trying to work out how to update packages that I define declaratively in my Nix config.
I think I figured out how to do it using my Nix flake. By running <code>nix flake update</code> and then
<code>sudo nixos-rebuild switch --flake ~/dotfiles#framework</code> to update the packages.</p>
<p>However, I have some plugins say for tmux which are defined like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">t-smart-manager</span> <span class="err">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">mkTmuxPlugin</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">pluginName</span> <span class="o">=</span> <span class="s2">&#34;t-smart-tmux-session-manager&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;unstable-2023-06-05&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">rtpFilePath</span> <span class="o">=</span> <span class="s2">&#34;t-smart-tmux-session-manager.tmux&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">src</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fetchFromGitHub</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;joshmedeski&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">repo</span> <span class="o">=</span> <span class="s2">&#34;t-smart-tmux-session-manager&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">rev</span> <span class="o">=</span> <span class="s2">&#34;0a4c77c5c3858814621597a8d3997948b3cdd35d&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;1dr5w02a0y84q2iw4jp1psxvkyj4g6pr87gc22syw1jd4ibkn925&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span></code></pre></div><p>Note the <code>fetchFromGitHub</code> function, where we specify a specific git revision to get. I was looking at ways we could
update this automatically. Then I came across this tool <a href="https://github.com/expipiplus1/update-nix-fetchgit">update-nix-fetchgit</a>.
When run it will update the <code>rev</code>, <code>sha256</code> and <code>version</code> for us.</p>
<p>Which will update various functions we use to fetch from git. All we need to do is install it then we can
do something like <code>fd .nix --exec update-nix-fetchgit</code>. Which will run the <code>update-nix-fetchgit</code> on all nix files in
our directory. The <code>fd</code> command (a <code>find</code> replacement) will find all nix files recursively in the current directory.</p>
<p>This should save us a lot of time doing it manually.</p>
<h2 id="devenv">devenv</h2>
<p>For my specific setup, I use <a href="devenv.sh/">devenv</a>. I have added it to my <code>devenv.nix</code> file, and set it up with <code>direnv</code>.
So it automatically loads a shell for me when I go navigate to the directory where my dotfiles are.</p>
<p>I will do a more detailed post on this setup, once I&rsquo;ve played around with it more. But by <code>devenv.nix</code> file looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># ....</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/packages/</span>
</span></span><span class="line"><span class="cl">  <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">git</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nixpkgs-fmt</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">update-nix-fetchgit</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/languages/</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># languages.nix.enable = true;</span>
</span></span><span class="line"><span class="cl">  <span class="n">languages</span><span class="o">.</span><span class="n">nix</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="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/pre-commit-hooks/</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># pre-commit.hooks.shellcheck.enable = true;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">#</span>
</span></span><span class="line"><span class="cl">  <span class="n">pre-commit</span><span class="o">.</span><span class="n">hooks</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">nixpkgs-fmt</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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># https://devenv.sh/processes/</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># processes.ping.exec = &#34;ping example.com&#34;;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># See full reference at https://devenv.sh/reference/options/</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I install some packages when I run <code>devenv shell</code>, it makes the <code>update-nix-fetchgit</code> command available for me to run.
Or anyone else for that matter, in a new &ldquo;shell&rdquo;.</p>
<h2 id="future-actions">Future Actions</h2>
<ul>
<li>Run the command automatically</li>
<li>Use with neovim to update the line under cursor <a href="https://github.com/expipiplus1/update-nix-fetchgit#from-vim">see here</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Setting Up Tmux With Nix Home Manager</title>
      <link>https://haseebmajid.dev/posts/2023-07-10-setting-up-tmux-with-nix-home-manager/</link>
      <pubDate>Mon, 10 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-07-10-setting-up-tmux-with-nix-home-manager/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this post I will show you how you can setup tmux (plugins) using the nix package manager, specifically using home-manager.
I will also show you how you can avoid an issue I encountered where tmux resurrect wasn&amp;rsquo;t working properly due to
plugin ordering.&lt;/p&gt;
&lt;p&gt;Typically we use the &lt;a href=&#34;https://github.com/tmux-plugins/tpm&#34;&gt;tmux plugin manager&lt;/a&gt; to manage our tmux plugins.
However, when I moved to NixOS, I wanted to move away from having lots of different ways of managing what is on my
system. For example, on my Arch Linux machine I had:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In this post I will show you how you can setup tmux (plugins) using the nix package manager, specifically using home-manager.
I will also show you how you can avoid an issue I encountered where tmux resurrect wasn&rsquo;t working properly due to
plugin ordering.</p>
<p>Typically we use the <a href="https://github.com/tmux-plugins/tpm">tmux plugin manager</a> to manage our tmux plugins.
However, when I moved to NixOS, I wanted to move away from having lots of different ways of managing what is on my
system. For example, on my Arch Linux machine I had:</p>
<ul>
<li>Pacman/Yay</li>
<li>lazyvim</li>
<li>tpm</li>
</ul>
<p>However, it wasn&rsquo;t obvious how to do this. In my case, I decided to use <a href="https://nixos.wiki/wiki/Home_Manager">home-manager</a>
which is a tool we can use with
Nix to manage user config including dotfiles. For tmux specifically, there is a module we can leverage. So assuming
you already have home manager and Nix setup. We can create a new module, say called <code>tmux.nix</code></p>
<h2 id="tmuxnix">tmux.nix</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
</span></span><span class="line"><span class="cl"><span class="k">let</span>
</span></span><span class="line"><span class="cl">  <span class="n">tmux-super-fingers</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">mkTmuxPlugin</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">pluginName</span> <span class="o">=</span> <span class="s2">&#34;tmux-super-fingers&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;unstable-2023-01-06&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">src</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fetchFromGitHub</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;artemave&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">repo</span> <span class="o">=</span> <span class="s2">&#34;tmux_super_fingers&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">rev</span> <span class="o">=</span> <span class="s2">&#34;2c12044984124e74e21a5a87d00f844083e4bdf7&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;sha256-cPZCV8xk9QpU49/7H8iGhQYK6JwWjviL29eWabuqruc=&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="k">in</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">tmux</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">    <span class="n">shell</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="si">}</span><span class="s2">/bin/fish&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">terminal</span> <span class="o">=</span> <span class="s2">&#34;tmux-256color&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">historyLimit</span> <span class="o">=</span> <span class="mi">100000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">plugin</span> <span class="o">=</span> <span class="n">tmux-super-fingers</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">extraConfig</span> <span class="o">=</span> <span class="s2">&#34;set -g @super-fingers-key f&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">better-mouse-mode</span>
</span></span><span class="line"><span class="cl">      <span class="p">];</span>
</span></span><span class="line"><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="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>In the file above there are a few key things I&rsquo;d like to discuss <code>programs.tmux.enable = true</code>, this automatically installs
tmux for us. We also set some other config options such as the shell to use and the history limit. Nix will automatically
add these to our tmux config file for us, which helps manage the config a bit easier in my opinion.</p>
<p>Next install tmux plugins available as a
<a href="https://search.nixos.org/packages?channel=unstable&amp;show=tmuxPlugins.better-mouse-mode&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=better+mouse+mode">nix package</a> we can simply do:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="err">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">better-mouse-mode</span>
</span></span><span class="line"><span class="cl">      <span class="p">];</span>
</span></span></code></pre></div><p>If however the plugin is not available, we can still install it like we did for tmux super fingers.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">tmux-super-fingers</span> <span class="err">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">mkTmuxPlugin</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">pluginName</span> <span class="o">=</span> <span class="s2">&#34;tmux-super-fingers&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">version</span> <span class="o">=</span> <span class="s2">&#34;unstable-2023-01-06&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">src</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fetchFromGitHub</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">owner</span> <span class="o">=</span> <span class="s2">&#34;artemave&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">repo</span> <span class="o">=</span> <span class="s2">&#34;tmux_super_fingers&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">rev</span> <span class="o">=</span> <span class="s2">&#34;2c12044984124e74e21a5a87d00f844083e4bdf7&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">sha256</span> <span class="o">=</span> <span class="s2">&#34;sha256-cPZCV8xk9QpU49/7H8iGhQYK6JwWjviL29eWabuqruc=&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>We tell home-manager where to get the plugin from on Git Hub,
which plugin we&rsquo;d like to install, and a specific revision (can be a tag or a commit sha). There is also a sha256, which
can be found when you run the <code>home-manager switch</code> command and leave the <code>sha256</code> field empty. It will initially fail
with the expected sha value which you can then copy over to the file.</p>
<p><img
        loading="lazy"
        src="/posts/2023-07-10-setting-up-tmux-with-nix-home-manager/images/example-sha.png"
        type=""
        alt="Example SHA"
        
      /></p>
<p>This sha is used to check if this derivation is already built by Nix and available to the machine, so we can skip
building it again. You can read more about it <a href="https://discourse.nixos.org/t/how-is-used-the-sha256-of-fetchfromgithub-exactly/4837">here</a>.</p>
<details
  class="notice warning"
  open="true"
>
    <summary class="notice-title">Using Same SHA</summary>
  
  <p>When I was first setting it up, I didn&rsquo;t fully realise what the sha256 was used for and shared between multiple plugins.
What will happen is that the first plugin will be installed. Then Nix will see that SHA is already installed so won&rsquo;t
install the remaining plugins.</p>
<p><strong>So make sure you add your plugins one at a time, to avoid this.</strong></p>

</details>

<p>Then we add it to our list of plugins we want to be installed. We can also specify extra config related to that plugin,
using the <code>extraConfig</code> field.
which I think helps organise our config a bit more, like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugin</span> <span class="o">=</span> <span class="n">tmux-super-fingers</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">extraConfig</span> <span class="o">=</span> <span class="s2">&#34;set -g @super-fingers-key f&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="continuum--resurrect-issues">continuum &amp; resurrect issues</h3>
<p>I had some issues getting tmux resurrect and continuum to work on my new machine. It turned out it was due to the ordering
of my plugins. Any plugin that edits the right status bar, like the catppuccin theme plugin needs to go before these two.
Now my tmux sessions automatically save and reload themselves. So when I shut down my PC I can carry on from where I left.</p>
<p>Like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="c1"># must be before continuum edits right status bar</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugin</span> <span class="o">=</span> <span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">catppuccin</span><span class="p">;</span>
</span></span><span class="line"><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="cl"><span class="s1">    set -g @catppuccin_flavour &#39;frappe&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    set -g @catppuccin_window_tabs_enabled on
</span></span></span><span class="line"><span class="cl"><span class="s1">    set -g @catppuccin_date_time &#34;%H:%M&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugin</span> <span class="o">=</span> <span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">resurrect</span><span class="p">;</span>
</span></span><span class="line"><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="cl"><span class="s1">    set -g @resurrect-strategy-vim &#39;session&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    set -g @resurrect-strategy-nvim &#39;session&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    set -g @resurrect-capture-pane-contents &#39;on&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugin</span> <span class="o">=</span> <span class="n">tmuxPlugins</span><span class="o">.</span><span class="n">continuum</span><span class="p">;</span>
</span></span><span class="line"><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="cl"><span class="s1">    set -g @continuum-restore &#39;on&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    set -g @continuum-boot &#39;on&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    set -g @continuum-save-interval &#39;10&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I haven&rsquo;t worked out how to restore my nvim session, however. The resurrect plugin needs a session.vim file to do that.
For now, this is good enough, as I have a session manager with nvim itself so it is simply a button press to restore it.</p>
<p>If you are using home-manager make sure to import this module into your main home manager nix file such as <code>home.nix</code>.
Then you should be able to run <code>home-manager switch</code> to install the tmux, and its plugins and build the config at
<code>~/.config/tmux/tmux.conf</code>.</p>
<p><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/ccb08009df7e0d884db790bca57317748661e35b/home-manager/programs/tmux.nix">My tmux file</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Why I moved to NixOS</title>
      <link>https://haseebmajid.dev/posts/2023-06-25-why-i-moved-to-nixos/</link>
      <pubDate>Sun, 25 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-06-25-why-i-moved-to-nixos/</guid>
      <description>&lt;p&gt;Recently I decided to move from Arch Linux to NixOS. Rather than doing what I should&amp;rsquo;ve done which was
try to use NixOS in a VM first and learn Nix properly. I decided to jump into the deep end and completely delete my
current Arch Linux build with Nix. This included replacing my dotfiles setup using DotBot moving them to Nix flakes and
home-manager (more on this in a bit). In this post, I&amp;rsquo;ll go over why I moved over to NixOS, and why I am staying put for now.
What I like about it and some difficulties I have had.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently I decided to move from Arch Linux to NixOS. Rather than doing what I should&rsquo;ve done which was
try to use NixOS in a VM first and learn Nix properly. I decided to jump into the deep end and completely delete my
current Arch Linux build with Nix. This included replacing my dotfiles setup using DotBot moving them to Nix flakes and
home-manager (more on this in a bit). In this post, I&rsquo;ll go over why I moved over to NixOS, and why I am staying put for now.
What I like about it and some difficulties I have had.</p>
<p>Also, NixOS is the new Arch meme.</p>
<p></p>
<details
  class="notice warning"
  open="true"
>
    <summary class="notice-title">New to NixOS</summary>
  
  I&rsquo;m pretty new to NixOS so there is a chance something I have said isn&rsquo;t quite correct.
Please let me know via Gitlab Issue (click on the edit button).
</details>

<h2 id="background">Background</h2>
<p>I first heard about NixOS last year at EuroPython 2022, when I went to a round table discussion around tooling. This was
mostly focused on CLI tools that people used. But someone mentioned they used NixOS and you could have your entire machines config
in a single repository. I was intrigued. I personally love reproducibility, and I have enjoyed using Docker for that very reason.
Though I have since learnt Docker is repeatable but Nix with Flakes is far more reproducible. Anyways tangent aside, I want and explored
but I just couldn&rsquo;t be bothered to swap. So I stuck with Arch Linux the main reason being it seemed like Arch with its AUR (arch user repository)
had far more packages.</p>
<p>Then recently I have been looking to improve my developer workflow, I have moved mostly to neovim with tmux (see previous posts in the series).
I was using pop shell as a &ldquo;pseudo&rdquo; tiling manager, and it was fine, to begin with. Then I started to explore more and came across Hyprland,
a Wayland compositor. Which looked quite powerful, and more flexible than what I had. For example, I had it set up so that workspaces could only
change my primary display. AFAIK on Gnome you couldn&rsquo;t have workspaces per monitor, changing workspace would change it on both monitors.</p>
<p>However, with Hyprland (and many other such window managers etc) you can set a workspace per monitor. I had tried to use qtile before but soon
found myself not wanting to configure everything. But I am much more experienced with Linux and said why not.
So essentially my initial reasons for moving were I wanted to have my machine configured via a single git repo and have it reproducible and also
try a new window manager, so I thought let us do both at once :laugh:</p>
<p>Around this time to make it even more interesting I decided to try and see if I could live just working on my Framework laptop which I barely used since
I bought it. In theory, moving back to my desktop should be a lot easier if I use NixOS.</p>
<h2 id="nix-vs-nixos">Nix vs NixOS</h2>
<p>The language can be a bit confusing so let&rsquo;s define what we mean: <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<ul>
<li>nix: The package manager, think like apt or Pacman</li>
<li>nixlang: The nix programming language, a functional language</li>
<li>nixos: An operating system built around nix package manager</li>
<li>machine/system/laptop/desktop: I use these words interchangeably, for NixOS I&rsquo;ve only set it up on my Laptop</li>
</ul>
<p>You can run Nix in any Linux distribution (and even macOS), so what I probably should have done is started using the Nix package manager first.
Then tried NixOS in a virtual machine (on my Arch machine). Then after I was comfortable with nix and nixlang, assuming I liked it, move properly
NixOS on my system.</p>
<h2 id="moving-to-nixos">Moving to NixOS</h2>
<p></p>
<p>So I moved to NixOS using their graphical installer, which was very easy to use and set up. Even setting up hibernate with ease, which I remember being
a pain on Arch Linux (mainly due to my lack of understanding but none the less nixos made it pretty easy).</p>
<p>Now Arch Linux is a rolling release distribution which means rather than getting &ldquo;big&rdquo; updates every 6 months with say POP!_OS (my previous distro).
You receive updates far more frequently, so you have a more up-to-date system. The down-side things can break, my most recent issue being
Plymouth breaking and me not being able to type in my password to decrypt my LUKs disk, so not being able to boot.
I then need to use a live USB to remove the Plymouth config from my grub setup.</p>
<p>So one of the features that convinced me to move to nixos was the ability to roll back to previous generations.
So if I install or update a package and it breaks my system I can roll back to the previous generation.
So the way my Arch system broke would not happen in NixOS alongside this and the ability to define the state of my system
in &ldquo;code&rdquo; was enough to convince me.</p>
<p></p>
<p>Another feature I liked was able to define my system state in code (nixlang). The idea being I could setup
on a new machine a lot quicker than I could with another Distro.</p>
<p>My dotfiles setup at the time used dotbot which did help me get set up faster but still involved lots of manual steps.
I thought about using Ansible to help configure my setup, but in the end, never got around to doing it.
So having the ability to define my system state in nixlang was a nice feature to have.</p>
<p>The final feature that I liked was the ability of atomic updates. So nix never overwrites packages it simply adds them to a new path
(in the /nix/store directory). It means we can maintain multiple versions of the same library (think like in Golang). It also means
there is no team where we have some of the old files and new ones. So if your upgrade fails in the middle, we can simply revert to the older version. <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<h3 id="summary">Summary</h3>
<ul>
<li>Define system state in Nixlang</li>
<li>Roll back to previous generations</li>
<li>Atomic updates</li>
</ul>
<h2 id="learnings">Learnings</h2>
<p>In this section, I will go over a few of my learnings, since picking up NixOS a month ago. It is not a beginner-friendly distribution.
If you are new to Linux I recommend trying a distribution like POP!_OS first then after you are more comfortable with Linux you can try
nix as a package manager and after that move to NixOS. I will go over more why later in this post.</p>
<p>There was a bunch of confusion about how to set up my repository to configure my system. What I ended up with was the following <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
<ul>
<li>Use Nix Flakes <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></li>
<li>Improves reproducibility</li>
<li>Use home-manager to configure dotfiles</li>
<li>Use NixOS configuration for the rest of the system
<ul>
<li>Such as bootloader</li>
<li>Luks encryption</li>
</ul>
</li>
<li>Allow multiple different host machines (laptop, desktop, etc)
<ul>
<li>Share common config</li>
</ul>
</li>
<li>Separate home-manager config
<ul>
<li>So can use machines that won&rsquo;t run NixOS (like work laptop)</li>
</ul>
</li>
</ul>
<h3 id="imperative-vs-declarative">Imperative vs Declarative</h3>
<p>I wanted my config to be declarative, which means I tell NixOS I want x,y,z i.e. Grub, Mullvad VPN and then NixOS works out how to get the system into the correct state.
Nix/NixOS have some imperative operations <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> like using <code>nix-env</code> is which more similar to other package managers to install packages. But I avoid using those.
Except <code>nix-shell -p &lt;pkg&gt;</code>, which creates a shell with the package installed temporarily which is great for quickly trying out the package without committing to an install.
Essentially I want to define my system state in code, so it can be reproduced on other machines.</p>
<h3 id="nix-flakes">Nix Flakes</h3>
<p>Again I&rsquo;m pretty new to Nix but I think from what I&rsquo;ve seen Nix flakes are the recommended way to use Nix.
Flakes essentially provide us with a lot more reproducibility. They are self-contained units which have inputs and outputs.
A flake needs a <code>flake.nix</code> file, which contains inputs and outputs.
The inputs can be other flakes (like home-manager), and these get locked to specific versions in a <code>flake.lock</code> file.</p>
<p>Where out flake file may look like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;My NixOS Config&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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-unstable&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">home-manager</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nix-community/home-manager&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">outputs</span> <span class="o">=</span> <span class="p">{</span> <span class="n">self</span><span class="o">,</span> <span class="n">nixpkgs</span><span class="o">,</span> <span class="n">home-manager</span><span class="o">,</span> <span class="n">nur</span><span class="o">,</span> <span class="o">...</span> <span class="p">}</span><span class="o">@</span><span class="n">inputs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>They also help with structuring nix repositories acting as a &ldquo;main&rdquo; function [4]. When I start doing programming projects
I will likely look into using flakes for even better reproducibility as compared with Docker.</p>
<h3 id="home-manager">Home Manager</h3>
<p>Home Manager makes it easier to manage the user environment using the Nix package manager (again declaratively). Anything related to the user
is managed here. Things like dotfiles, which applications to install and which config such as alacritty as my terminal.</p>
<p>In theory, my config is set up to support multiple users but at the moment there is only one user <code>haseeb</code>.
One nice feature I didn&rsquo;t consider was how it would be to swap back to Gnome from Hyprland. This makes it much easier to experiment
and try out new window managers or desktop environments. My current config has both my gnome config and hyprland config and with a few lines
I should be able to back to Gnome, if I want (and vice versa).</p>
<p>As you can probably imagine most of my config is here, as most changes happen in userland. I can run this separately to NixOS because
I will have machines where I cannot use NixOS, like my work laptop but can use the nix package manager.</p>
<p>command: <code>home-manager switch --flake ~/dotfiles#haseeb@framework</code></p>
<h3 id="nixos-configuration">NixOS Configuration</h3>
<p>This is like home manager except for system-wide changes, split up via device (currently only my framework laptop).
Things like the bootloader, and fingerprint reader. I only put config here if it needs to be system-wide.</p>
<p>This also builds the home manager config</p>
<p><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/6f2bac80e57999c793eb8ae48ca1dfc8dafa8f9e/hosts/framework/default.nix">Click here for an example</a>.
The common config can be shared</p>
<p>command: <code>sudo nixos-rebuild switch --flake ~/dotfiles#framework</code></p>
<h3 id="issues">Issues</h3>
<p>Some issues I encountered whilst moving to NixOS. Lots of docs still refer to nix-env and nix-channel as a way to install packages.
But from what I&rsquo;ve read and my personal preference it seems the preferred way is the declarative way I described above.
However, when you first get started this is not always clear</p>
<p>Docs are a bit messy in my opinion, I often find myself reading multiple different blog posts to understand what to do.
Or looking through <a href="https://sourcegraph.com">sourcegraph</a> for code examples and working it out that way.
As I said you will still see references to the imperative way to use nix.</p>
<p>I also think the error messages that home-manager and NixOS configuration can throw, can at times be a bit obtuse and hard to
understand (at least for me).</p>
<p>Overall these are just small issues, which I hope will get better over time. Nix/NixOS can be infuriating at times, when you know
on another distribution/package manager would be much quicker. However knowing that my builds are more reproducible is worth it!</p>
<p>That&rsquo;s it! Some reasons why I&rsquo;ve moved to NixOS and why I will be staying for now. In a future article, I will break down my own
NixOS configuration.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/tree/6f2bac80e57999c793eb8ae48ca1dfc8dafa8f9e">Nix Config</a></li>
<li><a href="https://thiscute.world/en/posts/nixos-and-flake-basics/#iii-nix-flakes-and-the-old-nix">NixOS Basic, a great read imo!</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://news.ycombinator.com/item?id=23251895">https://news.ycombinator.com/item?id=23251895</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://nixos.org/guides/how-nix-works.html">https://nixos.org/guides/how-nix-works.html</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Heavily inspired by this repo: <a href="https://github.com/Misterio77/nix-config">https://github.com/Misterio77/nix-config</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://www.tweag.io/blog/2020-05-25-flakes/">https://www.tweag.io/blog/2020-05-25-flakes/</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://nixos.wiki/wiki/Overview_of_the_NixOS_Linux_distribution">https://nixos.wiki/wiki/Overview_of_the_NixOS_Linux_distribution</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to use NUR with Home-Manager &amp; Nix Flakes</title>
      <link>https://haseebmajid.dev/posts/2023-06-22-til-use-nur-with-home-manager-flake/</link>
      <pubDate>Thu, 22 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-06-22-til-use-nur-with-home-manager-flake/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to use NUR with Home-Manager &amp;amp; Nix Flakes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NUR is the Nix user repository like the Arch user repository (AUR). It exists so that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The NUR was created to share new packages from the community in a faster and more decentralized way. - &lt;a href=&#34;https://github.com/nix-community/NUR&#34;&gt;https://github.com/nix-community/NUR&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If we want to install packages from NUR in our home manager config which is set up using Nix Flakes.
Assuming you build your home manager like&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to use NUR with Home-Manager &amp; Nix Flakes</strong></p>
<p>NUR is the Nix user repository like the Arch user repository (AUR). It exists so that:</p>
<blockquote>
<p>The NUR was created to share new packages from the community in a faster and more decentralized way. - <a href="https://github.com/nix-community/NUR">https://github.com/nix-community/NUR</a></p>
</blockquote>
<p>If we want to install packages from NUR in our home manager config which is set up using Nix Flakes.
Assuming you build your home manager like</p>
<p>To do so first add it as an input in our <code>flake.nix</code> file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">inputs</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><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-unstable&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">nur</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;github:nix-community/NUR&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span></code></pre></div><p>Then we can use with home-manager by importing <code>inputs.nur.hmModules.nur</code>, for example in your <code>home.nix</code> file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">imports</span> <span class="err">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">inputs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">hmModules</span><span class="o">.</span><span class="n">nur</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span></code></pre></div><p>Then we should be able to import packages like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="n">home</span><span class="o">.</span><span class="n">packages</span> <span class="err">=</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="cl">    <span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">peel</span><span class="o">.</span><span class="n">rofi-wifi-menu</span>
</span></span><span class="line"><span class="cl">    <span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">peel</span><span class="o">.</span><span class="n">rofi-emoji</span>
</span></span><span class="line"><span class="cl">  <span class="p">];</span>
</span></span></code></pre></div><blockquote>
<p>Note these packages won&rsquo;t work because they are out of date, and they caused me a lot of grief 😅, thinking it wasn&rsquo;t working.</p>
</blockquote>
<p>But that&rsquo;s it! You should be able to use NUR packages with home-manager setup via a flake.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Declaratively Setup Mullvad VPN with NixOS</title>
      <link>https://haseebmajid.dev/posts/2023-06-20-til-how-to-declaratively-setup-mullvad-with-nixos/</link>
      <pubDate>Tue, 20 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-06-20-til-how-to-declaratively-setup-mullvad-with-nixos/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Declaratively Setup Mullvad VPN with NixOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have recently moved to NixOS, one of the great features of NixOS is that you can set up your entire machine
from a single git repo. We can do this declaratively, what we mean by this is we tell nix what we want the state to
be and nixos will work out how to get there.&lt;/p&gt;
&lt;p&gt;For example, we can install Mullvad set various options already. This means on a new machine we don&amp;rsquo;t manually have to
setup these mullvad settings.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Declaratively Setup Mullvad VPN with NixOS</strong></p>
<p>I have recently moved to NixOS, one of the great features of NixOS is that you can set up your entire machine
from a single git repo. We can do this declaratively, what we mean by this is we tell nix what we want the state to
be and nixos will work out how to get there.</p>
<p>For example, we can install Mullvad set various options already. This means on a new machine we don&rsquo;t manually have to
setup these mullvad settings.</p>
<p>We can set it up by doing something like <code>mullvad.nix</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="o">...</span><span class="p">}:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">environment</span><span class="o">.</span><span class="n">systemPackages</span> <span class="o">=</span> <span class="p">[</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">mullvad-vpn</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">mullvad</span> <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="n">services</span><span class="o">.</span><span class="n">mullvad-vpn</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><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="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">systemd</span><span class="o">.</span><span class="n">services</span><span class="o">.</span><span class="s2">&#34;mullvad-daemon&#34;</span><span class="o">.</span><span class="n">postStart</span> <span class="o">=</span> <span class="k">let</span>
</span></span><span class="line"><span class="cl">    <span class="n">mullvad</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">services</span><span class="o">.</span><span class="n">mullvad-vpn</span><span class="o">.</span><span class="n">package</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">in</span> <span class="s1">&#39;&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">    while ! </span><span class="si">${</span><span class="n">mullvad</span><span class="si">}</span><span class="s1">/bin/mullvad status &gt;/dev/null; do sleep 1; done
</span></span></span><span class="line"><span class="cl"><span class="s1">    </span><span class="si">${</span><span class="n">mullvad</span><span class="si">}</span><span class="s1">/bin/mullvad auto-connect set on
</span></span></span><span class="line"><span class="cl"><span class="s1">    </span><span class="si">${</span><span class="n">mullvad</span><span class="si">}</span><span class="s1">/bin/mullvad tunnel ipv6 set on
</span></span></span><span class="line"><span class="cl"><span class="s1">    </span><span class="si">${</span><span class="n">mullvad</span><span class="si">}</span><span class="s1">/bin/mullvad set default \
</span></span></span><span class="line"><span class="cl"><span class="s1">        --block-ads --block-trackers --block-malware
</span></span></span><span class="line"><span class="cl"><span class="s1">  &#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The main part here is we set up mullvad and then in the service we set various options. That can be set via the
GUI app.</p>
<pre tabindex="0"><code>${mullvad}/bin/mullvad set default \
        --block-ads --block-trackers --block-malware
</code></pre><p>One improvement we could make is to use a secret manager like <code>nix-sops</code> and even login automatically using our account id [1].</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/dotfiles/-/blob/6f2bac80e57999c793eb8ae48ca1dfc8dafa8f9e/hosts/common/optional/mullvad.nix">Dotfiles</a></li>
</ul>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
