User:Jared/Gentoo On An M1 Mac

From Gentoo Wiki
Jump to:navigation Jump to:search

Last Updated Jared (talk) 02:12, 23 June 2024 (UTC)

Important
This guide is maintained by Jared , it shadows the official installation guide provided by Gentoo Asahi project as well as the AMD64 Handbook. If something isn't working well after following this guide, please reach out on the discussion page. If you need more official support (e.g., IRC), please do due diligence to ease the burden on support by reviewing the official Gentoo project's installation instructions BEFORE reaching out. This will free up the official project from chasing down any minor gaps between this guide and the official one! Thank you in advance and good luck!

This guide will walk you through an installation of Gentoo using the Asahi Linux patchset. The current supported distribution by Asahi Linux is Fedora. Due to macOS not allowing USB devices for booting, we're going to use "asahi-gentoosupport" to boot Gentoo off of an initramfs to mimic a liveusb.

This guide will end up creating an encrypted root partition (which prevents someone from accessing your data through single user mode) with Gentoo Linux on it.

Preparing Asahi Linux (Fedora)

Before we can get into Gentoo, we'll need to use the Asahi Linux installer to setup everything for us. Before running the following, it's highly recommended that you read the script at https://alx.sh, since piping to sh is generally a bad practice. For ease, we'll do that anyways.

user@host ~ %curl https://alx.sh | EXPERT=1 sh
Bootstrapping installer:
 Checking version...
 Version: v0.7.1
 Downloading...
 Extracting...
 Initializing...

The installer needs to run as root. Please enter your sudo password if prompted. Password: enter your user's password then Enter

Welcome to the Asahi Linux installer!

This installer will guide you through the process of setting up Asahi Linux on your Mac.

Please make sure you are familiar with our documentation at:

 https://alx.sh/w

Press enter to continue. press Enter

By default, this installer will hide certain advanced options that are only useful for Asahi Linux developers. You can enable expert mode to show them. Do not enable this unless you know what you are doing. Please do not file bugs if things go wrong in expert mode. » Enable expert mode? (y/N) press y then Enter

Collecting system information...
  Product name: MacBook Pro (14-inch, 2021)
  SoC: Apple M1 Pro
... additional output suppressed ... Collecting partition information...
  System disk: disk0

Collecting OS information...

Partitions in system disk (disk0):
  1: APFS [Macintosh HD] (494.38 GB, 6 volumes)
    OS: [B*] [Macintosh HD] macOS v14.4.1 [disk3s5s1, UUID-GOES-HERE]
  2: APFS (System Recovery) (5.37 GB, 2 volumes)
    OS: [  ] recoveryOS v14.4.1 [Primary recoveryOS]

  [B ] = Booted OS, [R ] = Booted recovery, [? ] = Unknown  [ *] = Default boot volume

Using OS 'Macintosh HD' (disk3s5s1) for machine authentication.

Choose what to do:
  r: Resize an existing partition to make space for a new OS
  q: Quit without doing anything

» Action (r): press r then Enter

We're going to resize this partition:
  APFS [Macintosh HD] (494.38 GB, 6 volumes)
  Total size:494.38 GB
  Free space: 439.89 GB
  Available space: 401.89 GB
  Overhead: 0 B
  Minimum total size: 92.49 GB (18.71%)
Enter the new size for your existing partition:
  You can enter a size such as '1GB', a fraction such as '50%',
  or the word 'min' for the smallest allowable size.

  Examples:
  30%  - 30% to macOS, 70% to the new OS
  80GB - 80GB to macOS, the rest to your new OS
  min  - Shrink macOS as much as (safely) possible

» New size (50%): press Enter

Resizing will free up 247.19 GB of space.

Note: your system may appear to freeze during the resize. This is normal, just wait until the process completes. » Continue? (y/N): press y then Enter

Started APFS operation ... SIGNIFICANT additional output suppressed ... Finished APFS operation

Resize complete. Press enter to continue. press Enter

Collecting partition information...
  System disk: disk0

Collecting OS information...

Partitions in system disk (disk0):
  1: APFS [Macintosh HD] (247.19 GB, 6 volumes)
    OS: [B*] [Macintosh HD] macOS v14.4.1 [disk3s5s1, UUID-GOES-HERE]
  2: (free space: 247.19 GB)  
  3: APFS (System Recovery) (5.37 GB, 2 volumes)
    OS: [  ] recoveryOS v14.4.1 [Primary recoveryOS]

  [B ] = Booted OS, [R ] = Booted recovery, [? ] = Unknown  [ *] = Default boot volume

Using OS 'Macintosh HD' (disk3s1s1) for machine authentication.

Choose what to do:
  f: Install an OS into free space
  r: Resize an existing partition to make space for a new OS
  q: Quit without doing anything

» Action (f): press Enter

Choose an OS to install:
Choose an OS to install:
  1: Fedora Asahi Remix 39 with KDE Plasma
  2: Fedora Asahi Remix 39 with GNOME
  3: Fedora Asahi Remix 39 Server
  4: Fedora Asahi Remix 39 Minimal
  5: Arch Linux ARM (not recommended)
  6: UEFI environment only (m1n1 + U-Boot + ESP)
  7: Tethered boot (m1n1, for development)

» OS: press 4 then Enter

Downloading OS package info... -

How much space should be allocated to the new OS?
  You can enter a size such as '1GB', a fraction such as '50%',
  the word 'min' for the smallest allowable size, or
  the word 'max' to use all available space.

» New OS size (max): press Enter

The new OS will be allocated 247.19 GB of space, leaving 86.02 KB of free space.

Enter a name for your OS

» OS name (Fedora Linux Minimal): type 'Gentoo' (without the quotes) then Enter

Choose the macOS version to use for boot firmware: (If unsure, just press enter) Enter

Downloading macOS OS package info... Creating new stub macOS named Gentoo Installing stub macOS into disk0s5 (Gentoo) ... additional output suppressed ...

To continue the installation, you will need to enter your macOS admin credentials.

Password for user: type your user's password then Enter

Setting the new OS as the default boot volume...

Installation successful!

Install information:
  APFS VGID: UUID-IS-HERE
  EFI PARTUUID: UUID-IS-HERE

To be able to boot your new OS, you will need to complete one more step. Please read the following instructions carefully. Failure to do so will leave your new installation in an unbootable state.

Press enter to continue. press Enter


When the system shuts down, follow these steps:

1. Wait 15 seconds for the system to fully shut down. 2. Press and hold down the power button to power on the system.      * It is important that the system be fully powered off before this step,        and that you press and hold down the button once, not multiple times.        This is required to put the machine into the right mode. 3. Release it once you see 'Entering startup options' or a spinner. 4. Wait for the volume list to appear. 5. Choose 'Gentoo'. 6. You will briefly see a 'macOS Recovery' dialog.      * If you are asked to 'Select a volume to recover',        then choose your normal macOS volume and click Next.        You may need to authenticate yourself with your macOS credentials. 7. Once the 'Asahi Linux installer' screen appears, follow the prompts.

If you end up in a bootloop or get a message telling you that macOS needs to be reinstalled, that means you didn't follow the steps above properly. Fully shut down your system without doing anything, and try again. If in trouble, hold down the power button to boot, select macOS, run this installer again, and choose the 'p' option to retry the process

Press enter to shut down the system. DO NOT PRESS ENTER. Continue reading the doc

Finishing the Asahi Linux Install

We're now close to having an Arch Linux install! The next step is to reboot. As you may have noticed from the output, there's an amount of complexity to the next steps, so please read the below carefully. When you reboot the computer do the following steps:

  1. Wait 15 seconds.
  2. Press and HOLD the power button until you see "Entering startup options" or a spinner.
  3. Release the power button (if you haven't already)
  4. Wait for "Gentoo" to appear. Choose 'Gentoo' using the arrow keys, select it and press Enter
  5. You will see what appears to be a macOS Recovery screen. Enter your user's password, if prompted (usually if FileVault is enabled).

If all went well, a terminal window should appear. This will set your system into permissive mode to allow booting Linux.

Note
The Asahi Linux devs are working on removing this requirement. If you have File Vault enabled, your credentials will always be required to install a new operating system, like we just did, which makes your system still secure against malicious actors. If you do not have File Vault enabled, the author recommends doing so

Follow the instructions on terminal window, it will mostly just consist of pressing Enter and at the end entering the username and password of your macOS user. At the end it'll ask you if you'd like to reboot, press Enter to do so an you'll be presented with the output of U-Boot. U-Boot is used as the bootloader, which right now just chains Grub (which most users should be familiar with). Grub, in turn, boots into Fedora for us. If all went well, you should see a TTY asking you a lot of questions. On to the next step!

Configuring Asahi Linux

In order to create our Gentoo "liveusb" (powered by an initramfs), we'll need to update the system first to ensure that we don't run into issues later. We're going to do this by running "dnf", the Fedora package manager. However, first we'll need to go through the configuration steps.

1) [ ] Language Options           2) [x] Time Settings
3) [x] Network Configuration      4) [!] Root password
5) [!] User Creation
Please make a selection from the above ['c' to continue, 'q' to quit', 'r' to
refresh]:
press 4 then Enter
Please select new root password. You will have to type it twice:

Password:
enter a root password then Enter
Password (confirm):
enter the same password again then Enter
1) [ ] Language Options           2) [x] Time Settings
3) [x] Network Configuration      4) [x] Root password
5) [!] User Creation
Please make a selection from the above ['c' to continue, 'q' to quit', 'r' to
refresh]:
press q then Enter
Are you sure you want to quit the configuration process?
  You might end up with unusable system if you do.
Please respond 'yes' or 'no':
refresh]: 
enter "yes" then Enter

You should now have a TTY screen, where you can enter "root" and the password you selected earlier!

To connect to wifi, we're going to use NetworkManager. We'll do this through the nmcli command.

[root@fedora ~]#nmcli device wifi connect <ssid> password <password>
Connection Output Here>

Let's validate that our network connectivity is working as expected

[root@fedora ~]#ping -c 3 www.gentoo.org
PING dualstack.n.sni.global.fastly.net (146.75.41.91) 56(84) bytes of data.
64 bytes from 146.75.41.91 (146.75.41.91): icmp_seq=1 ttl=57 time=5.66 ms
64 bytes from 146.75.41.91 (146.75.41.91): icmp_seq=2 ttl=57 time=7.72 ms
64 bytes from 146.75.41.91 (146.75.41.91): icmp_seq=3 ttl=57 time=7.45 ms

--- dualstack.n.sni.global.fastly.net ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 5.656/6.939/7.716/0.913 ms

If that completed successfully, we can update our system now!

[root@fedora ~]#dnf upgrade --refresh
Fedora Asahi Remix Hotfixes                     616  B/s | 241  B     00:00
... output snipped ...
Dependencies resolved.
============================================================================
 Package
============================================================================
... output snipped ...
Total download size: <size> M
Is this ok [y/N]: <press y and then enter>
... output snipped ...
Complete!

After a long time (usually!) later... our system should now be up-to-date. Let's go ahead and reboot it in case our kernel was upgraded.

[root@fedora ~]#reboot

Setting up the Gentoo "liveusb"

Now we can use asahi-gentoosupport to create the initramfs-based liveusb. We'll need to download git to clone the repo and wget to fetch the latest minimal iso.

[root@alarm ~]#dnf install git wget

From there, clone the repository and change into the newly created directory.

[root@alarm ~]#cd asahi-gentoosupport

In order for us to be able to run the genstrap.sh script, we'll need to download the latest install minimal iso for our platform. For convenience, I've written a script to automate fetching the latest minimal ISO. I highly encourage reading through the script before running it!

Determining latest minimal image...

Using latest minimal image: 20240505T234912Z/install-arm64-minimal-20240505T234912Z.iso --2024-05-08 22:20:53-- https://gentoo.rgst.io/gentoo/releases/arm64/autobuilds/20240505T234912Z/install-arm64-minimal-20240505T234912Z.iso ... output snipped ... 2024-05-08 22:21:16 (27.9 MB/s) - 'install-arm64-minimal-20240505T234912Z.iso' saved [721958912/721958912] Validating image...  -> Fetching GPG key(s)... gpg: key BB572E0E2D182910: public key "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" imported ... output snipped ...  -> Fetching download signature... --2024-05-08 22:21:16-- https://gentoo.rgst.io/gentoo/releases/arm64/autobuilds/20240505T234912Z/install-arm64-minimal-20240505T234912Z.iso.asc ... output omitted ... 2024-05-08 22:21:17 (24.4 MB/s) - 'install-arm64-minimal-20240505T234912Z.iso.asc' saved [488/488]

 -> Checking image signature... gpg: assuming signed data in 'install-arm64-minimal-20240505T234912Z.iso' gpg: Signature made Sun May 5 22:41:16 2024 EDT gpg: using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [ultimate]

Successfully validated image.
Image is available at: /root/asahi-gentoosupport/install.iso

Now we can run genstrap.sh to create the initramfs out of the installation iso we just downloaded.

[root@alarm asahi-gentoosupport]#./genstrap.sh
This script will bootstrap an initramfs for installing Gentoo on

Apple Silicon machines. It must be run from an Asahi Linux install.

Please ensure that the latest Gentoo arm64 minimal install image is located in this directory and named install.iso before continuing.

Press Enter to continue. press Enter Cleaning up....

Installing dependencies... Last metadata expiration check: 0:08:24 ago on Wed May 8 22:17:16 2024. allow_vendor_change is disabled. This option is currently not supported for downgrade and distro-sync commands Package squashfs-tools-4.6.1-2.fc39.aarch64 is already installed. Package cpio-2.14-4.fc39.aarch64 is already installed. Package parted-3.6-2.fc39.aarch64 is already installed. Dependencies resolved.

Package                Architecture    Version            Repository           Size

Installing:

bsdtar                   aarch64       3.7.1-1.fc39          fedora             64 k
dracut-live              aarch64       059-16.fc39           updates            28 k

Installing dependencies:

fuse                     aarch64       2.9.9-17.fc39         fedora             79 k
fuse-common              aarch64       3.16.1-1.fc39         fedora             8.3 k

Transaction Summary

Install 4 Packages

Total download size: 180 k Installed size: 1.0 M Is this ok [y/N]:press y then Enter Extracting squashfs... Creating temporary mount...

Warning: The resulting partition is not properly aligned for best performance: 34s % 2048s != 0s mke2fs 1.47.0 (5-Feb-2023) /dev/ram0p1 alignment is offset by 15360 bytes. This may result in very poor performance, (re)-partitioning suggested. Creating filesystem with 255748 4k blocks and 64000 inodes Filesystem UUID: 023e9a3c-a19e-42ba-88d6-fdc51b37bc3d Superblock backups stored on blocks:      32768, 98304, 163840, 229376

Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done

Unsquashing Gentoo live environment.

[=========================================================================================================] 85191/85191 100% Setting up Gentoo live environment for Apple Silicon...

Creating live image...

2046014+0 records in 2046014+0 records out 1047559168 bytes (1.0 GB, 999 MiB) copied, 1.81064 s, 579 MB/s [===========================================================================================================] 7993/7993 100% Setting up initramfs... Setting up initramfs and GRUB... Cleaning up....

When rebooting your system, select Gentoo Live Install environment from
the GRUB menu to boot into the Gentoo LiveCD.

We now have an entry in our Grub menu titled "Gentoo Live Install Environment". When selected, it will use our current kernel to boot an initramfs that contains the contents of the minimal install iso we downloaded earlier. This allows us to customize the partition that we're currently booted on. Namely, this allows us to wipe away Arch Linux (Asahi) and replace it with an encrypted Gentoo installation. Next we'll reboot and select the "Gento Live Install Environment" option from Grub so we can start the Gentoo install!

[root@fedora asahi-gentoosupport]#reboot

Wait for u-boot to send you into Grub, then select the "Gentoo Live Install Environment" option. You should see a number of penguins at the top of the screen, with dmesg output scrolling across the screen. Finally, you should be dumped into the familiar livecd ~ output of a Gentoo minimal install USB!

Setting up Networking (again)

Now that we're in a Gentoo install environment, we're going to need network connectivity again. This time, we're going to use net-setup. This will open a terminal UI that will ask you questions about your network setup. Follow the interactive prompts as needed. Once finished, run ifconfig until you have an ip address for your network interface (it may take a little bit!).

livecd ~ #ifconfig | grep w -A 2 | grep "inet "
    inet 192.168.1.250  netmask 255.255.255.0  broadcast 192.168.1.255
Note
If you're not getting an ip address and you're sure that you're entering the correct wireless credentials, check if your SSID is WPA3. Some settings may not be supported in this minimal installation environment. Use a 2.4 ghz network if possible, in this case.

Once again, let's double check that our network is working as expected.

livecd ~ #ping -c 3 www.gentoo.org
PING www.gentoo.org(2a04:4e42::347 (2a04:4e42::347)) 56 data bytes
64 bytes from 2a04:4e42::347 (2a04:4e42::347): icmp_seq=1 ttl=58 time=101 ms
64 bytes from 2a04:4e42::347 (2a04:4e42::347): icmp_seq=2 ttl=58 time=30.9 ms
64 bytes from 2a04:4e42::347 (2a04:4e42::347): icmp_seq=3 ttl=58 time=46.4 ms

--- www.gentoo.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 30.913/59.298/100.621/29.892 ms

(Optional) Setup SSH

It can be helpful to do the next step over SSH from a second "helper" computer, since a lot of the next steps may require a lot of copy and pasting as well as typing, which can be not very fun on a TTY session.

To setup ssh we'll need to set a password for root and start the SSH daemon.

livecd ~ #/etc/init.d/sshd start
livecd ~ #passwd root

Using the IP address from earlier, connect to your machine over SSH.

user $ssh root@192.168.X.X
Welcome to the Gentoo Linux Minimal Installation CD!

... output omitted ...

Thank you for using Gentoo Linux!
livecd ~ #

Now you can continue with the rest of the guide over SSH (until you reboot, anyways!)

Preparing the Filesystem

This section shadows Chapter 4 of the Gentoo Handbook, so please give that a read if you have any questions about what is going on here. It goes into much better detail about disk setup, in general, than I could ever do myself.

We're going to setup a LUKS2 encrypted volume using cryptsetup, from there we're going to create a btrfs formatted partition to be our root partition. Advanced users can setup LVM here, if they wish, but this is out-of-scope of this tutorial (the author doesn't believe LVM provides much value in today's world).

Let's start by identifying our disks. Thankfully, as of this writing, you can easily find the partitions by their labels. Let's used blkid to find them.

livecd ~ #blkid --label fedora
livecd ~ #blkid --label "EFI - GENTO"
/dev/nvme0n1p5 # asahi-root
/dev/nvme0n1p4 # EFI - GENTOO

The asahi-root partition is our / partition, while the EFI - GENTO partition will be our /boot partition.

Important
Do not mess with the boot partition, doing so may break the entire install.

Make note of the asahi-root device path, it will be used for our next command, when we use cryptsetup to create our encrypted partition. Using cryptsetup, we're going to create an encrypted partition, first lets dig into the arguments that we're going to be using.

  • We use argon2id instead of PBKDF because it is more resistant to ASIC/GPU cracking. We do not bump the iterations because [it is generally not worth the cost compared to using a higher entropy passphrase].
  • We keep the default of using aes-xtc because it is better supported and accelerated by hardware (yes, even the M1 mac has the aes CPU feature).
  • We use luks2 because we are not using Grub to boot our kernel (no encrypted /boot) and it provides better security tooling, such as cryptsetup reencrypt.


livecd ~ #cryptsetup luksFormat --type luks2 --pbkdf argon2id --hash sha512 --key-size 512 /dev/nvme0n1p#
WARNING: Device /dev/nvme0n1p# already contains a 'ext4' superblock signature.

WARNING!
========
This will overwrite data on /dev/nvme0n1p5 irrevocably.

Are you sure? (Type 'yes' in capital letters) <type YES>

This will take a little bit, cryptsetup will optimize the amount of iterations and memory to use based on how many it can do in 2 seconds to ensure the most secure, but also reasonable, options are set for your system.

Once that's finished, we can take a look at what it did by using the cryptsetup luksDump command. Let's take a look.

livecd ~ #cryptsetup luksDump /dev/nvme0n1p#
LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           UUID-GOES-HERE
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)

Data segments:
  0: crypt
        offset: 16777216 [bytes]
        length: (whole device)
        cipher: aes-xts-plain64
        sector: 4096 [bytes]

Keyslots:
  0: luks2
        Key:        512 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        Cipher key: 512 bits
        PBKDF:      argon2id
        Time cost:  7
        Memory:     1048576
        Threads:    4
        Salt:       <snipped hex>
        AF stripes: 4000
        AF hash:    sha512
        Area offset:32768 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
        Hash:       sha512
        Iterations: 422132
        Salt:       <snipped hex>
        Digest:     <snipped hex>

Next, we're going to mount the device as a mapper device that will enable us to treat the luks device as an unencrypted device for formatting.

livecd ~ #cryptsetup luksOpen /dev/nvme0n1p# luks
Enter passphrase for /dev/nvme0n1p#: <type in your password then press ENTER>

This mounted our luks device as a path at /dev/mapper/luks (based on the last argument to the command) that we'll use as our root device for creating a btrfs partition.

Note
Advanced users can replace btrfs with their preferred filesystem, but be sure to update/research areas that it needs to be included in when mentioned later.
livecd ~ #mkfs.btrfs --label root /dev/mapper/luks
btrfs-progs v6.2.1
See http://btrfs.wiki.kernel.org for more information.

Label:              root
UUID:               86a9b8cd-e939-490c-9203-05ebb07c0217
Node size:          16384
Sector size:        16384
Filesystem size:    227.41GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP               1.00GiB
  System:           DUP               8.00MiB
SSD detected:       yes
Zoned device:       no
Incompat features:  extref, skinny-metadata, no-holes
Runtime features:   free-space-tree
Checksum:           crc32c
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1   227.41GiB  /dev/mapper/luks

We now have a btrfs disk that we can mount and start our installation of Gentoo on. We're going to use a stage-3 archive to create an installation of Gentoo. A stage-3 is essentially a minimal installation, but with no kernel. Only libraries and binaries that are required to bootstrap a Gentoo installation. Let's mount the file system and download the stage-3 archive.

livecd ~ #mkdir --parents /mnt/gentoo
livecd ~ #mount /dev/mapper/luks /mnt/gentoo
livecd ~ #cd /mnt/gentoo

Now we'll download the stage-3 archive, we'll need to get the latest version first. Just like downloading the minimal install ISO earlier, we're going to use a helper script (that you should read first!).

curl -L https://raw.githubusercontent.com/jaredallard/gentoo-m1-mac/main/fetch-stage-3.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2761  100  2761    0     0  16682      0 --:--:-- --:--:-- --:--:-- 16733
Preparing to fetch minimal image
 -> Ensuring GPG keys are trusted
gpg: key A13D0EF1914E7A72: 1 signature not checked due to a missing key
gpg: key A13D0EF1914E7A72: public key "Gentoo repository mirrors (automated git signing key) <repomirrorci@gentoo.org>" imported
gpg: key DB6B8C1F96D8BF6D: 1 signature not checked due to a missing key
gpg: key DB6B8C1F96D8BF6D: public key "Gentoo ebuild repository signing key (Automated Signing Key) <infrastructure@gentoo.org>" imported
gpg: key 9E6438C817072058: 2 signatures not checked due to missing keys
gpg: key 9E6438C817072058: public key "Gentoo Linux Release Engineering (Gentoo Linux Release Signing Key) <releng@gentoo.org>" imported
gpg: key BB572E0E2D182910: 1 signature not checked due to a missing key
gpg: key BB572E0E2D182910: "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" 2 new signatures
gpg: Total number processed: 4
gpg:               imported: 3
gpg:         new signatures: 2
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2026-07-01
Determining latest minimal image...
 -> Checking latest-stage3-arm64-desktop-systemd.txt signature...
gpg: Signature made Thu May  9 12:01:13 2024 UTC
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [ultimate]
Using latest minimal image: 20240505T234912Z/stage3-arm64-desktop-systemd-20240505T234912Z.tar.xz
--2024-05-09 11:59:06--  https://gentoo.rgst.io/gentoo/releases/arm64/autobuilds/20240505T234912Z/stage3-arm64-desktop-systemd-20240505T234912Z.tar.xz
... output snipped ...
2024-05-09 11:59:23 (33.7 MB/s) - ‘stage3-arm64-desktop-systemd-20240505T234912Z.tar.xz’ saved [576920028/576920028]

 -> Fetching download signature...
--2024-05-09 11:59:23--  https://gentoo.rgst.io/gentoo/releases/arm64/autobuilds/20240505T234912Z/stage3-arm64-desktop-systemd-20240505T234912Z.tar.xz.asc
... output snipped ...
2024-05-09 11:59:23 (1.21 GB/s) - ‘stage3-arm64-desktop-systemd-20240505T234912Z.tar.xz.asc’ saved [488/488]

 -> Checking image signature...
gpg: assuming signed data in 'stage3-arm64-desktop-systemd-20240505T234912Z.tar.xz'
gpg: Signature made Mon May  6 05:01:20 2024 UTC
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [ultimate]
Sccessfully validated image.
Image is available at: /mnt/gentoo/latest-stage3-arm64-desktop-systemd.tar.xz

Now we're going to extract the contents of the archive into our directory, thus creating the Gentoo install.

livecd /mnt/gentoo #tar xpvf latest-stage3-arm64-desktop-systemd.tar.xz --xattrs-include='*.*' --numeric-owner

As per the handbook, the options to tar are to extract, provide verbose output, decompress with xz (J), preserve permissions and extract from a file, not standard input. Further, the --xattrs-include='*.*' option ensures that extended attributes stored in the tarball are also copied (from all namespaces), and the --numeric-owner option uses the numeric owner and group IDs from the tarball, even if they are different in the host system (they will not be here, since we are booted from an official minimal install image, but it doesn't hurt to specify this).[1]

Let's make sure that the base system installed OK

livecd /mnt/gentoo #ls
bin   dev  home  lib64  mnt  proc  run   stage3-arm64-desktop-systemd-20230514T223201Z.tar.xz      sys  usr
boot  etc  lib   media  opt  root  sbin  stage3-arm64-desktop-systemd-20230514T223201Z.tar.xz.asc  tmp  var

If you see output similar to the above, you should be good to go!

Before we continue, you may want to read up on portage, emerge, and other aspects of Gentoo package management[2]. We'll wait for you, don't worry! :)

Creating a chroot

Now that we have a Gentoo system, let's chroot into it so we can install the required packages as well as do initial configuration of our shiny new system.

To start with, we're going to opt into the Gentoo package repository.

livecd /mnt/gentoo #mkdir --parents /mnt/gentoo/etc/portage/repos.conf
livecd /mnt/gentoo #cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf

From there we need to ensure that networking still works from inside of the chroot.

livecd /mnt/gentoo #cp --dereference /etc/resolv.conf /mnt/gentoo/etc/

Now.. the exciting part (or for those of us who have ran through 'many gentoo installs, the tedious part). We're going to mount the required devices from the host into the chroot so that everything still works as expected from inside the chroot.

livecd /mnt/gentoo #mount --types proc /proc /mnt/gentoo/proc
livecd /mnt/gentoo #mount --rbind /sys /mnt/gentoo/sys
livecd /mnt/gentoo #mount --make-rslave /mnt/gentoo/sys
livecd /mnt/gentoo #mount --rbind /dev /mnt/gentoo/dev
livecd /mnt/gentoo #mount --make-rslave /mnt/gentoo/dev
livecd /mnt/gentoo #mount --bind /run /mnt/gentoo/run
livecd /mnt/gentoo #mount --make-slave /mnt/gentoo/run

Whew. That was exciting... let's enter the chroot and mount the our /boot partition from earlier! While we're here, we're going to change our PS1 (terminal prompt) to convey that we're in a chroot. This helps make it easier to remember that we're in a chroot vs the live usb image.

livecd /mnt/gentoo #chroot /mnt/gentoo /bin/bash
livecd /mnt/gentoo #source /etc/profile
livecd /mnt/gentoo #export PS1="(chroot) ${PS1}"
livecd /mnt/gentoo #mount /dev/nvme0n1p# /boot # The "#" number is partition number from 'blkid --label "EFI - GENTO"' earlier!

Now we're in our future Gentoo system! Let's go ahead and do some basic setup to ensure that we have a functional system, plus some steps exclusive to the M1 mac :)

Configuring the Basics

The first thing to setup in any Gentoo system is portage. This will allow us to configure how things are compiled and with what flags. We're going to use a stock configuration created by the author -- since it works out of the box with M1 macs. Feel free to change it as needed.

FILE /etc/portage/make.conf
# vim: set language=bash;
CHOST="aarch64-unknown-linux-gnu"

# Optimization flags.
COMMON_FLAGS="-march=armv8.5-a+fp16+simd+crypto+i8mm -mtune=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
RUSTFLAGS="-C target-cpu=native"

# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C

# Note: Update "-j" to be a number more appropriate for your
# hardware (e.g., m2 max has more cores).
MAKEOPTS="-j4"

# GENTOO_MIRRORS is the mirrors to use for emerge sources. The author
# hosts one on R2, which should be fast enough for most usecases.
GENTOO_MIRRORS="https://gentoo.rgst.io/gentoo"

# EMERGE_DEFAULT_OPTS is the options to use for emerges. We use -j3 here to
# enable compiling at most 3 packages at the same time. This also makes logs not spam
# our screen everytime. It's nice :)
EMERGE_DEFAULT_OPTS="--jobs 3"

# VIDEO_CARDS is the video card (gpu) we're using. We use "asahi" for the mesa package provided
# by the asahi-overlay.
VIDEO_CARDS="asahi"

# Keep a newline at the end! Important!

For brevity, we'll download this one from the Github Gist, feel free to check it out to see if any changes have been made since the writing of this post.

Now we'll need to fetch the packages available from the Gentoo repositories, the first time can take a really long time, so we use emerge-webrsync to speed things up and reduce the load on the servers.

(chroot) livecd / #emerge-webrsync
!!! Section 'gentoo' in repos.conf has location attribute set to nonexistent directory: '/var/db/repos/gentoo'
!!! Invalid Repository Location (not a dir): '/var/db/repos/gentoo'
Fetching most recent snapshot ...
Trying to retrieve 20230520 snapshot from https://gentoo.osuosl.org ...
Fetching file gentoo-20230520.tar.xz.md5sum ...
Fetching file gentoo-20230520.tar.xz.gpgsig ...
Fetching file gentoo-20230520.tar.xz ...
Checking digest ...
Getting snapshot timestamp ...
Syncing local tree ...

Number of files: 143,690 (reg: 116,949, dir: 26,741)
Number of created files: 143,689 (reg: 116,949, dir: 26,740)
Number of deleted files: 0
Number of regular files transferred: 116,949
Total file size: 186.46M bytes
Total transferred file size: 186.46M bytes
Literal data: 186.46M bytes
Matched data: 0 bytes
File list size: 3.26M
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 100.70M
Total bytes received: 2.34M

sent 100.70M bytes  received 2.34M bytes  15.85M bytes/sec
total size is 186.46M  speedup is 1.81
Cleaning up ...

Performing Global Updates
(Could take a couple of minutes if you have a lot of binary packages.)
@


 * IMPORTANT: 11 news items need reading for repository 'gentoo'.
 * Use eselect news read to view new items.

Note
Ignore any warning that looks like the below
!!! Section 'gentoo' in repos.conf has location attribute set to nonexistent directory: '/var/db/repos/gentoo'
!!! Invalid Repository Location (not a dir): '/var/db/repos/gentoo'
This will be solved by the command that was just ran, as it will create that directory.

Now that we've established the repository from a web snapshot, we're going to update our package list through emerge --sync just to make sure we have everything. You'll want to get in the habit of running this before any system updates!

(chroot) livecd / #emerge --sync
>>> Syncing repository 'gentoo' into '/var/db/repos/gentoo'...
 * Using keys from /usr/share/openpgp-keys/gentoo-release.asc
 * Refreshing keys via WKD ...                                                                                        [ ok ]
>>> Starting rsync with rsync://[2a00:1828:a00d:ffff::6]/gentoo-portage...
>>> Checking server timestamp ...
... lots of output snipped ...

It's a good idea to ensure that portage itself is up-to-date, though it should be if you downloaded a new snapshot :)

(chroot) livecd / #emerge --ask --verbose --oneshot portage
... output omitted ...
Would you like to merge these packages? [Yes/No] <press Y and then ENTER>
... output omitted ...

You may have noticed a lot of "IMPORTANT" news items. This is a great system provided by Gentoo repositories for communicating changes, however as this is your first time pulling them down, it will be showing things even years old that don't really apply to us. However, it's still worth taking a look! You can list all of the news items through eselect news list and read an individual item with eselect news read #.

For now, let's clear them so we can start fresh (unless you see something really scary in there from after this guide's last updated date at the top of this guide!).

(chroot) livecd / #eslect news read

Let's go ahead and update @world, this is useful because of all of that changes that we made to our /etc/portage/make.conf file earlier.

(chroot) livecd / #emerge --ask --verbose --update --deep --newuse @world
... output omitted ...
Would you like to merge these packages? [Yes/No] <press Y and then ENTER>
... output omitted ...

This will take a little bit, but also be your first taste (aside from updating portage earlier) of using emerge. This is how we'll update our system in the future as well, so take note of those flags!

Our next step is configuring the system to our liking, the basics of any Gentoo installation. We're going to setup the localtime, our locale, and create ourself a user (because running as root is bad!)

Setting a Timezone

Let's start by picking a local timezone, for the author we'll use America/Los_Angeles, so replace that with whatever your timezone is.

(chroot) livecd / #ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime

Picking a Locale

Now we'll pick our locale, open the file up with your favorite editor (nano is the easiest for newcomers!).

(chroot) livecd / #nano -w /etc/locale.gen

Uncomment, or if not present replace, your locales. For the author, it would be:

FILE /etc/locale.gen
en_US ISO-8859-1
en_US.UTF-8 UTF-8

Then, make sure to run locale-gen to generate the required locales.

(chroot) livecd / #locale-gen
 * Generating 3 locales (this might take a while) with 8 jobs
 *  (1/3) Generating en_US.ISO-8859-1 ...                                                                              [ ok ]
 *  (3/3) Generating C.UTF-8 ...                                                                                       [ ok ]
 *  (2/3) Generating en_US.UTF-8 ...                                                                                   [ ok ]
 * Generation complete
 * Adding locales to archive ...

Now we'll need to pick our default locale, which we can do with eselect locale list.

(chroot) livecd / #eselect locale list
Available targets for the LANG variable:
  [1]   C
  [2]   C.utf8
  [3]   POSIX
  [4]   en_US
  [5]   en_US.iso88591
  [6]   en_US.utf8
  [7]   C.UTF8 *
  [ ]   (free form)

Pick the locale option that is a UTF-8 option. So, for the author it is en_US.utf8.

(chroot) livecd / #eselect locale set 6
Setting LANG to en_US.utf8 ...
Run ". /etc/profile" to update the variable in your shell.

As it suggests, we'll need to resource /etc/profile for it to take effect.

(chroot) livecd / #env-update && . /etc/profile && export PS1="(chroot) $PS1"
>>> Regenerating /etc/ld.so.cache...

Now we're ready to create a user!

Creating a User

Let's go ahead and create a user for us to use, in the future. Decide on a username and use in the <username> fields in the command below.

(chroot) livecd / #useradd <username>
Creating mailbox file: No such file or directory
Note
If you see the below:
Creating mailbox file: No such file or directory
Feel free to ignore it, we don't need to worry about mailbox support right now.

Now we'll set a password for our user and then the root user as well, in case of any issues when we reboot later it's helpful to have that set.

(chroot) livecd / #passwd <username>
(chroot) livecd / #passwd # Root user!
Enter new password:
Re-type new password:
passwd: password updated successfully
# Root!
Enter new password:
Re-type new password:
passwd: password updated successfully

That's it for the basics! Now we can get started on building our own Kernel.

Building the Kernel

Currently, we'll build everything as normal through asahi-gentoosupport and then use the asahi-kernel package. To do so, we'll need to emerge the git package.

(chroot) livecd / #emerge --ask --verbose dev-vcs/git
... output omitted ...
Would you like to merge these packages? [Yes/No] y
... output omitted ...

Let's clone the repository again, since it's long gone from our Arch partition from earlier

(chroot) livecd / #cd asahi-gentoosupport
Cloning into 'asahi-gentoosupport'...
remote: Enumerating objects: 267, done.
remote: Counting objects: 100% (40/40), done.
remote: Compressing objects: 100% (31/31), done.
remote: Total 267 (delta 16), reused 28 (delta 9), pack-reused 227
Receiving objects: 100% (267/267), 89.78 KiB | 1.50 MiB/s, done.
Resolving deltas: 100% (144/144), done.

Now we can run the install.sh script to take care of installing a dist-kernel and other required packages through the sys-apps/asahi-meta package.

(chroot) livecd /asahi-gentoosupport #./install.sh
This script automates the setup and configuration of Apple Silicon                                                                                                specific tooling for Gentoo Linux. Please mount the ESP to /boot.                                                                                                                                                                                                                                                                   NOTE: This script will install linux-firmware automatically. It is not                                                                                            possible to run these machines properly without binary blobs. Please make                                                                                         sure you understand this, and agree to the linux-fw-redistributable and                                                                                           no-source-code licenses before continuing.                                                                                                                                                                                                                                                                                          Press Enter to continue... <ENTER>

Installing the Asahi Overlay. For more information, visit
https://github.com/chadmed/asahi-overlay/                                                                                                                                                                                                                                                                                           

>>> Verifying ebuild manifests                                                                                                                                    >>> Emerging (1 of 1) app-eselect/eselect-repository-14::gentoo                                                                                                   >>> Installing (1 of 1) app-eselect/eselect-repository-14::gentoo                                                                                                 >>> Recording app-eselect/eselect-repository in "world" favorites file...                                                                                         >>> Completed (1 of 1) app-eselect/eselect-repository-14::gentoo                                                                                                  --2024-05-09 07:26:49--  https://qa-reports.gentoo.org/output/repos/repositories.xml                                                                              ... output snipped ...                                                                                                                                                                                                                              Adding asahi to /etc/portage/repos.conf/eselect-repo.conf ...                                                                                                     1 repositories enabled                                                                                                                                            >>> Syncing repository 'asahi' into '/var/db/repos/asahi'...
/usr/bin/git clone --depth 1 https://github.com/gentoo-mirror/asahi.git .  
... output snipped ...  
=== Sync completed for asahi                                                                                                                                                                                                                                                                                                        ... output snipped ...                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           * IMPORTANT: 13 news items need reading for repository 'asahi'.                                                                                                   * Use eselect news read to view new items.

Action: sync for repo: asahi, returned code = 0

The Asahi overlay has been installed.                                                                                                                             We will now install the Asahi metapackage with some sane                                                                                                          defaults to get you started. This step will:                                                                                                                        
  * Mask media-libs/mesa::gentoo                                                                                                                                    
  * Emerge rust-bin (you can switch to the compiled rust later)                                                                                                     
  * Create /etc/portage/package.use/asahi and set:                                                                                                                          
      sys-apps/asahi-meta kernel -sources -audio                                                                                                                  
    If you are planning to use this machine as a desktop, please                                                                                                      
    delete '-audio' from this file and emerge -1 asahi-meta BEFORE                                                                                                    
    emerging your DE/WM.                                                                                                                                            
  * emerge the Asahi metapackage                                                                                                                                    
  * Unpack the Asahi firmware                                                                                                                                       
  * Update m1n1 and U-Boot                                                                                                                                        Press Enter to continue... <press ENTER>

.. emerge output snipped ...

Note: I had to run emerge -1 --autounmask-write sys-apps/asahi-meta and then dispatch-conf to get packages to actually install. Afterwards, you can re-run install.sh. This may not be required, but if you see a warning about "USE changes required", you'll need to do the same.

We have a Kernel now! Next, we'll configure dracut to build a crypto friendly initramfs and install iwd so we can reach the internet when we reboot.

Setting up the initramfs

In order to setup our initramfs, we'll need to grab the UUID of our btrfs partition to use as the root. Lets use blkid to get it.

(chroot) livecd /asahi-gentoosupport #blkid $(blkid --label root) # We want "UUID", we will refer to as "btrfs UUID"
/dev/mapper/luks: LABEL="root" UUID="86a9b8cd-e939-490c-9203-05ebb07c0217" UUID_SUB="c4a82413-e29e-429f-8e18-62e0439c3e22" BLOCK_SIZE="16384" TYPE="btrfs"

Let's configure dracut to support luks, we'll do so by creating /etc/dracut.conf.d/luks.conf

(chroot) livecd /asahi-gentoosupport #mkdir --parents /etc/dracut.conf.d/
(chroot) livecd /asahi-gentoosupport #nano -w /etc/dracut.conf.d/luks.conf
FILE /etc/dracut.conf.d/luks.conf
# Note: GRUB will override kernel_cmdline, so do not set it!
kernel_cmdline=""
add_dracutmodules+=" btrfs systemd crypt dm "
install_items+=" /sbin/cryptsetup /bin/grep "
# Change this if you didn't use btrfs.
filesystems+=" btrfs "

Next we can update /etc/default/grub to contain the required kernel parameters.

(chroot) livecd /asahi-gentoosupport #nano -w /etc/default/grub
FILE /etc/default/grub
# rd.auto automatically discovers the encrypted LUKS partition
GRUB_CMDLINE_LINUX="rd.auto=1 rd.luks.allow-discards"
GRUB_DEVICE_UUID="<btrfs UUID>"

Make sure to update /boot/grub/grub.cfg by running the following:

(chroot) livecd /asahi-gentoosupport #grub-mkconfig -o /boot/grub/grub.cfg

You can automate this step in the future with the grub USE flag on Installkernel

Next we'll update /etc/fstab. To do so, we'll need the UUID of the /boot partition. We'll get it with blkid again.

(chroot) livecd /asahi-gentoosupport #blkid $(blkid --label "EFI - GENTO") # We want "UUID", we will refer to as "boot UUID"
/dev/nvme0n1p4: LABEL_FATBOOT="EFI - GENTO" LABEL="EFI - GENTO" UUID="1C83-E48B" BLOCK_SIZE="4096" TYPE="vfat" PARTUUID="4ad6d68f-be3a-4dad-bb73-e250c08d1234"
(chroot) livecd /asahi-gentoosupport #nano -w /etc/fstab
FILE /etc/fstab
UUID=<btrfs UUID>         /               btrfs           rw,defaults       0 1
UUID=<boot UUID>          /boot           vfat            rw,defaults       0 2

In order to build the initramfs, we'll need to install a few things. Namely cryptsetup, grep and btrfs-progs. We will also install NetworkManager as well as sudo so we don't need to later.

(chroot) livecd /asahi-gentoosupport #emerge --ask --verbose net-misc/networkmanager sys-fs/cryptsetup sys-fs/btrfs-progs sys-apps/grep app-admin/sudo

Finally, we need to update systemd to support cryptsetup, which will be used by dracut for unlocking.

(chroot) livecd /asahi-gentoosupport #nano -w /etc/portage/package.use/fde
FILE /etc/portage/package.use/fde
sys-apps/systemd cryptsetup

Now we can build the initramfs, normally this would be just dracut --force, but for now we also need to specify the kernel version.

(chroot) livecd /asahi-gentoosupport #dracut --kver $(make -C /usr/src/linux -s kernelrelease) --force
... a lot of "dracut module XYZ will not be installed ...
dracut: *** Including module: systemd ***
dracut: *** Including module: systemd-initrd ***
dracut: *** Including module: i18n ***
dracut: *** Including module: btrfs ***
dracut: *** Including module: crypt ***
dracut: *** Including module: dm ***
dracut: Skipping udev rule: 64-device-mapper.rules
dracut: Skipping udev rule: 60-persistent-storage-dm.rules
dracut: Skipping udev rule: 55-dm.rules
dracut: *** Including module: kernel-modules ***
dracut: *** Including module: kernel-modules-extra ***
dracut: *** Including module: nvdimm ***
dracut: *** Including module: qemu ***
dracut: *** Including module: qemu-net ***
dracut: *** Including module: lunmask ***
dracut: *** Including module: resume ***
dracut: *** Including module: rootfs-block ***
dracut: *** Including module: terminfo ***
dracut: *** Including module: udev-rules ***
dracut: Skipping udev rule: 40-redhat.rules
dracut: Skipping udev rule: 50-firmware.rules
dracut: Skipping udev rule: 50-udev.rules
dracut: Skipping udev rule: 91-permissions.rules
dracut: Skipping udev rule: 80-drivers-modprobe.rules
dracut: *** Including module: virtiofs ***
dracut: *** Including module: dracut-systemd ***
dracut: *** Including module: usrmount ***
dracut: *** Including module: asahi-firmware ***
dracut: *** Including module: base ***
dracut: *** Including module: fs-lib ***
dracut: *** Including module: shutdown ***
dracut: *** Including modules done ***
dracut: *** Installing kernel module dependencies ***
dracut: *** Installing kernel module dependencies done ***
dracut: *** Resolving executable dependencies ***
dracut: *** Resolving executable dependencies done ***
dracut: *** Hardlinking files ***
dracut: Mode:                     real
dracut: Method:                   sha256
dracut: Files:                    1263
dracut: Linked:                   4 files
dracut: Compared:                 0 xattrs
dracut: Compared:                 407 files
dracut: Saved:                    6.9 KiB
dracut: Duration:                 0.007486 seconds
dracut: *** Hardlinking files done ***
dracut: *** Store current command line parameters ***
dracut: *** Stripping files ***
dracut: *** Stripping files done ***
dracut: *** Creating image file '/boot/initramfs-6.2.0-asahi-12-ARCH.img' ***
dracut: dracut: using auto-determined compression method 'gzip'
dracut: *** Creating initramfs image file '/boot/initramfs-6.2.0-asahi-12-ARCH.img' done ***

We now have an initramfs that supports running decrypting our root device. At this point we can now reboot through the command reboot, or do some of the optional tasks(s) below.

(Optional) Setup Sudo

Open up /etc/sudoers through the command visudo and uncomment one of the optional rules for users in the group wheel.

(chroot) livecd /asahi-gentoosupport #visudo

Add your user to the wheel group.

(chroot) livecd /asahi-gentoosupport #usermod -aG wheel <your user>

Post-Install Steps

At this point you should have rebooted, or if not go ahead and do it now. If all went well, you should be looking at a prompt to unlock your device. Go ahead and type your password to do so. If you don't, or have some other issue, check out the "Troubleshooting" section of this guide.

At this point you can continue to customize your system as if it were a normal Gentoo machine. Users may want to look at the Handbook for next steps (ignore that it is amd64) Handbook:AMD64/Installation/Finalizing, you also may want to reference the standard Asahi Gentoo install guide that this is built on, namely the Maintenance section.

Troubleshooting

"Hangs" then eventually boots into Emergency Mode

There's something wrong with your dracut or grub cmdline configuration. You can escape the emergency shell by doing the following:

root #cryptsetup luksOpen /dev/nvme0n1p# luks
root #exit

Make sure to replace # with your partition for LUKS, you can use blkid to fetch it if needed.

Wi-Fi Firmware isn't Working

The /lib/firmware/vendor directory needs to exist for firmware setup to function (it silently fails right now).

root #mkdir /lib/firmware/vendor
root #exit