Arch Linux: Manual Install vs archinstall (and Why You Want Btrfs Snapshots)
archinstall gets you booted in ten minutes. The manual install is why you'll know what to do when it breaks.
Every Arch install guide eventually asks the same question: do you type every command yourself, or do you let archinstall do it for you? Both roads land you at the same login prompt. What you carry away from the trip is different.
This post walks both paths, then covers the thing most guides skip: setting up Btrfs snapshots with Snapper (and where Timeshift fits in) so a bad update is a five-second rollback instead of a reinstall.
Manual vs archinstall: what’s actually different
The manual install is the Arch install script written out as commands — you partition, format, mount, pacstrap the base system, generate an fstab, chroot in, and configure the bootloader by hand. Nothing is hidden from you.
archinstall is Arch’s official TUI installer. You answer a series of menu prompts — disk layout, filesystem, desktop environment, profile — and it runs the same underlying steps for you, just faster and with fewer chances to typo a UUID.
💡 Why This Matters: The manual install isn’t about being a purist. When your system doesn’t boot at 2am, you need to know what
genfstabandmkinitcpioactually do.archinstallwon’t teach you that — it’ll just get you back online faster next time.
Neither is “more correct.” A rough guide for choosing:
- Manual install if this is your first Arch install, you want to understand your own system, or you’re doing something nonstandard (LUKS + LVM + Btrfs subvolumes, dual boot with an existing Windows EFI partition, etc.).
- archinstall if you already know what the manual steps do and just want a clean, repeatable system without retyping the same fifteen commands for the third time this year.
Part 1 — Manual Installation
Boot the Arch ISO from a USB drive and verify you’re in UEFI mode:
ls /sys/firmware/efi/efivarsIf that directory exists, you’re in UEFI mode — the rest of this guide assumes that.
⚠️ Important Exception: This guide uses
/dev/nvme0n1p1,/dev/nvme0n1p2, etc. throughout as placeholder device names — don’t copy them blindly. Runlsblkbefore you partition anything and confirm which device is actually your target:
- The installer USB itself commonly shows up as
/dev/sda(or/dev/sdb) — it’s easy to accidentally partition your own boot media instead of your target disk.- NVMe SSDs (most current laptops and many desktops) use the naming this guide’s examples show:
/dev/nvme0n1, with partitions as/dev/nvme0n1p1,/dev/nvme0n1p2(note thepbefore the partition number — NVMe needs it because the device name already ends in a digit).- SATA SSDs/HDDs use a different scheme instead:
/dev/sda, with partitions as/dev/sda1,/dev/sda2— nopseparator, since the device name doesn’t end in a digit.Check size and model in
lsblk -o NAME,SIZE,MODEL,TYPEto tell your install target apart from the USB drive with confidence, then substitute your actual device name everywhere this guide says/dev/nvme0n1. If you’re on SATA rather than NVMe, that also means adjusting every partition reference below —/dev/nvme0n1p1→/dev/sda1,/dev/nvme0n1p2→/dev/sda2, and so on.
1. Connect to the internet
If you’re on Ethernet, DHCP usually just works and you can skip straight to the ping check. For Wi-Fi, the live ISO uses iwd’s iwctl client:
iwctl
[iwctl]# device listNote your device name (usually wlan0), then scan for and list nearby networks:
[iwctl]# station wlan0 scan
[iwctl]# station wlan0 get-networksConnect to your network — iwctl will prompt for the passphrase interactively:
[iwctl]# station wlan0 connect "Your-SSID"
[iwctl]# station wlan0 show
[iwctl]# exitstation wlan0 show confirms you’re actually connected (state, SSID, and signal strength) before you leave the iwctl shell — worth checking, since a typo’d passphrase fails silently otherwise.
ping -c 3 archlinux.org💡 Quick Check: No reply from
ping? Runip aand confirmwlan0has an IP address. No IP means the connection didn’t actually succeed even ifiwctldidn’t show an error — reconnect and checkstation wlan0 showagain.
2. Rank mirrors with reflector
The default /etc/pacman.d/mirrorlist on the live ISO is a long, unsorted list — some of those mirrors are slow, some are geographically distant, some are stale. reflector fetches the current mirror list and rewrites it sorted by whatever actually matters (speed, sync recency, protocol), so every download from here on — pacstrap included — pulls from a fast, up-to-date mirror instead of whatever happened to be first alphabetically.
Recent Arch ISOs already run reflector once automatically at boot via a background service, but it’s worth running it yourself for a result tuned to your location and connection right now:
reflector --country 'US' --age 12 --protocol https --sort rate --save /etc/pacman.d/mirrorlist--country 'US'— limit to mirrors in your country (use your own, or drop the flag and use--latest 20instead to just grab the 20 most recently synced mirrors worldwide).--age 12— only consider mirrors that synced within the last 12 hours, so you’re not ranking a mirror that’s fast but stale.--protocol https— skip plain HTTP mirrors.--sort rate— sort the surviving candidates by actual measured download speed, fastest first.--save /etc/pacman.d/mirrorlist— overwrite the live ISO’s mirrorlist with the result.
💡 Why This Matters: This step is easy to skip because the install works either way — a slow mirror just means a slower
pacstrap. Butpacstrappulls the entire base system plus whatever packages you add, and a bad mirror can turn a 5-minute step into a 40-minute one. Two minutes runningreflectorup front usually pays for itself before you even finish partitioning.
3. Configure pacman for speed (and multilib for gaming)
Before you install anything, it’s worth tuning the live ISO’s pacman.conf — pacstrap uses these same mirror and download settings, so this saves time on every step from here on:
vim /etc/pacman.confUncomment or add these under the [options] section:
Color
ILoveCandy
ParallelDownloads = 5Color and ILoveCandy are cosmetic — colored output and a Pac-Man-style progress bar — but ParallelDownloads = 5 is the one that actually matters: by default pacman downloads packages one at a time, and setting this to 5 lets it fetch several in parallel, which is a real difference on a full pacstrap or later -Syu.
If you play games or need 32-bit libraries (Steam, Wine, Lutris, some proprietary GPU tooling), also uncomment the [multilib] block near the bottom of the file:
[multilib]
Include = /etc/pacman.d/mirrorlist💡 Why This Matters:
multilibis easy to forget because nothing breaks without it right away — until you try topacman -S steammonths later and get a “target not found” error. Enabling it now costs nothing if you never end up needing it.
Refresh the package databases so the new settings and (if enabled) multilib repo take effect:
pacman -Sy4. Partition the disk
Use cfdisk or fdisk on /dev/nvme0n1 (or /dev/sda if you’re on a SATA disk — check with lsblk first). A typical layout:
/dev/nvme0n1p1 512M EFI System
/dev/nvme0n1p2 rest Linux filesystemIf you want a dedicated swap partition instead of a swap file (see the callout below for why you’d choose one over the other), carve it out here instead of doing it later — resizing partitions after the fact is more painful than resizing a file:
/dev/nvme0n1p1 512M EFI System
/dev/nvme0n1p2 8G Linux swap (roughly your RAM size, more if you want hibernation headroom)
/dev/nvme0n1p3 rest Linux filesystem⚠️ Important Exception: A dedicated swap partition is the only option that reliably supports hibernation (suspend-to-disk) — a Btrfs swap file can technically work with hibernation on recent kernels, but it’s fiddlier to get right and easy to misconfigure. If you don’t care about hibernation, skip the swap partition here and use a Btrfs swap file instead (Step 7) — it’s resizable without repartitioning and is the more common choice on SSDs today.
5. Format the partitions
mkfs.fat -F32 /dev/nvme0n1p1
mkfs.btrfs /dev/nvme0n1p2If you created a dedicated swap partition above, format and enable it too — adjust the device numbers if you added it as /dev/nvme0n1p2:
mkswap /dev/nvme0n1p2
swapon /dev/nvme0n1p2We’re using Btrfs for the root filesystem instead of ext4 — more on why in Part 3, but the short version is copy-on-write snapshots that make rollbacks trivial.
6. Create Btrfs subvolumes and mount
Subvolumes let Snapper snapshot @ (root) without dragging your home directory or package cache along with it. Add @swap here too even if you’re not sure yet whether you’ll use a swap file — a swap file needs its own subvolume so it doesn’t get caught up in snapshots (snapshotting an active swap file corrupts it):
mount /dev/nvme0n1p2 /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@log
btrfs subvolume create /mnt/@pkg
btrfs subvolume create /mnt/@swap
umount /mnt
mount -o subvol=@,compress=zstd /dev/nvme0n1p2 /mnt
mkdir -p /mnt/{boot,home,var/log,var/cache/pacman/pkg,swap}
mount -o subvol=@home,compress=zstd /dev/nvme0n1p2 /mnt/home
mount -o subvol=@log,compress=zstd /dev/nvme0n1p2 /mnt/var/log
mount -o subvol=@pkg,compress=zstd /dev/nvme0n1p2 /mnt/var/cache/pacman/pkg
mount -o subvol=@swap /dev/nvme0n1p2 /mnt/swap
mount /dev/nvme0n1p1 /mnt/bootNote @swap is mounted without compress=zstd — swap files can’t be compressed, and pointing that out now saves a confusing error in the next step.
💡 Why This Matters: Setting up
@home,@log,@pkg, and@swapas separate subvolumes now costs you two minutes. Doing it after the fact means backing up, reformatting, and restoring. This is the step people skip and regret.
7. Set up swap
Skip this step entirely if you created and enabled a dedicated swap partition back in Step 4/5. Otherwise, create a Btrfs swap file inside the @swap subvolume you just mounted. Modern btrfs-progs (5.19+) has a dedicated command that handles the Copy-on-Write and compression exclusions for you automatically:
btrfs filesystem mkswapfile --size 8G --uuid clear /mnt/swap/swapfile
swapon /mnt/swap/swapfileSize is a rough guideline, not a hard rule: 8G is plenty for a desktop with 16G+ of RAM doing normal work; match or exceed your RAM size if you want hibernation to be possible.
⚠️ Important Exception: If your
btrfs-progsis older than 5.19 andmkswapfileisn’t available, you need to do the same thing by hand — create the file, disable Copy-on-Write on it before writing any data, then format it as swap:BASHtruncate -s 0 /mnt/swap/swapfile chattr +C /mnt/swap/swapfile fallocate -l 8G /mnt/swap/swapfile chmod 600 /mnt/swap/swapfile mkswap /mnt/swap/swapfile swapon /mnt/swap/swapfileThe
chattr +Cbeforefallocatematters — Copy-on-Write can only be disabled on an empty file. Runningchattr +Cafter the file already has data does nothing.
You’ll add the fstab entry for this in the next step, and enable swappiness tuning (optional) once you’re in the chroot.
8. Install the base system
pacstrap -K /mnt base linux linux-firmware btrfs-progs vim networkmanagernetworkmanager is in that list deliberately, not as an afterthought. The live ISO’s iwd/iwctl setup only exists for the installer environment — it doesn’t carry over to your installed system. Without a network manager installed now, your first boot into the new system has no working network stack at all, wired or wireless, and you’d have to bring it up manually (systemctl enable --now systemd-networkd, hand-write .network files, etc.) just to install anything else.
💡 Why This Matters: NetworkManager isn’t the only option —
systemd-networkdandiwdalone both work — but it’s the one that “just works” across wired, Wi-Fi, and VPN with almost no configuration, and it’s what every major desktop environment’s network applet expects to talk to. Unless you specifically want a minimal headless setup, install it and enable it (next step) rather than configuring networking by hand.
9. Generate fstab
genfstab -U /mnt >> /mnt/etc/fstab💡 Quick Check: Open
/mnt/etc/fstaband confirm every mount point (/,/home,/var/log,/var/cache/pacman/pkg,/boot) has its own line with a UUID. If any are missing, something didn’t mount before you rangenfstab— remount and regenerate.
If you set up a Btrfs swap file in Step 7, genfstab won’t add it automatically — swap files need a manual line. Append it yourself:
echo "/swap/swapfile none swap defaults 0 0" >> /mnt/etc/fstabIf you used a dedicated swap partition instead, genfstab picks it up on its own as long as you ran swapon on it back in Step 5 — check for a swap line in /mnt/etc/fstab to confirm.
10. Chroot and configure
arch-chroot /mnt
ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohc
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "myhostname" > /etc/hostname
passwd
systemctl enable NetworkManagerThat last line matters as much as installing the package in Step 8 — pacstrap puts the binaries on disk, but nothing starts them on boot until the service is enabled. Skip it and you’ll boot into a system with no network and no obvious reason why.
⚠️ Important Exception:
/mnt/etc/pacman.confis a fresh default file — theColor,ILoveCandy,ParallelDownloads, and[multilib]settings you set on the live ISO in Step 3 did not carry over into your installed system. Re-edit/etc/pacman.confhere inside the chroot (orpacman -Syagain after enabling multilib) if you want the same settings on the installed OS.
While you’re in the chroot, this is also a reasonable point to tune swappiness if you used a swap file — the kernel default (60) is tuned for older hardware and tends to swap earlier than most modern desktops with plenty of RAM actually need:
echo "vm.swappiness=10" > /etc/sysctl.d/99-swappiness.conf11. Bootloader
You need a boot manager so UEFI has something to hand control to after POST. GRUB gets the most tutorial coverage because it’s been the historical default, but it isn’t what most current Arch users actually run day to day — systemd-boot and Limine both show up more often in current Arch community polls and forum threads, with rEFInd as a smaller but still active third option. Four real choices, in the order this guide recommends trying them:
- systemd-boot — ships as part of systemd, so no extra package beyond
efibootmgr. Config is a handful of plain-text files, no generator step, boots fast. UEFI-only, and doesn’t auto-detect other OSes. The default recommendation here for a single-OS UEFI install. - Limine — newer, actively developed, UEFI and legacy BIOS support from one bootloader, with a config format most people find more readable than GRUB’s. It’s now a selectable option in
archinstallitself (added in 2023), which says something about how mainstream it’s become. Good pick if you want GRUB’s flexibility without GRUB’s config generator. - rEFInd — UEFI-only, graphical, and excellent at auto-detecting other OSes and kernels without a config file at all — it scans your ESP at boot time. A good fit for multi-boot machines where you want zero maintenance when kernels change.
- GRUB — still the right call for BIOS/legacy hardware, unusual multi-OS setups, or if you specifically want
os-proberauto-detecting Windows for you. Otherwise it’s the most complex of the four for what most single-OS Arch installs need.
⚠️ Important Exception: GRUB has a real, documented failure mode on Arch worth knowing about even if you don’t choose it — in August 2022, an update changed how GRUB’s generated config invokes the firmware-setup command, and installs where the on-disk bootloader and the newly generated config fell out of sync could fail to boot. Arch published an official news post about it, and the forums saw a wave of “GRUB won’t boot after update” threads for months afterward. The fix (rerun both
grub-installandgrub-mkconfigtogether after any GRUB update, never just one) is officially documented now, but it’s a real class of breakage the other three bootloaders here don’t share, since none of them auto-generate a config file that can desync from the installed loader.
This guide demonstrates systemd-boot as the default path:
bootctl installThen create the loader config and a boot entry by hand — there’s no generator step, which is exactly why it’s simpler for single-OS machines and less forgiving if you need something more elaborate:
cat > /boot/loader/loader.conf <<EOF
default arch.conf
timeout 3
console-mode max
EOF
cat > /boot/loader/entries/arch.conf <<EOF
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=UUID=$(blkid -s UUID -o value /dev/nvme0n1p2) rw
EOF💡 Quick Check: Run
bootctl statusafterward. Under “Boot Loaders Listed in EFI Variables” you should see systemd-boot. If it’s missing,bootctl installdidn’t register with firmware — confirm/bootis mounted to your EFI partition and re-run it.
If you’d rather use GRUB, Limine, or rEFInd instead, the package names and setup differ but the underlying pattern is the same as Part 1’s earlier steps — install the bootloader package, run its install command so it registers with UEFI (usually via efibootmgr), then write or generate its config:
# GRUB
pacman -S grub efibootmgr
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
# Limine
pacman -S limine efibootmgr
mkdir -p /boot/EFI/limine
cp /usr/share/limine/BOOTX64.EFI /boot/EFI/limine/
efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Arch Linux" --loader '\EFI\limine\BOOTX64.EFI' --unicode
# --disk takes the whole-disk device (e.g. /dev/nvme0n1 on NVMe, not /dev/nvme0n1p1) —
# --part stays a plain partition number (1) either way, efibootmgr handles the naming difference for you
# then write /boot/limine.conf with your kernel and root UUID
# rEFInd
pacman -S refind
refind-install12. Reboot
exit
umount -R /mnt
rebootPart 2 — Automatic Installation with archinstall
Boot the same ISO. archinstall ships on it already:
archinstallYou’ll walk through a menu instead of typing each step:
- Locale & keyboard layout — pick your region and layout up front.
- Disk configuration — choose the target disk, then filesystem. Pick Btrfs and enable the subvolume layout option if offered; it creates
@,@home,@log,@pkg-style subvolumes automatically, same as Part 1. Swap is handled right here too, usually as a separate prompt: archinstall defaults to a Btrfs swap file sized to your RAM rather than a partition, which matches this guide’s recommendation from Part 1 — pick a swap partition instead only if you specifically want hibernation support. - Bootloader — archinstall offers three of the four options from Part 1 directly in the menu: systemd-boot, GRUB, and Limine (added as a native option in archinstall 2.6). rEFInd isn’t in the menu and has to be installed manually after first boot if you want it. Pick systemd-boot for a plain single-OS UEFI install, Limine if you want something GRUB-like without GRUB’s config-desync failure mode (see Part 1’s callout on the 2022 GRUB incident), or GRUB specifically if you need
os-proberto find an existing Windows install. - Network configuration — pick NetworkManager here rather than “Use existing configuration.” archinstall enables it as a service automatically, which is the one manual step (
systemctl enable NetworkManager) that’s easiest to forget when doing this by hand — same reason it matters as in Part 1: no enabled network service means no network on first boot. - Repository & mirrors — this is where multilib lives, as a toggle, not a text edit. Enable it here if you’ll want
steam,lib32-*packages, or Wine later; skip it if not. There’s usually a mirror-region picker here too, which does roughly the same job as manually editing/etc/pacman.d/mirrorlist. - Profile — desktop environment, server, or minimal. Pick “Desktop” and a DE (GNOME, KDE Plasma, etc.) if you want a GUI on first boot.
- Additional packages — a free-text field for anything not covered by the profile:
base-develandgitif you’ll be building AUR packages,steamandlib32-nvidia-utils(or the equivalent for your GPU) if you enabled multilib in Step 5,reflectorif you want automatic mirror ranking later. Package names here need multilib already enabled or they simply won’t resolve — this is the step people skip and then wonder whypacman -S steamfails after first boot. - Users, hostname, timezone — same information as the corresponding manual steps in Part 1, just filled into form fields.
- Review and install — archinstall shows you the full JSON of what it’s about to do before it touches the disk.
💡 Why This Works: Every field in that menu maps to a manual command from Part 1 — the disk config screen is
mkfs.btrfsandbtrfs subvolume create, the profile screen ispacstrapwith a longer package list. If Part 1 made sense, nothing here is a black box.
⚠️ Important Exception: archinstall’s Btrfs subvolume presets are good defaults but not identical to a hand-rolled layout — check the summary screen before confirming if you specifically need a
@snapshotssubvolume for Snapper (see Part 3). If it’s missing, you can still add it manually after first boot.
The menu doesn’t expose ParallelDownloads, Color, or ILoveCandy — those are cosmetic/performance tweaks, not install-blocking, so archinstall skips them. Add them to /etc/pacman.conf yourself after first boot the same way as Step 3 in Part 1 if you want them. archinstall does rank mirrors for you automatically as part of its mirror-region selection, so there’s no separate reflector step to run here — that’s one advantage of the guided path.
When it finishes, unmount and reboot the same way as the manual path — archinstall handles that for you and offers to chroot in for any last changes first.
Part 3 — Conclusion: Set Up Snapshots Before You Need Them
Whichever install path you took, you now have a Btrfs root. The reason that matters: Btrfs is copy-on-write, so a snapshot is just a reference to the current state of the filesystem — near-instant to create, and cheap to keep dozens of them around. That turns “I broke my system updating a package” from a reinstall into a one-command rollback.
Two tools do this on Arch, and they solve slightly different problems:
Snapper is the tighter integration. It hooks into pacman (via snap-pac) so it automatically takes a pre/post snapshot around every package transaction — install, update, or remove. Rollback after a bad update means booting into the pre-transaction snapshot straight from your bootloader menu, so you’re back exactly where you were without touching a live USB.
pacman -S snapper snap-pac
snapper -c root create-config /Getting those snapshots to actually show up as bootable entries needs one more package, and which one depends on the bootloader you picked in Part 1 or Part 2:
- GRUB →
grub-btrfsregeneratesgrub.cfgto include a “Snapshots” submenu. - systemd-boot →
systemd-bootdoesn’t scan subvolumes on its own; the common approach is a small script or the AURsbctl/booster-adjacent snapshot-boot helpers that write a loader entry per snapshot, or simply mounting the desired snapshot read-write and rebooting into it viaarch-chrootif things go wrong. - Limine →
limine-snapper-sync(AUR) reads your Snapper snapshots and writes matching Limine boot entries automatically, similar in spirit togrub-btrfs.
⚠️ Important Exception: Out of the box, only GRUB (via
grub-btrfs) and Limine (vialimine-snapper-sync) get you a “just pick the old snapshot from the boot menu” experience. On systemd-boot, rolling back is closer to “boot the live USB,arch-chrootin, andbtrfs subvolume set-defaultto the snapshot” — still fast, just one extra step. If seamless boot-menu rollback matters more to you than systemd-boot’s simplicity, that’s a reasonable trade to make in favor of Limine.
Timeshift is the more general-purpose, GUI-friendly backup tool. It supports Btrfs snapshots too, but it isn’t pacman-aware out of the box — snapshots happen on a schedule or manually, not automatically around package changes. It’s a good fit if you want a simple “roll back to last Tuesday” safety net without thinking about subvolume layout, or if you’re coming from a Timeshift-on-Ubuntu habit and want the same mental model.
💡 Why This Matters: If you only remember one thing from this section — install
snap-pac. The whole value of Snapper on Arch is that it snapshots automatically before everypacman -Syu. Withoutsnap-pac, you’re just running Snapper manually, which is closer to what Timeshift already does.
A reasonable default: Snapper + snap-pac + grub-btrfs for automatic, update-aware protection, and Timeshift only if you specifically want a scheduled, GUI-managed backup on top of that. Running both isn’t wrong, just redundant for most single-user desktops.
Either way, the underlying reason to have chosen Btrfs back in Part 1 or Part 2 pays off here: the filesystem decision you made during partitioning is what makes any of this possible without a separate backup partition or third-party tool.