<?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>Linux on Chris Rants at Clouds</title>
    <link>https://chris.funderburg.me/tags/linux/</link>
    <description>Recent content in Linux on Chris Rants at Clouds</description>
    <image>
      <title>Chris Rants at Clouds</title>
      <url>https://chris.funderburg.me/me.jpg</url>
      <link>https://chris.funderburg.me/me.jpg</link>
    </image>
    <generator>Hugo -- 0.157.0</generator>
    <language>en-gb</language>
    <lastBuildDate>Tue, 10 Jun 2025 13:54:37 +0100</lastBuildDate>
    <atom:link href="https://chris.funderburg.me/tags/linux/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>10/Jun/2025 - Full Disk Encryption on ARM Based Arch Linux</title>
      <link>https://chris.funderburg.me/posts/2025/06/10/full-disk-encryption-on-arm-based-arch-linux/</link>
      <pubDate>Tue, 10 Jun 2025 13:54:37 +0100</pubDate>
      <guid>https://chris.funderburg.me/posts/2025/06/10/full-disk-encryption-on-arm-based-arch-linux/</guid>
      <description>An in-depth guide to setting up full disk encryption on Arch Linux ARM running on Apple M1 via Parallels Desktop</description>
      <content:encoded><![CDATA[<h2 id="arch-linux-arm-on-m1-parallels-encrypted-root-done-right-a-battle-log--guide">Arch Linux ARM on M1 Parallels: Encrypted Root Done Right (A Battle Log &amp; Guide)</h2>
<p>So, you&rsquo;ve decided to tackle Arch Linux ARM on your shiny Apple Mx Mac via
Parallels Desktop. Fantastic! You&rsquo;ve likely made it through the first bits of
the installation, but now you want that sweet, sweet full-disk encryption for
your root filesystem. You follow the Arch Wiki diligently, but&hellip; it just won&rsquo;t
boot. Kernel panics. &ldquo;Unable to mount root fs on unknown-block(0,0).&rdquo; Sound
familiar?</p>
<p>I&rsquo;ve been there. After wrestling with this for longer than I&rsquo;d like to admit,
I&rsquo;ve consolidated the specific steps and common pitfalls that finally got my
encrypted Arch ARM VM happily booting. This isn&rsquo;t a replacement for the official
<a href="https://wiki.archlinux.org/title/Installation_guide" target="_blank" >ArchWiki installation guide</a>,
but rather a set of crucial hints and corrections, particularly for the ARM and
Parallels context.</p>
<p>Let&rsquo;s dive in.</p>
<h3 id="my-setup-snapshot">My Setup Snapshot:</h3>
<ul>
<li><strong>Host:</strong> Apple MacBook M1</li>
<li><strong>Virtualization:</strong> Parallels Desktop</li>
<li><strong>Guest OS:</strong> Arch Linux ARM using the local install <a href="https://release.archboot.com/aarch64/latest/iso/" target="_blank" >from here</a>.</li>
<li><strong>Disk Layout:</strong>
<ul>
<li><code>/dev/sda1</code>: 4GB, FAT32, mounted as <code>/boot</code> (EFI partition).</li>
<li><code>/dev/sda2</code>: Rest of disk (approx. 496GB).
<ul>
<li><strong>Encrypted with LUKS:</strong> <code>cryptsetup luksFormat /dev/sda2</code></li>
<li><strong>Decrypted device:</strong> <code>/dev/mapper/cryptroot</code></li>
<li><strong>LVM Physical Volume (PV):</strong> <code>/dev/mapper/cryptroot</code></li>
<li><strong>Volume Group (VG):</strong> <code>volgrp</code></li>
<li><strong>Logical Volumes (LVs):</strong>
<ul>
<li><code>volgrp-swap</code>: 4GB, for swap.</li>
<li><code>volgrp-root</code>: Rest of space, formatted as <code>ext4</code>, mounted as <code>/</code>.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="the-encryption--lvm-journey-the-standard-part">The Encryption &amp; LVM Journey (The Standard Part)</h3>
<p>The initial steps of setting up LUKS on <code>/dev/sda2</code>, then creating the LVM
physical volume, volume group (<code>volgrp</code>), and logical volumes (<code>volgrp-swap</code>,
<code>volgrp-root</code>) on top of <code>/dev/mapper/cryptroot</code> are generally well-covered in
the ArchWiki. Follow those instructions meticulously. Ensure your filesystems
(FAT32 for <code>/boot</code>, ext4 for <code>volgrp-root</code>) are created correctly. Just to note,
the next time I do this, I will likely use <code>btrfs</code> for the root filesystem.</p>
<h3 id="the-initramfs-the-crucial-messenger-mkinitcpioconf">The Initramfs: The Crucial Messenger (mkinitcpio.conf)</h3>
<p>This is where the kernel gets its early boot instructions, including how to
decrypt your disk. Since we&rsquo;re using a <code>systemd</code>-based init (a common choice for
modern Arch installations), our hooks need to reflect that.</p>
<p>Open <code>/etc/mkinitcpio.conf</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo vim /etc/mkinitcpio.conf
</span></span></code></pre></div><p>Find the <code>HOOKS</code> line and ensure it contains the following, in this <em>exact</em> order:</p>
<pre tabindex="0"><code>HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)
</code></pre><p><strong>Key takeaways here:</strong></p>
<ul>
<li><strong><code>base</code></strong>: Provides essential utilities and a BusyBox recovery shell if
<code>systemd</code> fails. Always include it.</li>
<li><strong><code>systemd</code></strong>: This hook is crucial because it sets up the <code>systemd</code> early
userspace. If you picked <code>systemd</code> during installation, this is a must.</li>
<li><strong><code>sd-encrypt</code></strong>: This is the <code>systemd</code>-native hook for LUKS decryption. It
<em>must</em> be used when <code>systemd</code> is present in your hooks, and it replaces the
older <code>encrypt</code> hook.</li>
<li><strong><code>lvm2</code></strong>: Comes <em>after</em> <code>sd-encrypt</code> because LVM volumes reside on the
decrypted LUKS container.</li>
<li><strong>Order matters!</strong> <code>keyboard</code> before <code>sd-vconsole</code> and <code>sd-encrypt</code> ensures
your keyboard is ready for the passphrase. <code>block</code> ensures the disk devices
are visible before encryption.</li>
</ul>
<p>After editing, regenerate your initramfs with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkinitcpio -P
</span></span></code></pre></div><p><strong>Always watch for errors here!</strong> Ensure it successfully builds
<code>/boot/initramfs-linux.img</code> and acknowledges the <code>sd-encrypt</code> and <code>lvm2</code> hooks.</p>
<h3 id="grub-the-bootloader-whisperer-the-sneaky-bits">GRUB: The Bootloader Whisperer (The Sneaky Bits)</h3>
<p>GRUB is responsible for loading the kernel and initramfs, and passing kernel
parameters. This is where things get particularly tricky on ARM with encryption.</p>
<ol>
<li>
<p><strong>Enable Cryptodisk in GRUB:</strong>
Open <code>/etc/default/grub</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo vim /etc/default/grub
</span></span></code></pre></div><p>Ensure this line is present and uncommented:</p>
<pre tabindex="0"><code>GRUB_ENABLE_CRYPTODISK=&#34;y&#34;
</code></pre><p><strong>Why:</strong> This tells GRUB to load its own necessary modules to understand and
prompt for encrypted disks <em>before</em> the kernel even starts. Without this,
GRUB won&rsquo;t know what to do with your encrypted <code>/dev/sda2</code>.</p>
</li>
<li>
<p><strong>Kernel Command Line Parameters (<code>GRUB_CMDLINE_LINUX_DEFAULT</code>):</strong>
This line passes critical information to the kernel.</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">GRUB_CMDLINE_LINUX_DEFAULT</span><span class="o">=</span><span class="s2">&#34;loglevel=3 quiet rd.luks.name=5cf92567-adf8-46ef-816f-0519aea55b50=cryptroot root=/dev/mapper/volgrp-root&#34;</span>
</span></span></code></pre></div><p><strong>Let&rsquo;s break down <code>rd.luks.name</code>:</strong></p>
<ul>
<li><code>rd.luks.name=UUID=YOUR_LUKS_UUID=YOUR_DECRYPTED_NAME</code> is the most robust way.</li>
<li><strong>My specific working configuration used <code>rd.luks.name=5cf92567-adf8-46ef-816f-0519aea55b50=cryptroot</code></strong>. While <code>UUID=</code> is generally preferred for <code>rd.luks.name</code> (e.g., <code>rd.luks.name=UUID=your-uuid-here=cryptroot</code>), the bare UUID also worked for me. The key is that <code>5cf92567-adf8-46ef-816f-0519aea55b50</code> <strong>must</strong> be the exact UUID of your <em>raw encrypted partition</em> (<code>/dev/sda2</code>), and <code>cryptroot</code> must be the name you want the decrypted volume to have.</li>
<li><code>root=/dev/mapper/volgrp-root</code>: This tells the kernel where your actual root filesystem is <em>after</em> decryption and LVM activation. Make sure <code>volgrp-root</code> matches your LVM Logical Volume name exactly.</li>
</ul>
</li>
<li>
<p><strong>The Hidden Gem: Ensuring GRUB Loads the Initramfs (<code>/etc/grub.d/10_linux</code>)</strong></p>
<p>This was the stealthy culprit in my case! Even if <code>mkinitcpio -P</code> builds the initramfs and <code>grub-mkconfig</code> runs, GRUB might not include the <code>initrd</code> command in its generated <code>grub.cfg</code> if it doesn&rsquo;t find the initramfs file under its expected names.</p>
<p>Open <code>/etc/grub.d/10_linux</code> (be careful, this is a GRUB generation script!):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo vim /etc/grub.d/10_linux
</span></span></code></pre></div><p>Look for the <code>for i in</code> loop that iterates through common initramfs filenames. It should look something like this (or similar on ARM):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> i in <span class="s2">&#34;initramfs-linux.img&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initrd.img-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">.img&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">.img.old&#34;</span> <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">.gz&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">.gz.old&#34;</span> <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initramfs-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">.img&#34;</span> <span class="s2">&#34;initramfs-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">.img.old&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initrd.img-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">.img&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initrd-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;initramfs-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">.img&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initramfs-genkernel-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initramfs-genkernel-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initramfs-genkernel-</span><span class="si">${</span><span class="nv">GENKERNEL_ARCH</span><span class="si">}</span><span class="s2">-</span><span class="si">${</span><span class="nv">version</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">            <span class="s2">&#34;initramfs-genkernel-</span><span class="si">${</span><span class="nv">GENKERNEL_ARCH</span><span class="si">}</span><span class="s2">-</span><span class="si">${</span><span class="nv">alt_version</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">test</span> -e <span class="s2">&#34;</span><span class="si">${</span><span class="nv">dirname</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">&#34;</span> <span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">      <span class="nv">initrd_real</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="nb">break</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span></code></pre></div><p><strong>My Fix:</strong> I had to explicitly ensure <code>&quot;initramfs-linux.img&quot;</code> was present and ideally early in that list. It appears the default <code>10_linux</code> on my ARM setup wasn&rsquo;t correctly prioritizing or finding the standard Arch <code>initramfs-linux.img</code>. <strong>Adding <code>&quot;initramfs-linux.img&quot;</code> explicitly as the very first option in that list (or ensuring it&rsquo;s there) solved the issue of GRUB not loading the initramfs.</strong></p>
<p><strong>After making this change, save the file.</strong></p>
</li>
</ol>
<h3 id="the-final-grub-generation">The Final GRUB Generation</h3>
<p>Now, with all the pieces in place, regenerate your GRUB configuration:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo grub-mkconfig -o /boot/grub/grub.cfg
</span></span></code></pre></div><p><strong>Crucially, watch the output!</strong> You should now see lines confirming:</p>
<ul>
<li><code>Found Linux image: /boot/vmlinuz-linux</code></li>
<li><strong><code>Found initrd image: /boot/initramfs-linux.img</code></strong> (This is the big one!)</li>
<li>It should also show the kernel command line it&rsquo;s generating, confirming your <code>cryptdevice</code> and <code>root</code> parameters are correct.</li>
</ul>
<h3 id="reboot-and-victory">Reboot and Victory!</h3>
<p>Exit your chroot environment, unmount all partitions, close the LUKS device, and reboot your VM:</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">exit</span>
</span></span><span class="line"><span class="cl">sudo umount /mnt/boot
</span></span><span class="line"><span class="cl">sudo umount /mnt
</span></span><span class="line"><span class="cl">sudo cryptsetup close cryptroot
</span></span><span class="line"><span class="cl">sudo reboot
</span></span></code></pre></div><p>If all steps were followed, you should now be greeted by a passphrase prompt from GRUB, and upon successful entry, your Arch Linux ARM system should boot seamlessly into your encrypted root!</p>
<p>This process was a true test of patience, highlighting that while Arch Linux is incredibly powerful, solving boot issues on non-standard architectures and encrypted setups requires a deep dive into the specifics of each component. Hopefully, this detailed account saves someone else the late nights!</p>
<p>As always, you can add my <a href="https://chris.funderburg.me/index.xml" target="_blank" >RSS feed</a> to your reader of choice and if you made it this far <strong>thanks for reading</strong>!</p>
<p>Chris</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
