Skip to content

Instantly share code, notes, and snippets.

@altercation
Last active June 6, 2024 15:13
Show Gist options
  • Save altercation/58d0dd8dc8aaf1cf4380197c64c97f34 to your computer and use it in GitHub Desktop.
Save altercation/58d0dd8dc8aaf1cf4380197c64c97f34 to your computer and use it in GitHub Desktop.
Bulletproof Arch - Minimal Clean Install
------------------------------
IMPORTANT NOTE:
Please see @craSH's update to this. He has updated and reformatted these working notes and his version is what I recommend you start with (as of 2021 or later).
-Ethan
@craSH fork & update (also listed in the forks on this gist above):
https://gist.github.com/craSH/21a6321d3dcd7f5b56ec8fe28bea1444#file-bulletproof_arch-md
------------------------------
These are working notes on the installation of Arch Linux. I've just completed this install on a notebook (Lenovo P50)
but the setup should work for most laptop/desktop configurations.
Some assumptions/notes:
1. This isn't a dual boot configuration. I can see some of the appeal and still work in Adobe from time to time, but given
the increasing complexity of EFI and the way Windows/MS manhandles the EFI partition during upgrades, I really would
recommend steering clear of dual boot. Just my two cents here.
2. We're encrypting with LUKS. I've used so-called "self encrypting drives" as well (and linux has multiple ways of dealing
with these keys and the encryption thereof). They are fast and as secure as you trust your UEFI bios manufacturer and
harddrive manufacturer. Honestly, not a bad solution and would eliminate the need for LUKS. You do need UEFI bios support for
these drives, though that's pretty common now. For me it feels a little too proprietery at this point and I don't trust that
there isn't a big ol' backdoor in the drive firmware.
3. We're avoiding LVM. This talk by Marc Merlins changed my views on a lot of things, including LVM:
Video: https://www.youtube.com/watch?v=6DplcPrQjvA
Slides: http://marc.merlins.org/linux/talks/2015/Btrfs-LCA2015/Btrfs.pdf
Besides the performance hit, there is just no need. The only benefit for us might be the swap situation, but you can do
either standard encrypted swap (as detailed herein) or encrypted-with-hibernate-support without LVM. LVM gets us nothing at
this point given that we'll be using BTRFS subvolumes as they were meant to be.
-----------------------------------------------------------------------------------------------------------
PREPARATION
-----------------------------------------------------------------------------------------------------------
BOOT ARCH USB
-----------------------------------------------------
Download and burn USB drive as per instructions on ArchLinux.org
PICK INSTALL DRIVE
-----------------------------------------------------
# lsblk
an aside:
If you don't already use `lsblk` a lot, you should. I love it. Here's a way to quickly list all your partitions along
with their partition labels, filesystem labels, mount points, and UUIDS/PARTUUIDS.
# lsblk -o +LABEL,PARTLABEL,UUID,PARTUUID
NOTE: in the following sections, DRIVEID might be "sda", for example, while PARTID might be "sda1". I used to just append
partition numbers to a $DRIVE variable in my scripts, but this is no longer safe with the advent of NVMe drives, which
enumerate using a different format.
WIPE DRIVE (can skip)
-----------------------------------------------------
This is a full, secure wipe of the drive. If you aren't worried about the NSA, APTs, your mom, whatever, then you can skip
this, but why not have some peace of mind and do it? Note that even though we're sourcing /dev/zero for the input, it's
scrambled on disk due to the use of LUKS.
# sgdisk --zap-all /dev/DRIVEID
# cryptsetup open --type plain /dev/DRIVEID container --key-file /dev/random
# dd if=/dev/zero of=/dev/mapper/container status=progress
# cryptsetup close container
PARTITION DRIVE
-----------------------------------------------------
# DRIVE=/dev/whatever
# MNT=/mnt
Create all partitions. See http://www.rodsbooks.com/efi-bootloaders/principles.html for an explanation of why 550MiB is a
minimum size for the EFI partition.
# sgdisk --clear \
--new=1:0:+550MiB --typecode=1:ef00 --change-name=1:EFI \
--new=2:0:+8GiB --typecode=2:8200 --change-name=2:cryptswap \
--new=3:0:0 --typecode=2:8200 --change-name=3:cryptsystem \
$DRIVE
ENCRYPT SYSTEM PARTITION
-----------------------------------------------------
Encrypt the main partition. Use a good passphrase. Then open the partition.
2021 UPDATE & WARNING!
https://www.man7.org/linux/man-pages/man8/cryptsetup.8.html --align-payload is apparently now a scary no-no! Thanks to @craSH for noting this. Don't make life easy for the NSA :)
ALSO 2021 Update: xts keysize minumum should be 512
# cryptsetup luksFormat --align-payload=8192 -s 256 -c aes-xts-plain64 /dev/disk/by-partlabel/cryptsystem
# cryptsetup open /dev/disk/by-partlabel/cryptsystem system
FORMAT EFI PARTITION
-----------------------------------------------------
EFI now needs to be formatted as FAT32, as per the standard.
# mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/EFI
CREATE BTRFS SUBVOLUMES
-----------------------------------------------------
Notes:
1. While it is possible to just create a single subvolume (the so-called "top level subvolume") and use that as root, we'd be
throwing away the real power of BTRFS. Our subvolume structure will in fact be this:
TOPLEVEL
|
|--root
|--home
`--snapshots
|
|--root_snapshot_datehere
|--root_snapshot_datehere
|--root_snapshot_datehere
|--home_snapshot_datehere
`--home_snapshot_datehere
The snapshots should all be made as read-only BTRFS snapshots. At any time we can boot into a shell where our root or home
isn't mounted and rename our "root" subvolume to something like "root_old" and then simply create a new rw snapshot from any
of the snapshots, naming it root and placing it under the top-level subvolume. This will be a perfect restore of the root
filesystem (sans /home, as we want to keep / and /home decoupled for snapshotting purposes).
Note that in time I may decide to make parts of /var or other branches of the filesystem separate subvolumes so that they are
not being snapshotted along with the rest of root. For example, any directory contain the bulk of my VM images.
cf https://btrfs.wiki.kernel.org/index.php/FAQ#Does_Btrfs_support_TRIM.2Fdiscard.3F
"-o discard" can have some negative consequences on performance on some SSDs or at least whether it adds worthwhile performance is up for debate depending on who you ask, and makes undeletion/recovery near impossible while being a security problem if you use dm-crypt underneath (see http://asalor.blogspot.com/2011/08/trim-dm-crypt-problems.html ), therefore it is not enabled by default. You are welcome to run your own benchmarks and post them here, with the caveat that they'll be very SSD firmware specific.
Top-level subvolume first:
# mkfs.btrfs --force --label system /dev/mapper/system
# o=defaults,x-mount.mkdir
# o_btrfs=$o,compress=lzo,ssd,noatime
Mount this temporarily so that we can create the subvolumes that will be our actual mounted volumes:
# mount -t btrfs LABEL=system $MOUNT
Subvolumes will be created, we'll unmount, then remount the subvolumes at the correct mountpoints. Specifically, this creates separate subvolumes for / (root) and /home for easier snapshot and rollback, along with a container subvolume for the snapshots themselves.
Create the subvolumes under the top-level subvolume:
# btrfs subvolume create $MOUNT/root
The following is either wrong or unnecessary? I think? I was using the ID before. Better to use the subvolume name. I should never be mounting without a subvolume name anyhow. So verdict is: unnecessary.
# btrfs subvolume set-default ${$(btrfs subvolume list $MOUNT)[(w)2]} $MOUNT
# btrfs subvolume create $MOUNT/home
# btrfs subvolume create $MOUNT/snapshots
Unmount everything…
# umount -R $MOUNT
Remount them at their correct locations
# mount -t btrfs -o subvol=root,$o_btrfs LABEL=system $MOUNT
# mount -t btrfs -o subvol=home,$o_btrfs LABEL=system $MOUNT/home
# mount -t btrfs -o subvol=snapshots,$o_btrfs LABEL=system $MOUNT/.snapshots
# NOTE: mkdir $MOUNT/boot is NOT needed since we are using the x-mount.mkdir mount option which will create the directory
# mount -o $o LABEL=EFI $MOUNT/boot/EFI
Open encrypted device for swap
# cryptsetup open --type plain --key-file /dev/urandom \
/dev/disk/by-partlabel/cryptswap swap
# mkswap -L swap /dev/mapper/swap
# swapon -L swap
@thepenguinthatwants
Copy link

Any way to include booting part?
Couldn't figure out how to get grub or refind work?

@Katkidnapped
Copy link

line 86, I noticed that both the swap and crypt partitions have the same typecode, or to say more accurately, the typecode for 2nd partition is repeated, and not mentioned for the third one?

@altercation
Copy link
Author

line 86, I noticed that both the swap and crypt partitions have the same typecode, or to say more accurately, the typecode for 2nd partition is repeated, and not mentioned for the third one?

Was probably an error but be warned this code is quite out of date now :) - there’s a link to a more current forked version above though I don’t know if that author has maintained his or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment