My journey with Linux I think is a common one. For ten years, my installation has evolved across 3 machines, 3 distros, and 4 hard drives. But this road isn't easy, as most users know. I grew tired of jumping between eight different ways to do any given thing, where each option is only 80% implemented. On top of that, all options seem either ignorant of one another, or at war with one another.
This led me to adopt a Macbook as my primary machine around 2019, with a hope that maybe this is "Unix on the desktop, done right". But now I'm running into more and more issues with their walled garden. To name a few, macOS lacks thread affinity support, gdb support, and full support for valgrind/helgrind.
So do I choose something that "just works", but doesn't let me do that 10% of things I want to do? Or do I choose something that's going to break 10% of the time, but will always let me do the things that I want to do?
This dilemma has caused many users to swing back and forth between Macbooks and Linux, and I think my latest pendulum swing has gotten me fed up with the proprietary system that's making macOS harder and harder to use.
Maybe there's a third option where I can keep either OS available. Instead of fully swinging back to my old "everything in my life is Linux" ways, can I reach for my Linux box when working on an OS project, while still having my Macbook handy for music production and running proprietary software? I don't know, but I'll be exploring this approach in 2021. In fact, I've already updated my dotfiles repository to work across both operating systems!
While the rest of this post documents my latest Arch Linux installation, I've found some peace for now in accepting that it won't be perfect. Operating systems, hardware, and their ecosystems will continue to evolve, and we'll need to adapt if we want to keep up. Also, there is hope, with promising projects like Asahi Linux aiming to deliver a polished Linux experience. I'm hoping that one day this will be a problem of the past that we'll look back on with wistful smiles.
But until then, it's becoming clear that the only constant we can optimize for is change. So let's get to it!
I find myself performing an installation every few years as I haul my data across various machines and devices. Luckily Arch makes this very simple, as long as we stay committed to understanding the Linux ecosystem.
This post is intended for anyone (especially my future self) who wants to do the following:
systemd-bootbootloader, and configuring the bootloader
I'll be documenting all of the steps of my basic installation, but I won't be elaborating too much on any given step. The Arch Linux installation guide is a great reference for further clarification.
I'm assuming that we already have the following:
I recommend reading the Arch docs for the ThinkPad X1 Carbon.
While it mentions that the Legacy BIOS route is easier than UEFI, I've found that using the
systemd-boot bootloader over UEFI to be simpler and more forward-thinking than Legacy GRUB (or other MBR bootloaders). GRUB can be especially difficult to configure correctly when things go wrong.
And here's docs on the X1 Carbon gen 3
I wasn't able to confirm the generation from the CLI, but another way to check the device's version is by checking at model number sticker on the bottom of the laptop. On gen 3, it starts with
There are 2 settings that we'll have to ensure are correctly configured in our BIOS:
Why are we disabling Secure Boot?
The Arch Linux installation images do not support Secure Boot, although we can configure our system to use Secure Boot after installation, if desired.
This is how I'm partitioning my 500GB disk:
cfdisk for creating and editing partitions. It's like
fdisk, but with a curses interface, which is much easier to use.
If needed, we can format each partition on the file system like so:
mkfs.vfat -F 32 /dev/sda1 mkfs.ext4 /dev/sda2 mkswap /dev/sda3 mkfs.ext4 /dev/sda4
warning - formatting a partition will delete all of the data on it!
To boot into UEFI, I had to migrate my partitioning scheme from MBP to the newer GPT. You can check your partitioning scheme with
Sometimes we need to resize our partitions. This came up for me when I moved my partitioning scheme from MBR to GPT. Since GPT requires a small amount of space at the end of the disk, I had to shrink the last partition on my disk (
/dev/sda4) to make space.
Although GPT only needs ~33 blocks, I gave it a couple GB's just to be safe :)
resize2fs /dev/sda4 396GB
/dev/sda4 partition originally extended to the end of the disk, and was ~400GB.
Be sure to run
efsck -f <device> (eg:
efsck -f /dev/sda4) after shrinking the file system, to ensure everything is ok.
After shrinking the file system, we can then shrink the partition using
Now that our partitions are correctly formatted and sized, let's mount them so that we can install Arch!
This is how I do it:
# mount root: mount /dev/sda2 /mnt # mount boot: mount /dev/sda1 /mnt/boot # mount home: mount /dev/sda4 /mnt/home # enable swap swapon /dev/sda3
Make sure that you're connected to the internet for this part, since the installation process needs to retrieve packages from a remote repository. The live boot image that I used (
2021.02.01) came with a neat tool
iwctl which makes it pretty easy to connnect to a wifi network:
iwctl --passphrase <passphrase> station <device> connect <SSID>
Now we can run our installation script, which will add the kernel image into our
pacstrap /mnt base linux linux-firmware
We also have to configure our
fstab. Unless we've added, removed, or reformatted any partitions, we won't need to make any updates. But it's always good to check. I usually do the following:
# concat the new fstab config into our fstab file: genfstab -U /mnt >> /mnt/etc/fstab # verify the it looks correct, comparing the new/old version: vim /mnt/etc/fstab
This is how my fstab looks:
# Static information about the filesystems. # See fstab(5) for details. # <file system> <dir> <type> <options> <dump> <pass> # /dev/sda2 UUID=12345678-1234-1234-1234-1234567890ab / ext4 rw,relatime 0 1 # /dev/sda1 UUID=1234-5678 /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2 # /dev/sda4 UUID=22345678-1234-1234-1234-1234567890ab /home ext4 rw,relatime 0 2 # /dev/sda3 UUID=32345678-1234-1234-1234-1234567890ab none swap defaults 0 0
Now that fstab is configured, we can chroot into the root:
We should also check if there's a
initramfs-linux.img image located in the
/boot directory. If not, we can regenerate it with:
We'll also want to install intel microcode with
pacman -Syu intel-ucode.
We should now have a
intel-ucode.img file in our
While GRUB is great, it's an old and bloated program. I've had trouble debugging GRUB in the past, so I switched to systemd-boot, which is a text only bootloader. It's basically an interface for the boot logic included in EFI.
systemd-boot, first verify the system is configured to boot in UEFI mode (which we configured earlier in our BIOS setting):
Now let's install our
We should now have a
Finally, to complete our bootloader config, we need to add our loader configuration, and a loader entry.
My loader configuration is saved under
/boot/loader/loader.conf, and looks like this:
default arch.conf timeout 4
I only have one loader entry, although we can always add more for multiple OS's. My loader entry is saved under
title Arch Linux linux /vmlinuz-linux initrd /intel-ucode.img initrd /initramfs-linux.img options root="LABEL=arch_os" rw
Note that the
root option is referencing the root partition by it's partition label. We can check the partition's label like so:
In my case, I set it to
sudo e2label /dev/sda2 arch_os
Now we're done! We should be ready to restart the system and have it boot successfully.
To recap, our
/boot directory should look like this:
❯ tree /boot /boot ├── EFI │ ├── BOOT │ │ └── BOOTX64.EFI │ ├── Linux │ └── systemd │ └── systemd-bootx64.efi ├── initramfs-linux.img ├── intel-ucode.img ├── loader │ ├── entries │ │ └── arch.conf │ ├── loader.conf │ └── random-seed └── vmlinuz-linux