User:Altercation/Bullet Proof Arch Install
This page is a summary of the current process I follow when installing Arch on a new laptop or desktop. My process varies over time, but this serves as my "state of the art" best practice recommendations. I'm open to feedback and suggestions for improvements.
Objectives
The goals of my standard "bullet proof" Arch Linux installation are:
- Benefit from Arch's rolling release model while mitigating any risk of system corruption or data loss due to failed upgrades
- Minimize risk due to hardware failure or total system loss (e.g. theft or physical destruction)
- Make system rollbacks easy and procedural, using a standard setup and methodology for recovery of previous system (and user data) states
Why not the Arch Install instructions?
The Arch Linux installation instructions are an excellent, general starting point and you should read and understand them. That being said, they are designed to map to a very, very broad set of installation scenarios. I am interested in a very specific type of installation (daily use desktops and laptops in this article) and I have a strong set of opinions about the "right" or "best practice" way to set up my own working systems.
These instructions, then, are much more prescriptive and have strong suggestions or directions about how (and why) one should use a particular method during Arch Linux installation.
Key differences from the stock Arch install instructions
How these instructions differ from the standard Arch guidance:
- We are encrypting the entire system but not using LVM as is often recommended (see the encryption section below for details about why we are not using it).
- I use labels and avoid UUIDs where possible to make switching to an alternate recovery drive easier.
- I skip arch-chroot and simply boot the new system (not reboot, just boot) from within the install environment using systemd-nspawn(1) which enables the *ctl commands to work (and systemd services to be enabled properly without need for a system reboot)
- I use the various systemd *ctl commands (hostnamectl, timedatectl, localectl, etc.) to configure the system
- I use the systemd mkinitcpio hooks in lieu of the legacy hooks.
- I use BTRFS exclusively for root and home partitions for its backup capabilities.
- I recommend and use secure boot (but not with the Microsoft keys) to minimize risk due to the unavoidably unencrypted EFI partition.
Assumptions
These instructions presuppose the following:
- fairly new hardware (these instructions may work on older hardware, but there may be unusual issues that crop up... if you aren't comfortable handling those situations you should consider a more "traditional" Arch Linux install (e.g. using grub, LVM, ext4, etc.)
- UEFI support (BIOS system install is also possible with some modification of these instructions, but this has not yet been detailed here)
- probably an SSD.
- some familiarity with Arch, or at least some experience with Linux, will help
Prerequisites
You must have a recent copy of the Arch install USB. See Getting and installing Arch for general information and USB flash installation media for specific details on creating a USB Arch installation drive.
You should also have a reasonable amount of time in which to complete the installation. Novice users will want to budget a couple hours. Experienced users will know to budget a couple hours.
Preparation
Boot from USB Drive
Boot your system from your prepared Arch Linux USB drive. It is important that you boot in EFI mode, not legacy BIOS compatibility mode. See the UEFI article for more information about checking boot mode and ensuring you are booting using EFI.
Bring up the network
If you booted into a system with an ethernet cable plugged in, chances are you're up and running. If you need to use wireless instead, iwctl will more often than not work without trouble. If those don't work, see the Arch installation guide section on connecting to the internet.
Select Drive
I like to use the lsblk
command to bring up a quick list of the block devices on the system and identify existing partition structures and sizes, as well as mount points. If you don't already use it, I recommend lsblk
when you need information on any given drive or partition. It's useful for polling UUIDs as well. For example, the following command gives you a clearly formatted summary of all block devices, their partition labels, filesystem lables, UUIDs and partition UUIDS: lsblk -o +LABEL,PARTLABEL,UUID,PARTUUID
In any case, the plain command without options should be enough to identify the drive you will install to (for example /dev/sda
or /dev/nvme0n1
:
# lsblk
Wipe Drive Securely (optional)
While it is not necessary, given that this process will go through the trouble of encrypting the main system partition, it makes sense to do a secure wipe of the drive. This is more or less directly from Dm-crypt/Drive preparation#dm-crypt wipe on an empty disk or partition.
First, create a temporary encrypted container the full disk (sdX
) to be encrypted, e.g. using default encryption parameters and a random key via the --key-file /dev/{u}random
option (see also Random number generation):
# cryptsetup open --type plain /dev/sdXY container --key-file /dev/urandom
Second, check the container exists:
# fdisk -l
Disk /dev/mapper/container: XXXX MB, XXXXXXXXXX bytes ... Disk /dev/mapper/container does not contain a valid partition table
Wipe the container with zeros. A use of if=/dev/urandom
is not required as the encryption cipher itself generates randomness.
# dd if=/dev/zero of=/dev/mapper/container status=progress bs=1M
dd: writing to ‘/dev/mapper/container’: No space left on device
- Using dd with the
bs=
option, e.g.bs=1M
as above, is frequently used to increase disk throughput of the operation. - To perform a check of the operation, zero the partition before creating the wipe container. After the wipe command
blockdev --getsize64 /dev/mapper/container
can be used to get the exact container size as root. Now od can be used to spotcheck whether the wipe overwrote the zeroed sectors, e.g.od -j containersize - blocksize
to view the wipe completed to the end.
Finally, close the temporary container:
# cryptsetup close container
Partition & Format Drive
Understanding some basics about disks, partitions, and filesystems
Think of your drive like a big empty building, no rooms. This is your plain physical drive (either a spinning platter drive or an SSD). Next imagine that to make it useful, we divide the building into apartments. In our analogy the apartments are partitions of the drive.
Imagine also that there are a couple different standard methods of creating layout maps to the apartments. These plans are standardized so that the public services that have to access the building regularly (like the fire and police, for example) understand how to find the apartment entrances. In the world of partitioning, the equivalent is the "partition table scheme". The two common schemes are called "MBR" (Master Boot Record, older) and "GPT" (GUID Partition Table, newer). We will be using the new GPT scheme.
Finally, imagine that the apartments are just empty shells. The act of building walls and laying out the functional structure of the apartments is equivalent to formatting our disk partitions with a filesystem. And just as different layouts may be more or less efficient, or have other different functional characteristics, so to filesystems have different attributes that make them useful in different ways.
Our partition plans
We will take our physical drive and divide it into three partitions. These partitions each serve a distinct purpose. All but the first and smallest, the EFI partition, will be encrypted. For security, if your system supports Secure Boot, you may choose to cryptographically sign the data stored on the EFI partition so that any tampering will be evident, despite the lack of encryption on that partition.
We will not be using LVM. You read a lot about LUKS and LVM and it all gets a bit complicated (LVM on LUKS, LUKS on LVM, etc.). LVM is a "logical volume manager" and abstracts physical devices (drives) into virtual devices, for easier management. It's a good idea but we will be using btrfs to effectively achieve the same results and really don't need the overhead of LVM.
Partition Summary
- 1: EFI - The UEFI 'bios" will look for this FAT32 formatted partition and either locate a default bootloader or will locate a specific EFI boot entry on it. This partition is by necessity not encrypted (unless the drive it is on has been encrypted as a "self encrypting drive")
- 2: Swap - Used by Linux to swap out pages of memory from RAM to disk. Despite debate in this area, it is advisable to have at least some swap space, even it you are not planning on using hibernation on your machine. The Arch wiki is unfortunately rather too brief in its own swap article so I recommend the Fedora documentation on swap for a good overview on determining the right swap partition size.
- 3: System - This will hold our root and home data. It will be formatted as BTRFS and will use subvolumes to manage snapshots of the current root and home contents.
Visual overview of our partitions, filesystems, and contents
This is a visual summary of our partions (inc. size information), encryption, filesystems, and a summary of the contents of each container.
Partition 1 (EFI)
550MiB+
|
Partition 2 (Swap)
w/ Hibernate: Equal RAM, w/o Hibernate: min 8GB
|
Partition 3 (System)
Remaining Space
|
Partition Drive
There are many utilities available for Partitioning. Because we are using Arch Linux and the command line doesn't hurt us (it makes us stronger) we will be using pure, non-interactive command line tools for this. Specifically, we will be using the utility sgdisk from the gptfdisk package. The fdisk utility now also supports GPT partitioned drives, so it would be an alternative. sgdisk is available by default on the standard Arch install iso that you use to make your bootable USB drive.
First, select the drive you will install to. Make sure you have selected the correct drive!. Again, a quick lsblk
will work here.
# DRIVE=/dev/DRIVEID
(replace /dev/DRIVEID with the correct value, for example /dev/sda, /dev/nvme0n1, etc.)
If you didn't securely wipe the drive already, it's worth "zapping" it using sgdisk to remove any lingering legacy partition information. If you already wiped the drive you can skip this command (though it won't hurt to run it again).
# sgdisk --zap-all $DRIVE
The following command will then create all three partitions in one go. It will also effectively erase the selected drive!
# 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=3:8300 --change-name=3:cryptsystem \ $DRIVE
It is worth noting that the "--change-name" values are, in this case, creating GPT "partition labels". You can subsequently see these by using the lsblk -o +PARTLABEL
command. It is good to use "EFI" for the efi partition. I am not aware of UEFI implementations that actively use the label for identification of the EFI partition, but it is possible that some do (UEFI bios implementations are not always consistent or to spec). The other two names are entirely "arbitrary". There is nothing special about calling them cryptswap and cryptsystem; they are simply good, clear names that remind us of the purpose of this partition and what it contains (for example, "cryptswap" suggests "this partition is for swap, and is encrypted").
One final note about partition labels: we want them to be unique on your system. If for some reason there is already a GPT partition with the name EFI on another drive on your system, either change that partition name or use something besides "EFI" to avoid a namespace collision.
Note also, that the backslashes at the end of each line can be omitted if you are writing the command on one long line instead. Those simply allow the splitting of a single command onto multiple lines.
Format EFI Partition
Next up: format the first (EFI) partition using the (required) FAT32 filesystem.
# mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/EFI
Note that we here make use of the partition label we just assigned. I prefer doing this since it simplifies scripts significantly for me and makes them, in my opinion, more readable.
Encrypt System Partition
Encrypt the main partition. Use a good passphrase. Note that the "--align-payload" value has been used as per this suggestion/explanation on the dm-crypt mailing list.
Note also that I selected the encryption algorithm and key size using cryptsetup benchmark. See the Dm-crypt/Device_encryption article for more details.
# cryptsetup luksFormat --align-payload=8192 -s 256 -c aes-xts-plain64 /dev/disk/by-partlabel/cryptsystem
After creating the encrypted container, open it. Again, note the use of the partition label to identify the drive. Additionally, note that once we open this device we are giving it a name of "system." Thus "cryptsystem" is the encrypted system partition, while "system" is the name we are using once it has been opened in an unencrypted state. These names are arbitrary (Linux doesn't care what we use) but they help us keep things organized during this process.
# cryptsetup open /dev/disk/by-partlabel/cryptsystem system
Bring Up Encrypted Swap
Finally we create encrypted swap. In this example we are not enabling hibernation. I will provide information on how to enable hibernation separately. Again, using partition labels to identify the partition and going from "cryptswap" to just "swap".
We are not using LUKS here (which effectively makes dm-crypt easier to use). We're just using plain dm-crypt to encrypt the swap partition using a random key.
# cryptsetup open --type plain --key-file /dev/urandom /dev/disk/by-partlabel/cryptswap swap # mkswap -L swap /dev/mapper/swap # swapon -L swap
Create and mount BTRFS subvolumes
Now on to the main attraction: creating our BTRFS subvolume structure. While BTRFS can be set up like any other filesystem (single command, just use the created file system directly), we're going to use the power of BTRFS to enable snapshotting our system state efficiently and rollbacks as necessary.
First we create a top-level BTRFS subvolume. Note that the top-level entity in BTRFS nomenclature is still referred to as a subvolume, despite being at the top-level.
We will create and mount this subvolume, create some new subvolumes inside it, and then switch to those subvolumes as our proper, mounted filesystems. Doing this will enable us to treat our root filesystem as a snapshotable object.
Top-level subvolume creation.
# mkfs.btrfs --label system /dev/mapper/system
Temporarily mount our top-level volume for further subvolume creation. Note that the variable 'o' in this case is our default set of options for any given filesystem mount, while "o_btrfs" are those plus some options specific to btrfs. The default option "x-mount.mkdir" is a neat trick that allows us to skip the creation of directories for mountpoints (they will be created automatically). We assume /mnt as the standard mount point, as in a normal Arch Linux installation.
# o=defaults,x-mount.mkdir # o_btrfs=$o,compress=lzo,ssd,noatime
Note the use of our filesystem label to mount our subvolume. This is distinct from the partition labels used earlier. See the Arch wiki article on Persistent_block_device_naming for more information.
# mount -t btrfs LABEL=system /mnt
Now we create the subvolumes which will actually be mounted in our running system:
# btrfs subvolume create /mnt/@root # btrfs subvolume create /mnt/@home # btrfs subvolume create /mnt/@snapshots
Then we unmount everything...
# umount -R /mnt
And remount just the subvolumes under our top-level subvolume (which remains unmounted unless we need to do "surgery" and rollback to a previous system system):
# mount -t btrfs -o subvol=@root,$o_btrfs LABEL=system /mnt
Before mounting the home and snapshots subvolumes, let's walk through that command so we understand what it's doing:
The 'mount -t btrfs' just specifies that our filesystem is of type BTRFS. This is often not necessary since mount will attempt to identify the filesystem type, but being explicit is often the best strategy with command line utilities, so we identify the type here.
We use our previously defined mount options with the $o_btrfs variable and add the additional option "subvol=@root" (separating it from our other defaults with a comma, of course). The next part of the command is "LABEL=system". Combined this reads as "mount the filesystem with the 'system' label, and use the 'root' subvolume within that".
Finally, all this gets mounted at our install root, which in this case is "/mnt".
Now let's pick back up and mount our home and snapshots subvolumes. Note that while the subvolume name is "@snapshots", we will mount it at ".snapshots" (note dot prefix for the mount point). This will keep our root directory listing clean but will still make it available at a reasonable mount location.
# mount -t btrfs -o subvol=@home,$o_btrfs LABEL=system /mnt/home # mount -t btrfs -o subvol=@snapshots,$o_btrfs LABEL=system /mnt/.snapshots
It it worth noting that in each case we are telling mount to use the same filesystem, namely the one labeled "system". However in each case we are also telling it to look for a different subvolume in that filesystem (via the "subvol=" option).
With this done, we can move on to installing the actual system.
Mount EFI partition
First create the folder /mnt/boot
# mkdir /mnt/boot
then mount the partition
# mount LABEL=EFI /mnt/boot
Installation of Base Arch Linux System
We are currently running off the Arch installer root filesystem. We will first use the 'pacstrap' utility to start our installation and then we will boot into our new minimal system using systemd-nspawn.
Install base package group
# pacstrap /mnt base linux linux-firmware
fstab Generation and Modification
Create an fstab filesystem table file, using labels (-L) to identify the filesystems.
# genfstab -L -p /mnt >> /mnt/etc/fstab
I prefer to use labels as this makes the system more portable to a backup drive. You should end up with something that looks pretty close to this:
# cat /mnt/etc/fstab
# /dev/mapper/system UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LABEL=system / btrfs rw,noatime,compress=lzo,ssd,space_cache,subvolid=257,subvol=/root,subvol=root 0 0 # /dev/mapper/system UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LABEL=system /home btrfs rw,noatime,compress=lzo,ssd,space_cache,subvolid=258,subvol=/home,subvol=home 0 0 # /dev/mapper/system UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LABEL=system /.snapshots btrfs rw,noatime,compress=lzo,ssd,space_cache,subvolid=259,subvol=/snapshots,subvol=snapshots 0 0 # /dev/nvme0n1p1 UUID=xxxx-xxxx LABEL=EFI /boot/EFI vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2 # /dev/mapper/swap UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LABEL=swap none swap defaults 0 0
There is one problem, however. Swap will not remount this way (the plain dm-crypt partition with a random key will not have a label when it is recreated on reboot). You will have to change that line from this:
LABEL=swap none swap defaults 0 0
to this:
/dev/mapper/cryptswap none swap sw 0 0
This will ensure that the mapped device will opened as swap successfully. The other lines may remain unchanged.
(NOTE by maximevince: /dev/mapper/swap should probably be used in the aboved fstab, instead of /dev/mapper/cryptswap)
Use sed
instead
As a (scriptable) alternative to the manual editing of your /etc/fstab
you could use sed(1) to edit the file in place:
# sed -i s+LABEL=swap+/dev/mapper/swap+ /mnt/etc/fstab
in /etc/crypttab we must add the part to mount at boot, so just add :
cryptswap /dev/disk/by-partlabel/cryptswap /dev/urandom swap,offset=2048,cipher=aes-xts-plain64,size=256
Boot into new system
# systemd-nspawn -bD /mnt
This will boot your new base Arch Linux system. After the standard boot messages scroll by you will be presented with a login (enter root
and hit enter to login).
securetty
TTY device whitelist. Add pts/0
through pts/9
to the container's version of the file (/mnt/etc/securetty
) and retry. See FS#45903 for details.Generate and set locale
Next, edit and uncomment your desired locale(s) from /etc/locale.gen
. We use vi
in the example below, but you could use a simpler editor such as nano
if you wish.
vi /etc/locale.gen
... #en_PH.UTF-8 UTF-8 #en_PH ISO-8859-1 #en_SG.UTF-8 UTF-8 #en_SG ISO-8859-1 #en_US.UTF-8 UTF-8 #en_US ISO-8859-1 #en_ZA.UTF-8 UTF-8 #en_ZA ISO-8859-1 #en_ZM UTF-8 ...
Changing it to (for en_US.UTF-8 as a locale in this example):
... #en_PH.UTF-8 UTF-8 #en_PH ISO-8859-1 #en_SG.UTF-8 UTF-8 #en_SG ISO-8859-1 en_US.UTF-8 UTF-8 #en_US ISO-8859-1 #en_ZA.UTF-8 UTF-8 #en_ZA ISO-8859-1 #en_ZM UTF-8 ...
Alternately one could simply append a known value to the /etc/locale.gen
file:
# echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
After either method, one runs the locale-gen
command to generate the locale files:
# locale-gen
Finally we use systemd-firstboot(1) or localectl(1) to set the system locale. Each of these effectively does the same thing which is to simply write to /etc/locale.conf
(which can simply be edited directly as per standard Arch install instructions).
With systemd-firstboot
systemd-firstboot(1) will prompt us for selection from our generated locales. It will only work if there is no assigned system locale. If you wish to make changes afterward you can use localectl(1)
# systemd-firstboot --prompt-locale
With localectl
This is an alternate to using systemd-firstboot --prompt-locale
. It may also be used subsequent to that command if further changes to the locale are desired.
If you need a reminder of which locales have been installed (during this install or later during system changes), use localectl list-locales
:
# localectl list-locales
en_US.UTF-8
We then use localectl set-locale
:
# localectl set-locale LANG=en_US.UTF-8
Time and Date
Unless you have a reason not to, we'll turn on NTP synchronization.
# timedatectl set-ntp 1
Then list timezones and pick one
# timedatectl list-timezones
... America/Kentucky/Louisville America/Kentucky/Monticello America/Kralendijk America/La_Paz America/Lima America/Los_Angeles America/Lower_Princes America/Maceio America/Managua America/Manaus America/Marigot America/Martinique America/Matamoros ...
# timedatectl set-timezone America/Los_Angeles
Set hostname
# hostnamectl set-hostname myhostname
See the man page for hostnamectl(1) for other attributes that can be set. You might also add the hostname to hosts(5):
/etc/hosts
127.0.0.1 localhost.localdomain localhost ::1 localhost.localdomain localhost 127.0.1.1 myhostname.localdomain myhostname
Use echo
for a scriptable solution:
# echo "127.0.1.1 myhostname.localdomain myhostname" >> /etc/hosts
Network configuration
Configure the network for the newly installed environment: see Network configuration.
For Wireless configuration, install the iw, wpa_supplicant, and dialog packages, as well as needed firmware packages.
Base Package Installation
We've already included the base group which is, strictly speaking, all you need to boot a minimal Arch Linux system. At this stage, however, we can install some useful utilities (and Xorg or Wayland, etc.).
# pacman -Syu linux-zen base-devel btrfs-progs iw gptfdisk zsh vim terminus-font
Initramfs
Creating a new initramfs is usually not required, because mkinitcpio was run on installation of the linux package with pacstrap. However we'll need to make some changes to the hooks used on our system. Additionally, I switched over to using the systemd hooks in mkinitcpio, so that is largely what you'll see in my example below.
Edit your {ic|/etc/mkinitcpio.conf}} file and change the line with HOOKS to:
HOOKS=(base systemd sd-vconsole modconf keyboard block filesystems btrfs sd-encrypt fsck)
Finally, recreate the initramfs image:
# mkinitcpio -p linux
Bootloader
ReFind Installation / UEFI
Install ReFind with
# pacman -S refind-efi
Then run the command
# refind-install --usedefault /dev/<your_efi_drive> --alldrivers
or if the disk is not detected because you booted on the new system (or other reasons), just refind-install witout the --usedefault, refind will find the boot mountpoint
# refind-install
--alldrivers
is a safe option if you Dual Boot, have often boot from USB Sticks and so on. But it's not recommended by the ReFind author - see ReFind - Using EFI Driver for source and alternativesNow spin up your favourite text editor and edit /boot/EFI/refind/refind.conf
First move the existent one:
# cd /boot/EFI/refind/ && mv refind.conf refind.bak
And create a new refind.conf:
# touch refind.conf && vim refind.conf
# refind.conf
timeout 20 # Timeout how long ReFind wait for user input #include themes/rEFInd- # For theming ReFind uncomment this and fill in the right location of your theme use_graphics_for windows # Specify the simpler "mac-style" behaviour also_scan_dirs +,@/ # Search for boot loaders in the specified directory
Edit the refind_linux.conf file located in /boot/
- focus on the first line:
# /boot/refind_linux.conf
"Boot with standard options" "rd.luks.name=*FILL IN UUID FROM PARTITION*=cryptsystem root=UUID=*UUID FROM encrypted root subvolume* rootflags=subvol=@root initrd=/intel-ucode.img initrd=/initramfs-linux-zen.img" ...
# btrfs filesystem show system
and the part UUID with:
# lsblk -fs
initrd=/intel-ucode.img
if you don't have any Intel Hardware in your computer or you didn't install the Intel Microcode Updates.Root password
Set the root password:
# passwd
Leave the systemd-nspawn environment
Issue a poweroff to exit the nspawned environment:
# poweroff
This will return you the Arch installer environment where you can wrap up.
Legacy boot loader
If your system is not UEFI and you need to use a legacy installer like grub, it will need to be installed from within an arch-chroot generated chroot, not the systemd-nspawn running container. An example of this would be (assuming that the drive of the new system is at /dev/sdb):
# arch-chroot /mnt # grub-install $DRIVE # grub-mkconfig -o /boot/grub/grub.cfg # exit
Command Summary
The following are all critical commands (exluded: the initial drive wipe which is optional). It assumes you have successfully brought up networking prior to starting this sequence.
DRIVE=/dev/DRIVEID sgdisk --zap-all $DRIVE 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=3:8300 --change-name=3:cryptsystem \ $DRIVE mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/EFI cryptsetup luksFormat --align-payload=8192 -s 256 -c aes-xts-plain64 /dev/disk/by-partlabel/cryptsystem cryptsetup open /dev/disk/by-partlabel/cryptsystem system cryptsetup open --type plain --key-file /dev/urandom /dev/disk/by-partlabel/cryptswap swap mkswap -L swap /dev/mapper/swap swapon -L swap mkfs.btrfs --force --label system /dev/mapper/system o=defaults,x-mount.mkdir o_btrfs=$o,compress=lzo,ssd,noatime mount -t btrfs LABEL=system /mnt btrfs subvolume create /mnt/root btrfs subvolume create /mnt/home btrfs subvolume create /mnt/snapshots umount -R /mnt mount -t btrfs -o subvol=root,$o_btrfs LABEL=system /mnt mount -t btrfs -o subvol=home,$o_btrfs LABEL=system /mnt/home mount -t btrfs -o subvol=snapshots,$o_btrfs LABEL=system /mnt/.snapshots pacstrap /mnt base genfstab -L -p /mnt >> /mnt/etc/fstab sed -i "s+LABEL=swap+/dev/mapper/swap" /mnt/etc/fstab systemd-nspawn -bD /mnt echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen locale-gen localectl set-locale LANG=en_US.UTF-8 timedatectl set-ntp 1 timedatectl set-timezone America/Los_Angeles hostnamectl set-hostname myhostname echo "127.0.1.1 myhostname.localdomain myhostname" >> /etc/hosts pacman -Syu base-devel btrfs-progs iw gptfdisk zsh vim terminus-font
Quick and Dirty
This is the approximate process I follow if I want to bring up Arch on, say, an old laptop for a quick purpose built test machine, etc. It's not an install that I consider long term maintainable since rollbacks aren't implemented, nor is there any encryption, but it's a good example of how simple installation can be.
DRIVE=/dev/DRIVEID sgdisk --zap-all $DRIVE mkfs.btrfs -f $DRIVE mount -t btrfs $DRIVE /mnt pacstrap /mnt base grub systemd-nspawn -bD /mnt echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen locale-gen localectl set-locale LANG=en_US.UTF-8 timedatectl set-ntp 1 timedatectl set-timezone America/Los_Angeles hostnamectl set-hostname myhostname poweroff arch-chroot /mnt grub-install --root-directory=/mnt $DRIVE grub-mkconfig -o /mnt/boot/grub/grub.cfg exit reboot