<?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>Homelab on Carlos Vaz</title>
    <link>https://carlosvaz.com/tags/homelab/</link>
    <description>Recent content in Homelab on Carlos Vaz</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <managingEditor>carlos@carjorvaz.com (Carlos Vaz)</managingEditor>
    <webMaster>carlos@carjorvaz.com (Carlos Vaz)</webMaster>
    <lastBuildDate>Mon, 07 Aug 2023 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://carlosvaz.com/tags/homelab/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>iPXE booting with NixOS</title>
      <link>https://carlosvaz.com/posts/ipxe-booting-with-nixos/</link>
      <pubDate>Mon, 07 Aug 2023 00:00:00 +0000</pubDate><author>carlos@carjorvaz.com (Carlos Vaz)</author>
      <guid>https://carlosvaz.com/posts/ipxe-booting-with-nixos/</guid>
      <description>&lt;p&gt;When you only manage a few systems, it is usually enough to install NixOS on them using a live installer on a USB drive.&#xA;When dealing with almost a hundred systems, however, using USB drives becomes unfeasable and solutions like PXE booting become necessary.&lt;/p&gt;&#xA;&lt;p&gt;Thankfully, Pixiecore makes it easy to set up an iPXE server on NixOS, a task that could otherwise be quite complex.&lt;/p&gt;&#xA;&lt;p&gt;The simplest iPXE server we can set up on NixOS can look like the following:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When you only manage a few systems, it is usually enough to install NixOS on them using a live installer on a USB drive.
When dealing with almost a hundred systems, however, using USB drives becomes unfeasable and solutions like PXE booting become necessary.</p>
<p>Thankfully, Pixiecore makes it easy to set up an iPXE server on NixOS, a task that could otherwise be quite complex.</p>
<p>The simplest iPXE server we can set up on NixOS can look like the following:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{ config<span style="color:#f92672">,</span> lib<span style="color:#f92672">,</span> pkgs<span style="color:#f92672">,</span> <span style="color:#f92672">...</span> }:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  services<span style="color:#f92672">.</span>pixiecore <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    openFirewall <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    dhcpNoBind <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    kernel <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://boot.netboot.xyz&#34;</span>;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div><p>In this configuration, we enable the Pixiecore service, set it to work along the DHCP server that already exists on our network and to boot the <a href="https://netboot.xyz">netboot.xyz</a> iPXE image, a common option which gives you a selection of live installers on boot.</p>
<p>This may be enough for your environment but, as we&rsquo;re running NixOS, we&rsquo;d like to an image customized to our needs, having SSH access pre-configured, for example:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{ config<span style="color:#f92672">,</span> inputs<span style="color:#f92672">,</span> lib<span style="color:#f92672">,</span> pkgs<span style="color:#f92672">,</span> <span style="color:#f92672">...</span> }:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span>
</span></span><span style="display:flex;"><span>  sys <span style="color:#f92672">=</span> inputs<span style="color:#f92672">.</span>nixos<span style="color:#f92672">.</span>lib<span style="color:#f92672">.</span>nixosSystem {
</span></span><span style="display:flex;"><span>    system <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;x86_64-linux&#34;</span>;
</span></span><span style="display:flex;"><span>    modules <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span>      ({ config<span style="color:#f92672">,</span> pkgs<span style="color:#f92672">,</span> lib<span style="color:#f92672">,</span> modulesPath<span style="color:#f92672">,</span> <span style="color:#f92672">...</span> }: {
</span></span><span style="display:flex;"><span>        imports <span style="color:#f92672">=</span> [ (modulesPath <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/installer/netboot/netboot-minimal.nix&#34;</span>) ];
</span></span><span style="display:flex;"><span>        config <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>          services<span style="color:#f92672">.</span>openssh <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>            enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>            openFirewall <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            settings <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>              PasswordAuthentication <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>              KbdInteractiveAuthentication <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>            };
</span></span><span style="display:flex;"><span>          };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          users<span style="color:#f92672">.</span>users<span style="color:#f92672">.</span>root<span style="color:#f92672">.</span>openssh<span style="color:#f92672">.</span>authorizedKeys<span style="color:#f92672">.</span>keys <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>      })
</span></span><span style="display:flex;"><span>    ];
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  build <span style="color:#f92672">=</span> sys<span style="color:#f92672">.</span>config<span style="color:#f92672">.</span>system<span style="color:#f92672">.</span>build;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">in</span> {
</span></span><span style="display:flex;"><span>  services<span style="color:#f92672">.</span>pixiecore <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    openFirewall <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    dhcpNoBind <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>; <span style="color:#75715e"># Use existing DHCP server.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    mode <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;boot&#34;</span>;
</span></span><span style="display:flex;"><span>    kernel <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>build<span style="color:#f92672">.</span>kernel<span style="color:#e6db74">}</span><span style="color:#e6db74">/bzImage&#34;</span>;
</span></span><span style="display:flex;"><span>    initrd <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>build<span style="color:#f92672">.</span>netbootRamdisk<span style="color:#e6db74">}</span><span style="color:#e6db74">/initrd&#34;</span>;
</span></span><span style="display:flex;"><span>    cmdLine <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;init=</span><span style="color:#e6db74">${</span>build<span style="color:#f92672">.</span>toplevel<span style="color:#e6db74">}</span><span style="color:#e6db74">/init loglevel=4&#34;</span>;
</span></span><span style="display:flex;"><span>    debug <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div><p>The previous example does exactly that.</p>
<p>This now becomes very powerful and we&rsquo;ve just starting using this on the lab computers we manage.
We set the boot order to boot first from the hard disk and, if it&rsquo;s not bootable, it will automatically boot from iPXE, still allowing remote access from the administrators and allowing us, if necessary, to redeploy its configuration with <a href="https://github.com/numtide/nixos-anywhere">nixos-anywhere</a>, as I&rsquo;ll explain in a future blog post.</p>
<p>But we also want to be able to trigger an iPXE boot remotely, even if the current hard disk has a bootable configuration.</p>
<p>Initially, it wasn&rsquo;t very obvious how we should be able to do this.
One possibility would be to use <code>efibootmgr</code> to change the boot order accordingly, but it would make it more difficult to return to booting from local hard disk after the redeploy.</p>
<p>After some reflection, we settled on creating a special GRUB entry that boots from iPXE.</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{ config<span style="color:#f92672">,</span> lib<span style="color:#f92672">,</span> pkgs<span style="color:#f92672">,</span> <span style="color:#f92672">...</span> }:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  boot<span style="color:#f92672">.</span>loader <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    efi<span style="color:#f92672">.</span>canTouchEfiVariables <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    grub <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>      enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>      efiSupport <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>      device <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;nodev&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      extraFiles <span style="color:#f92672">=</span> { <span style="color:#e6db74">&#34;ipxe.efi&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>pkgs<span style="color:#f92672">.</span>ipxe<span style="color:#e6db74">}</span><span style="color:#e6db74">/ipxe.efi&#34;</span>; };
</span></span><span style="display:flex;"><span>      extraEntries <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        menuentry &#34;Reinstall via iPXE&#34; {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          chainloader /ipxe.efi
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div><p>Presumably, this only works on UEFI systems.</p>
<p>Finding out how to create this entry wasn&rsquo;t trivial at all, I couldn&rsquo;t find anyone else doing it this way,  but it seems to work perfectly fine.</p>
<p>Having this boot entry on its own isn&rsquo;t much different from choosing a different one-time boot option, so I&rsquo;ll look into using the <code>grub-reboot</code> tool to be able to trigger it remotely, although I haven&rsquo;t tested that yet on NixOS.</p>
<p><em>2023/08/24 Update</em>: I can confirm that <code>grub-reboot</code> works as expected on NixOS.</p>
<p>For example, you can get the available entries on your system like so:</p>





<pre tabindex="0"><code class="language-nil" data-lang="nil">[root@nixos:~]# grep menuentry /boot/grub/grub.cfg
menuentry &#34;NixOS - Default&#34; --class nixos {
menuentry &#34;Windows 10&#34; {
menuentry &#34;iPXE Boot&#34; {
menuentry &#34;NixOS - Configuration 19 (2023-08-24 - 23.05.20230820.475d5ae)&#34; --class nixos {</code></pre><p>From this output, we&rsquo;d run <code>grub-reboot 2</code> to boot to iPXE on next reboot.</p>
<p>There&rsquo;s also a more complicated approach, where the iPXE boot entry won&rsquo;t be visible by default, only when you trigger it remotely.</p>
<p>To do this, we use the following snippet instead:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{ config<span style="color:#f92672">,</span> lib<span style="color:#f92672">,</span> pkgs<span style="color:#f92672">,</span> <span style="color:#f92672">...</span> }:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  environment<span style="color:#f92672">.</span>shellAliases<span style="color:#f92672">.</span>reboot2PXE <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>pkgs<span style="color:#f92672">.</span>grub2<span style="color:#e6db74">}</span><span style="color:#e6db74">/bin/grub-editenv /boot/grub/grubenv set entry=ipxe &amp;&amp; reboot&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  boot<span style="color:#f92672">.</span>loader <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    efi<span style="color:#f92672">.</span>canTouchEfiVariables <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    grub <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>      enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>      efiSupport <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>      device <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;nodev&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      extraFiles <span style="color:#f92672">=</span> { <span style="color:#e6db74">&#34;ipxe.efi&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>pkgs<span style="color:#f92672">.</span>ipxe<span style="color:#e6db74">}</span><span style="color:#e6db74">/ipxe.efi&#34;</span>; };
</span></span><span style="display:flex;"><span>      extraConfig <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        if [ &#34;</span><span style="color:#ae81ff">&#39;&#39;$</span><span style="color:#e6db74">{entry}&#34; = &#34;ipxe&#34; ]; then
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          set entry=&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          save_env --file /grub/grubenv entry
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          menuentry &#34;Reinstall via iPXE&#34; {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">            chainloader /ipxe.efi
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        fi
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div><p>Now, if we call <code>reboot2PXE</code>, the system will immediately reboot to iPXE, while not showing the iPXE boot entry on regular boots.</p>
<h2 id="closing-remarks">Closing remarks</h2>
<p>As you can see by these snippets, setting up an iPXE server doesn&rsquo;t have to be a chore.</p>
<p>As basically every computer built in the last 10 years has proper iPXE booting support, when managing tens of bare metal machines, setups like these drastically make the sysadmins&rsquo; lives easier.</p>
<p>Although I believe it would still be technically possible to remotely configure and recover these systems using lower level tools like AMT, I feel this would create a more complicated setup.
I&rsquo;m still looking to experiment with <a href="https://meshcentral.com">MeshCentral</a> to explore these lower level AMT capibilities, and that may become a future blog post.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://github.com/danderson/netboot/tree/main/pixiecore">https://github.com/danderson/netboot/tree/main/pixiecore</a></li>
<li><a href="https://nixos.wiki/wiki/Netboot">https://nixos.wiki/wiki/Netboot</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Installing NixOS on the Raspberry Pi 4 with UEFI and ZFS</title>
      <link>https://carlosvaz.com/posts/nixos-on-raspberry-pi-4-with-uefi-and-zfs/</link>
      <pubDate>Tue, 10 May 2022 00:00:00 +0000</pubDate><author>carlos@carjorvaz.com (Carlos Vaz)</author>
      <guid>https://carlosvaz.com/posts/nixos-on-raspberry-pi-4-with-uefi-and-zfs/</guid>
      <description>&lt;p&gt;After spending some time with &lt;a href=&#34;https://osmc.tv/&#34;&gt;OSMC&lt;/a&gt; on my Raspberry Pi 4, I&amp;rsquo;ve been meaning to install NixOS on it as it has been my distribution of choice on all my other systems.&lt;/p&gt;&#xA;&lt;p&gt;Installing &amp;ldquo;vanilla&amp;rdquo; NixOS on the Pi isn&amp;rsquo;t too difficult, just follow the &lt;a href=&#34;https://nixos.wiki/wiki/NixOS_on_ARM#SD_card_images_.28SBCs_and_similar_platforms.29&#34;&gt;installation steps on the wiki&lt;/a&gt;: download the SD card image, decompress it, flash the image to the SD card and you&amp;rsquo;re good to go.&lt;/p&gt;&#xA;&lt;p&gt;However, it gets more complicated when you try to go off the beaten path, such as when trying to do full-disk encryption or using filesystems other than ext4.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>After spending some time with <a href="https://osmc.tv/">OSMC</a> on my Raspberry Pi 4, I&rsquo;ve been meaning to install NixOS on it as it has been my distribution of choice on all my other systems.</p>
<p>Installing &ldquo;vanilla&rdquo; NixOS on the Pi isn&rsquo;t too difficult, just follow the <a href="https://nixos.wiki/wiki/NixOS_on_ARM#SD_card_images_.28SBCs_and_similar_platforms.29">installation steps on the wiki</a>: download the SD card image, decompress it, flash the image to the SD card and you&rsquo;re good to go.</p>
<p>However, it gets more complicated when you try to go off the beaten path, such as when trying to do full-disk encryption or using filesystems other than ext4.</p>
<p>After some reading and some trial and error, here are the steps I took to get NixOS with ZFS on the Pi, with UEFI booting.</p>
<h2 id="requirements">Requirements</h2>
<p>Make sure you&rsquo;ve enabled support for USB booting on your Raspberry Pi. If yours is considerably older, you might need to update its EEPROM before you can enable support for USB booting. For more details, check the <a href="https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#usb-mass-storage-boot">documentation</a>.</p>
<h2 id="installation-steps">Installation steps</h2>
<p>I started by booting the Pi off of a USB stick with the <a href="https://hydra.nixos.org/job/nixos/release-21.11/nixos.sd_image.aarch64-linux">generic SD card AArch64 image</a> but it would work just as well by initially booting off of an SD card.</p>
<p>As my installation target was a SATA SSD, I now connected it to one of the USB 3.0 ports on the Pi. I find using the Raspberry Pi with an SSD makes it feel more like a real computer, as the SSD is faster, has more storage capacity and will most certainly be more durable than a flimsy SD card, especially now that I&rsquo;ll also be using the Pi as a home server.</p>
<h3 id="partitioning">Partitioning</h3>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wipefs -a /dev/sda
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>parted -a optimal /dev/sda -- mklabel gpt
</span></span><span style="display:flex;"><span>parted -a optimal /dev/sda -- mkpart ESP fat32 1MiB 513MiB
</span></span><span style="display:flex;"><span>parted -a optimal /dev/sda -- set <span style="color:#ae81ff">1</span> esp on
</span></span><span style="display:flex;"><span>parted -a optimal /dev/sda -- mkpart primary linux-swap 513MiB 8705MiB
</span></span><span style="display:flex;"><span>parted -a optimal /dev/sda -- mkpart primary 8705MiB 100%
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mkfs.fat -F <span style="color:#ae81ff">32</span> -n boot /dev/sda1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mkswap -L swap /dev/sda2
</span></span><span style="display:flex;"><span>swapon /dev/sda2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>zpool create -O mountpoint<span style="color:#f92672">=</span>none -O atime<span style="color:#f92672">=</span>off -o ashift<span style="color:#f92672">=</span><span style="color:#ae81ff">12</span> -O acltype<span style="color:#f92672">=</span>posixacl -O xattr<span style="color:#f92672">=</span>sa -O compression<span style="color:#f92672">=</span>zstd -O dnodesize<span style="color:#f92672">=</span>auto -O normalization<span style="color:#f92672">=</span>formD zroot /dev/sda3
</span></span><span style="display:flex;"><span>zfs create -o refreservation<span style="color:#f92672">=</span>1G -o mountpoint<span style="color:#f92672">=</span>none zroot/reserved
</span></span><span style="display:flex;"><span>zfs create zroot/root
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mount -t zfs -o zfsutil zroot/root /mnt
</span></span><span style="display:flex;"><span>mkdir -p /mnt/boot
</span></span><span style="display:flex;"><span>mount /dev/sda1 /mnt/boot</span></span></code></pre></div><h3 id="uefi-setup">UEFI setup</h3>
<p>We&rsquo;ll now setup UEFI on the Pi. We do this by placing the files from the <a href="https://github.com/pftf/RPi4">Raspberry Pi 4 UEFI Firmware Images</a> on the boot partition:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nix-shell -p wget unzip
</span></span><span style="display:flex;"><span>cd /mnt/boot
</span></span><span style="display:flex;"><span>wget https://github.com/pftf/RPi4/releases/download/v1.33/RPi4_UEFI_Firmware_v1.33.zip
</span></span><span style="display:flex;"><span>unzip RPi4_UEFI_Firmware_v1.33.zip
</span></span><span style="display:flex;"><span>rm README.md
</span></span><span style="display:flex;"><span>rm RPi4_UEFI_Firmware_v1.33.zip</span></span></code></pre></div><p><em>2022/11/04 Update:</em> As a reader pointed out, you can also do this step by just copying the files on the installation media (assuming <code>/dev/sda</code> is your installation disk):</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir /firmware
</span></span><span style="display:flex;"><span>mount /dev/sda1 /firmware
</span></span><span style="display:flex;"><span>cp /firmware/* /mnt/boot</span></span></code></pre></div><h3 id="nixos-installation">NixOS installation</h3>
<p>As per usual, we let NixOS generate a config for us:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nixos-generate-config --root /mnt</span></span></code></pre></div><p>As we&rsquo;re using ZFS, we&rsquo;ll need to enable ZFS support:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>boot<span style="color:#f92672">.</span>supportedFilesystems <span style="color:#f92672">=</span> [ <span style="color:#e6db74">&#34;zfs&#34;</span> ];
</span></span><span style="display:flex;"><span>networking<span style="color:#f92672">.</span>hostId <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&lt;8 random numbers&gt;&#34;</span>;</span></span></code></pre></div><p>And also specify the <code>zfsutil</code> mount option for each of our datasets (in the <code>/mnt/etc/nixos/hardware-configuration.nix</code> file):</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>fileSystems<span style="color:#f92672">.</span><span style="color:#e6db74">&#34;/&#34;</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  device <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;zroot/root&#34;</span>;
</span></span><span style="display:flex;"><span>  fsType <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;zfs&#34;</span>;
</span></span><span style="display:flex;"><span>  options <span style="color:#f92672">=</span> [ <span style="color:#e6db74">&#34;zfsutil&#34;</span> ];
</span></span><span style="display:flex;"><span>};</span></span></code></pre></div><p>Now, as we&rsquo;re booting with UEFI, we&rsquo;ll delete the following line which is generated by default:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>boot<span style="color:#f92672">.</span>loader<span style="color:#f92672">.</span>generic-extlinux-compatible<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;</span></span></code></pre></div><p>&hellip;and we&rsquo;ll install a UEFI bootloader:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>boot<span style="color:#f92672">.</span>loader<span style="color:#f92672">.</span>efi<span style="color:#f92672">.</span>canTouchEfiVariables <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>boot<span style="color:#f92672">.</span>loader<span style="color:#f92672">.</span>systemd-boot<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;</span></span></code></pre></div><p>Finally, we&rsquo;ll install NixOS:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>nixos-install</span></span></code></pre></div><h3 id="closing-remarks">Closing remarks</h3>
<p>To my surprise, I found that by using UEFI I could more easily achieve non-standard setups with NixOS on the Pi. I had some attempts at trying to install NixOS with ZFS with the usual booting setup on the Pi but I could never seem to boot it after the installation.</p>
<p>I should also note that setting up encryption and remote unlocking is not very difficult on this setup, as it only requires a little bit more of ZFS configuration.</p>
<p>After setting this up, a friend of mine pointed me to the following links:</p>
<ul>
<li><a href="https://discourse.nixos.org/t/planning-for-a-better-nixos-on-arm/15346">Planning for a better NixOS on ARM</a></li>
<li><a href="https://nixos.wiki/wiki/NixOS_on_ARM/UEFI">NixOS on ARM/UEFI</a></li>
</ul>
<p>It turns out that I accidentally ended up building an ARM system which is aligned with the NixOS ARM lead&rsquo;s view for NixOS ARM systems in the future, which I find amusing.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://mgdm.net/weblog/nixos-on-raspberry-pi-4">https://mgdm.net/weblog/nixos-on-raspberry-pi-4</a></li>
<li><a href="https://nixos.wiki/wiki/NixOS_on_ARM">https://nixos.wiki/wiki/NixOS_on_ARM</a></li>
<li><a href="https://nixos.wiki/wiki/NixOS_on_ARM/Raspberry_Pi_4">https://nixos.wiki/wiki/NixOS_on_ARM/Raspberry_Pi_4</a></li>
<li><a href="https://elis.nu/blog/2019/08/encrypted-zfs-mirror-with-mirrored-boot-on-nixos/">https://elis.nu/blog/2019/08/encrypted-zfs-mirror-with-mirrored-boot-on-nixos/</a></li>
<li><a href="https://nixos.wiki/wiki/ZFS">https://nixos.wiki/wiki/ZFS</a></li>
<li><a href="https://nixos.org/manual/nixos/stable/index.html#sec-installation">https://nixos.org/manual/nixos/stable/index.html#sec-installation</a></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
