Skip to content

Latest commit

 

History

History
688 lines (619 loc) · 34.2 KB

File metadata and controls

688 lines (619 loc) · 34.2 KB

reference guides on youtube

https://www.youtube.com/watch?v=DPLnBPM4DhI “Arch Linux: Full Installation Guide - A complete tutorial/walthrough in one video!” (dead but channel is Learn Linux TV)

read this first

for a fresh new machine the section i actually want to follow is current recommended install without lvm2 but with luks (Dec 2024) below. the older legacy install with lvm2 (Jul 2019) path is mostly here for historical context / recovery on old boxes and should not be my default recipe.

before starting on a new machine:

  • verify the iso checksum/signature before writing it to usb
  • decide intel vs amd microcode package
  • decide whether secure boot is disabled (these notes assume the usual unsigned grub path)
  • write down disk device, hostname, username, timezone
  • before reboot sanity check lsblk -f, /etc/fstab, and efibootmgr -v

create iso image

download an iso like this

mkdir arch-iso-20241101
rsync -av rsync://mirror.adectra.com/archlinux/iso/2024.11.01/ ./arch-iso-20241101/

before writing it i want to verify the checksum/signature from that same release directory.

then cat it into the usb drive (triple check the target first with lsblk or fdisk -lu; i do not want to guess here)

sudo -i
cat /path/to/the.iso > /dev/sdX # replace sdX only after confirming it is the usb device
sync
exit

to make the thumb drive usable again after that one must repartition like this:

sudo wipefs --all /dev/sdx
sudo fdisk /dev/sdx #followed by g, n, <RET> to make single partition and w to commit
sudo mkfs.ext4 /dev/sdx1 #to put a fresh file system into the partition made above

legacy install with lvm2 (Jul 2019)

mostly here for older boxes / historical reference. for a fresh machine i want the current recommended install without lvm2 but with luks (Dec 2024) section below.

boot into image, get internet, set time, partition

need to verify in UEFI mode by checking for presence of file /sys/firmware/efi/efivars next internet use iwctl (rather than the old wifi-menu) and check with ip a or ping -c 2 archlinux.org if that is fine next steps are a quick time set

timedatectl status #to check
timedatectl set-ntp true

next

pacman -Sy #sync latest
fdisk /dev/sdx #your disk - type g for a new GPT partition table

make an EFI partition about 500MB, a boot about 500MB and last partition fill it up and type t to pick type 31/43 (LVM) for it then finalize (check types with L) then first two filesystems:

mkfs.fat -F32 /dev/sdx1 #EFI
mkfs.ext4 /dev/sdx2 #Boot

for the last one make the volumes with /dev/sdx3 directly like

pvcreate --dataalignment 1m /dev/sdx3
vgcreate vg0 /dev/sdx3
lvcreate -L 30GB vg0 -n lv_root
lvcreate -L 500GB vg0 -n lv_home
modprobe dm_mod
vgscan
vgchange -ay

next make file systems and mount everything:

mkfs.ext4 /dev/vg0/lv_root
mkfs.ext4 /dev/vg0/lv_home
mount /dev/vg0/lv_root /mnt
mkdir /mnt/boot /mnt/home /mnt/etc /mnt/efi
mount /dev/sdx2 /mnt/boot
mount /dev/sdx1 /mnt/efi
mount /dev/vg0/lv_home /mnt/home

with everything mounted make the fstab file and strap on:

genfstab -U -p /mnt >> /mnt/etc/fstab
pacstrap -K /mnt base linux linux-firmware lvm2
arch-chroot /mnt

initial setup now in your ssd

first set the timezone and hwclock

ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohc

name your host by editing or creating /etc/hostname with name and then editing /etc/hosts to contain

127.0.0.1 localhost
::1       localhost
127.0.1.1 yourhostname.localdomain yourhostname

some packages to install

pacman -S base-devel grub efibootmgr dosfstools mtools linux linux-headers linux-firmware lvm2 networkmanager wpa_supplicant emacs sudo man-db man-pages
systemctl enable NetworkManager

now edit /etc/mkinitcpio.conf and in HOOKS between block and filesystems add lvm2 entry and then one can run

mkinitcpio -P

generate locale by uncommenting en_US.UTF-8 in /etc/locale.gen and running locale-gen set the root passwd passwd add your user useradd -m -g users -G wheel bla and passwd bla allow wheel group by running EDITOR='emacs -nw' visudo and uncommenting %wheel ALL=(ALL) ALL next ready grub like so

grub-install --efi-directory=/efi --boot-directory=/boot --target=x86_64-efi --bootloader-id=grub_uefi --recheck
cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale/en.mo #might have to mkdir the destination
grub-mkconfig -o /boot/grub/grub.cfg

(in unlikely case of not using uefi the grub-install command is likely grub-install --target=i386-pc --recheck /dev/sda) finally make a swapfile and add it to fstab like so

dd if=/dev/zero of=/swapfile bs=1M count=8000 status=progress
chmod 600 /swapfile
mkswap /swapfile
cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab

ready to go at this point so exit; umount -R /mnt; reboot

upon boot

verify everything works. if i am benchmarking and intentionally trading off security, i can temporarily add mitigations=off from the grub menu with e, check it via cat /proc/cmdline, and only make it persistent later if i really mean to. i do not want that as a default on a fresh install. next install quite a few more useful packages

sudo pacman -S r gcc-fortran openblas turbostat xorg-server xorg-xinit xorg-xprop xorg-xset rxvt-unicode dmenu
sudo pacman -S tree ripgrep the_silver_searcher parallel alsa-utils wget
sudo pacman -S firefox xorg-xrandr xorg-xwininfo xorg-xprop xorg-xdpyinfo xdpyinfo
sudo pacman -S pipewire pipewire-pulse pipewire-alsa wireplumber pavucontrol bc gdb htop pacman-contrib

sudo pacman -S base-devel inetutils cmake tk man-db man-pages rsync #inetutils for hostname and tk for R menu
sudo pacman -S bind #dnsutils like host and nslookup

if old laptop also grab linux-firmware

get sensors to be able to monitor system

sudo pacman -S lm_sensors
sudo sensors-detect

install nvidia requirements if actually needed; often the packages alone are enough and nvidia-xconfig is a last resort

sudo pacman -S nvidia nvidia-utils nvidia-settings
# if i really need a generated xorg file:
# sudo nvidia-xconfig
# sudo mv /etc/X11/xorg.conf /etc/X11/xorg.conf.d/20-nvidia.conf

use sudo nvidia-settings for future monitor additions and updates to displays edit /etc/makepkg.conf (in particular MAKEFLAGS -j) to match server capacity

set up a global gitignore (for github auth prefer ssh keys or gh auth login, not a plaintext token in gitconfig)

git config --global core.excludesFile ~/.gitignore

current recommended install without lvm2 but with luks (Dec 2024)

this is the main path i want to follow on a fresh machine.

boot and ensure uefi/wifi

boot into iso, verify /sys/firmware/efi/fw_platform_size (must exist, likely contain value 64) then iwctl to connect to wifi these notes assume secure boot is disabled; if i want to keep secure boot i need a signed boot path rather than assuming plain grub will boot. if i am using a non-US keyboard and encrypted root, remember that the LUKS passphrase later has to survive the early boot keyboard layout too.

iwctl # will enter a shell, do 'station list', then something like 'station wlan0 get-networks'
iwctl --passphrase <XXX> station wlan0 connect <WIFI-NETWORK-NAME>

ip a # check you have ip addr
ping archlinux.org # ping check
timedatectl set-ntp true

partition and format disks

will want to mount ESP to /efi (separate from /boot) so one can have ext4 for it and separate concern from the fat fs for bootloader (this is more similar to learn linux tv approach) - (arch wiki reference)

lsblk -o NAME,MAJ:MIN,RM,SIZE,RO,TYPE,MOUNTPOINT,LABEL # use along the way to see devices
fdisk /dev/nvme0n1 # type g for new GPT (make an efi 500MB, boot 500MB, rest will be root)

mkfs.fat -F32 -n "EFI" /dev/nvme0n1p1
mkfs.ext4 -L "BOOT" /dev/nvme0n1p2

cryptsetup luksFormat /dev/nvme0n1p3
cryptsetup open /dev/nvme0n1p3 cryptroot # opens it naming it cryptroot
mkfs.ext4 -L "ROOT" /dev/mapper/cryptroot
mount /dev/mapper/cryptroot /mnt
mount --mkdir /dev/nvme0n1p1 /mnt/efi
mount --mkdir /dev/nvme0n1p2 /mnt/boot

mirrors and pacstrap

uncomment line that says ParallelDownloads via nano /etc/pacman.conf /etc/pacman.d/mirrorlist carries over from live env to installed system so get good mirrors

pacman -S reflector
reflector -c US -a 12 --sort rate --save /etc/pacman.d/mirrorlist
pacman -Syy # refresh mirror list after replacing it

install essential packages (pick the microcode package for the cpu actually in the machine; below shows intel)

pacstrap -K /mnt base base-devel emacs networkmanager cryptsetup grub efibootmgr linux linux-headers linux-firmware sudo reflector intel-ucode
# on AMD swap intel-ucode for amd-ucode

fstab and chroot

genfstab -U /mnt >> /mnt/etc/fstab
arch-chroot /mnt

set up swapfile

fallocate -l 38G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap defaults 0 0' >> /etc/fstab

time setup

ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
hwclock --systohc # generates /etc/adjtime

systemctl enable systemd-timesyncd.service

localization

locale-gen # after uncomment en_US.UTF-8 UTF-8 from /etc/locale.gen

create /etc/locale.conf with content LANG=en_US.UTF-8

hostname

name it on /etc/hostname and also in /etc/hosts add

127.0.0.1 localhost
::1       localhost
127.0.1.1 yourhostname.localdomain yourhostname

set root pwd, add user

passwd to set root pwd, then uncomment %wheel ALL=(ALL) ALL line in EDITOR='emacs -nw' visudo then useradd -m -g users -G wheel bla then passwd bla

networking

systemctl enable NetworkManager

mkinitcpio (given luks)

edit /etc/mkinitcpio.conf in the HOOKS line and add encrypt between block and filesystems regenerate mkinitcpio -P

boot loader

grub-install --efi-directory=/efi --boot-directory=/boot --target=x86_64-efi --bootloader-id=grub_uefi --recheck

because of encryption edit /etc/default/grub and set GRUB_CMDLINE_LINUX to something like

cryptdevice=UUID=<UUID-OF-ENCRYPTED-PARTITION>:cryptroot root=/dev/mapper/cryptroot

get that UUID with

blkid -o value -s UUID /dev/nvme0n1p3 # replace with the actual encrypted partition if not nvme0n1p3

then regenerate grub and sanity check the mounts / boot entries before reboot

grub-mkconfig -o /boot/grub/grub.cfg
lsblk -f
cat /etc/fstab
efibootmgr -v # to confirm the UEFI boot entries
# /efi/EFI/grub_uefi should be there too

exit chroot and reboot into new system

exit
umount -R /mnt
reboot # remove the usb now

optional / personal packages after first boot

not required to get the machine booted; these are the bits i usually want on one of my own machines.

# likely first connect to wifi via nmtui
sudo pacman -S alsa-utils bc clang cmake dmenu dosfstools efibootmgr firefox gcc-fortran gdb ghostscript git htop inetutils libvterm llvm lm_sensors lsof man-db man-pages mlocate mtools openbox openssh obconf pacman-contrib parallel pdftk python-black python-pip qpdf r ripgrep rsync rxvt-unicode strace texinfo the_silver_searcher tk tmux tree turbostat valgrind wget xorg-server xorg-xdpyinfo xorg-xinit xorg-xprop xorg-xrandr xorg-xset xournalpp
sudo pacman -S pipewire pipewire-pulse pipewire-alsa wireplumber pavucontrol # normal desktop audio stack
sudo systemctl enable --now fstrim.timer # for ssd/nvme

for fonts, fc-list should have very few by default, fc-match Monospace might match something like FreeMono.otf. install noto to instead fc-match NotoSansMono-Regular.ttf

sudo pacman -S noto-fonts
fc-match Monospace

bootstrap some home dirs and content (like dotfiles)

mkdir development docs history rabbit; cd development
git clone https://github.com/PalaceChan/helm-shell-history.git
git clone https://github.com/PalaceChan/Configuration.git dotfiles
git clone https://github.com/PalaceChan/systemNotes.git
git clone https://github.com/PalaceChan/scripts.git

(cd ~/development/dotfiles && for f in .gitconfig .gitignore .Rprofile .tmux.conf .Xmodmap .xinitrc .Xresources .mc-lists.el .gdbinit .bash_profile .bashrc; do cp -v $f ~/; done)
cp ~/development/dotfiles/dump_history.sh ~/history/
# in .gitconfig copy over only the non-secret bits manually
# restore secrets (ssh keys, authinfo, tokens) via a safer path rather than keeping plaintext creds in gitconfig

set up hibernation

edit /etc/mkinitcpio.conf and add resume after encrypt but before filesystems, then regen mkinitcpio -P

edit /etc/default/grub and append to GRUB_CMDLINE_LINUX “resume=UUID=B resume_offset=123456”

where the offset value comes from a command like and B is the uuid of the decrypted root volume

filefrag -v /swapfile # physical_offset column first row
#filefrag -v /swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
# findmnt -no UUID -T /swapfile can help confirm B

then

sudo grub-mkconfig -o /boot/grub/grub.cfg

to hibernate you can say

systemctl hibernate # suspend would be sleeping in low powered RAM vs hibernate will be to disk via swapfile
# can also say hybrid-sleep which suspends but saves state to disk so can resume if power gets lost

control behaviors in /etc/systemd/logind.conf then bounce the daemon sudo systemctl restart systemd-logind

references

linknotes
arch-wiki install guide
DenshiVideo, Arch Linux: An Encrypted Guide(uses single boot partition)
EF Linux Made Simple
Learn Linux TV
setup hibernation short youtube clip(forgets to add resume to the hooks in mkinitcpio.conf between filesystems and fsck)
arch wiki on power management

optional / personal extras after base install

these are not required to get Arch installed; they are the extras i usually add on my own machines.

battery optimization

set charge threshold for health, for thinkpad laptop:

sudo pacman -S tlp
sudo systemctl enable tlp # systemctl is-enabled tlp to check if have enabled before and systemctl status tlp also useful
sudo systemctl start tlp
# then in /etc/tlp.conf set the START_CHARGE_THRESH_BAT0 and STOP_CHARGE_THRESH_BAT0 (60 and 70 e.g.), then:
sudo systemctl restart tlp
# run this to see details of current state and battery stats:
sudo tlp-stat -b

openbox

sudo pacman -S openbox obconf
# mkdir p ~/.config && cp -r ~/development/dotfiles/.config/openbox ~/.config/ # if bootstrapping from github

then add exec openbox-session to bottom of xinitrc

lvm snapshots

use a command like this to backup root filesystem regularly

sudo lvcreate -L 8GB -s -n root_snapshot_YYYYMMDD /dev/mapper/vg0-lv_root
sudo lvs #display existing

to purge an old snapshot

sudo lvremove /dev/vg0/root_snapshot_YYYYMMDD

you can check volume group stats (like free space) with sudo vgs

multiple monitors

use xprop | grep CLASS command (package xorg-xprop) to click on windows and see their class names

audio

for a normal fresh install prefer PipeWire rather than PulseAudio; pipewire-pulse is the PulseAudio replacement, so you not want both installed. a good default set is pipewire pipewire-pulse pipewire-alsa wireplumber pavucontrol and pavucontrol still works fine there. run alsamixer to ensure channels are unmuted, run speaker-test to test if there is annoying beep, alsamixer might have a beep channel, mute it with M

do lspci | grep -i audio to see soundcard, can also consult arch wiki for lenovo models here and one may need alsa firmware (package sof-firmware) then also aplay -l will show soundcards. if the user session audio stack seems dead, check systemctl --user status pipewire pipewire-pulse wireplumber. installing sof-firmware rebuilds mkinitcpio so you have to reboot (this usually resolves headphones, but not laptop speakers)

setting up vpn

youtube source: https://www.youtube.com/watch?v=O-wIUZaywBc

install this package:

sudo pacman -S networkmanager-openvpn

go to https://www.vpnbook.com/ to get a username and pwd and to download a package bundle. Unzip it.

you also want these for gui setup

sudo pacman -S nm-connection-editor network-manager-applet

then you run nm-connection-editor & and hit the + then import vpn from file to import the ovpn file (the tcp one) along with the username and pwd from the website

afterwards it should show up when you run nmcli connection show (for example, vpnbook-us16-tcp80) and you can turn it on via nmcli connection up vpnbook-us16-tcp80 and off via nmcli connection down vpnbook-us16-tcp80 just check on https://whatismyipaddress.com/ and it should be working

miscellaneous packages

Useful packages to have on any system

PackageNotesCommand
isyncyields mbsync used by mu4e to pull emailsudo pacman -S isync
mu-gitmu and mu4e in AURgit clone https://aur.archlinux.org/mu.git then makepkg -si
virtualboxneeds AUR extensionsudo pacman -S virtualbox git git clone https://aur.archlinux.org/virtualbox-ext-oracle.git
telegram-desktopsudo pacman -S telegram-desktop
telegaemacs equivalent (see packageNotes.org)AUR for tdlib, git from src for the rest (incuding a C server)
mlocatefor updatedb to do custom helm locatessudo pacman -S mlocate
ctagsto generate TAGSsudo pacman -S ctags
clangllvm frontendsudo pacman -S clang
llvmllvm libssudo pacman -S llvm
lsofsudo pacman -S lsof
stracesudo pacman -S strace
valgrindsudo pacman -S valgrind
stdmanc++11/14 man pagesgit clone https://aur.archlinux.org/stdman-git.git then makepkg -si
python-black/usr/bin/blacksudo pacman -S python-black
python-pipsudo pacman -S python-pip
jupyterlabfor elpy use of coursesudo pacman -S jupyterlab
perfperf eventssudo pacman -S perf
peekgif recordersudo pacman -S peek
ghostscriptpdf manipsudo pacman -S ghostscript
pdftkpdf manipsudo pacman -S pdftk
libvtermfor vterm in emacssudo pacman -S libvterm
texlivecovers needs for texsudo pacman -S texlive
qpdfencrypt/decrypt pdfssudo pacman -S qpdf
xournalppannotate pdfs (e.g. to sign them)sudo pacman -S xournalpp

external drive backups

first time only need to make a partition on the external drive and then an ext4 fs. for the partition just do sudo fdisk on the device (e.g. /dev/sda) and g for GPT label then n for new partition (all defaults fine to use the whole thing) then w to save that

then e.g. sudo mkfs.ext4 /dev/sda1 to get the fs done and then just sudo mount -t ext4 /dev/sda1 /mnt and it useable

for backups get timeshift from AUR, run as sudo timeshift-gtk from commandline (it can auto mount external drive above)

lifetime notes

If timedatectl status shows NTP off (or clock looks off) just run timedatectl set-ntp true

to ssh/scp stuff across two of these

ssh-keygen -C "$(whoami)@$(uname -n)-$(date -I)" # if you need to make an ssh key

systemctl start sshd
ip -br a # see ip addr this way the 192.*
# ssh username@<the ip> from other computer or rsync -abviuzPc docs/ avelazqu@<the ip>:docs/
systemctl stop sshd # when done

for a smart merge using rsync see https://superuser.com/questions/547282/which-is-the-rsync-command-to-smartly-merge-two-folders so basically rsync -abviuzPc src/ dest/ (the -c flag uses checksums rather than timestamps when comparing -n to sanity check and remove -b if want no backups created and --delete to delete stuff in dest not present in src)

annotating a pdf, unencrypting and decrypting

use xournal++ (package xournalpp) to open it, can use text box or draw. Then export it as pdf. To decrypt a pdf: qpdf --password='pwd' --decrypt input.pdf output.pdf To encrypt a pdf: qpdf --encrypt 'pwd' 'pwd' 256 -- input.pdf output.pdf (the first password is to open, the second is to allow modifying/printing/annotating/extracting content)

vc tracking home dir locally

in development

mkdir home && git init --separate-git-dir home $HOME

then in home dir add appropriate .gitignore, something like

*
!.gitignore
!.bashrc
!.bash_profile
!.authinfo
!.Rprofile
!.xinitrc
!.Xmodmap
!.Xresources
!.tmux.conf
!.gitconfig
!.gitignore_global
!.emacs.d/
!.emacs.d/init.el
!.emacs.d/early-init.el
!.emacs.d/config.org
!.emacs.d/eww-bookmarks
!.emacs.d/custom.el
!.emacs.d/elpa/
!.emacs.d/elpa/**
.emacs.d/elpa/**/*.elc
.emacs.d/elpa/**/*.png
.emacs.d/elpa/**/*.pdf

maintenance / rescue

routine maintenance plus the break-glass notes i have actually used.

updating mirrors

from https://wiki.archlinux.org/title/mirrors go to https://archlinux.org/mirrorlist/ to get a new list and replace below (/sudo::/path/to/file for tramp)

cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.backup

updating arch

if invalid or corrupted packages upgrade keyring with sudo pacman -S archlinux-keyring if root partition full error clear cache all except most recent version with sudo paccache -rk1 reference: https://ostechnix.com/recommended-way-clean-package-cache-arch-linux/ if a package conflicts and get asked to remove can check what deps on it via pacman -Qi pkggname

steps are:

  • use sudo lvcreate -L18GB -s -n root_snapshot_$(date +'%Y%m%d') /dev/mapper/vg0-lv_root to save state
  • use sudo pacman -Syu --ignore emacs to upgrade
  • reboot
  • use sudo lvremove /dev/vg0/root_snapshot_20210117 to remove the oldest snapshot

removing packages

wiki

look for them with pacman -Q | grep and remove with their deps not required by others with sudo pacman -Rs pkgname (just pacman -Rs -p pkgname for dry-run) (can also query for orphan/not-needed packages with pacman -Qdt)

troubleshooting / break glass

these are rescue notes from real incidents, not a normal install checklist.

chrooting into lvm desktop system

Use this from the Arch ISO when you need to repair the installed system without booting it (broken bootloader, recover from a botched pacman -Syu, edit user config files that prevent normal login, etc.). The mount paths below should always be verified against the installed system’s /etc/fstab.

Throughout, replace <user> with your installed-system username.

Prerequisites: boot ISO, get wifi, optionally enable sshd

Boot the Arch ISO USB to its root shell, then bring up wifi:

iwctl
station list                          # find wifi interface (usually wlan0)
station wlan0 get-networks
station wlan0 connect YOUR_SSID       # or: iwctl --passphrase "PASS" station wlan0 connect SSID
exit
ping -c 2 archlinux.org               # confirm

Optional but recommended — drive the chroot from another machine over ssh:

passwd                                # set a temp root password on the ISO
systemctl start sshd
ip -br a                              # note the IPv4

# For keyless ssh, append your other machine's public key (whichever you use:
# id_ed25519.pub, id_rsa.pub, etc.) into /root/.ssh/authorized_keys
mkdir -p /root/.ssh
chmod 700 /root/.ssh
# ... paste the public key line into /root/.ssh/authorized_keys ...
chmod 600 /root/.ssh/authorized_keys

Then from the other machine: ssh-keygen -R <ISO_IP> (clear any stale host key from a previous ISO boot) and ssh -o StrictHostKeyChecking=accept-new root@<ISO_IP>.

Activate the LVM volume group

vgscan                                # should list vg0
vgchange -ay                          # activates lv_root, lv_home, any snapshots
lvs                                   # confirm

Mount the partition / LVM stack

Layout (confirm against this system’s /etc/fstab):

DeviceFSMount atfstab path
/dev/nvme0n1p1vfat/mnt/boot/EFI/boot/EFI
/dev/nvme0n1p2ext4/mnt/boot/boot
/dev/vg0/lv_rootext4/mnt/
/dev/vg0/lv_homeext4/mnt/home/home

Critical: the EFI partition mounts at =/boot/EFI= (UPPERCASE), not =/boot/efi=. Match fstab exactly — otherwise grub-install --efi-directory=/mnt/boot/EFI writes to the wrong place and the installed system won’t see your changes.

mount /dev/vg0/lv_root /mnt
mount /dev/nvme0n1p2   /mnt/boot
mount /dev/nvme0n1p1   /mnt/boot/EFI     # UPPERCASE -- see fstab
mount /dev/vg0/lv_home /mnt/home         # always mount; see note below

findmnt -R /mnt                          # verify
ls /mnt/home/<user>/.bashrc              # if "No such file", lv_home isn't mounted right

Always mount lv_home. Without it, /mnt/home/<user>/ is the root LV’s empty placeholder, not the user’s actual home — any edits to files in there silently land in the placeholder and have zero effect on the booted system. Only skip if you’re certain you won’t touch /home (e.g., pure AUR build done in /tmp).

chroot

arch-chroot /mnt

arch-chroot (from arch-install-scripts) automatically bind-mounts /proc, /sys, /dev, /dev/pts, /run, and /sys/firmware/efi/efivars. No manual mount --bind dance needed. If efibootmgr or grub-install later complain about EFI vars, mount | grep efivars and remount if missing: mount -t efivarfs efivarfs /sys/firmware/efi/efivars.

Common operations inside the chroot

  • Edit user files (needs lv_home mounted): /home/<user>/<file>.
  • Recover a botched upgrade:
    rm /var/lib/pacman/db.lck             # if pacman complains "could not lock"
    pacman -Syu                           # or --overwrite '*' if it complains about
                                          # existing files from an interrupted upgrade
        
  • Regenerate initramfs (needs /boot mounted): mkinitcpio -P
  • Rebuild GRUB (needs /boot AND /boot/EFI mounted):
    grub-mkconfig -o /boot/grub/grub.cfg
    grub-install --target=x86_64-efi --efi-directory=/boot/EFI \
                 --bootloader-id=grub_uefi --recheck
    efibootmgr -v                         # confirm the boot entry
        

Clean exit and reboot

exit                                  # leave the chroot shell
cd /                                  # avoid "umount: target is busy"
sync
umount -R /mnt
reboot                                # or  shutdown now

Pull the USB during POST so the installed bootloader takes over on next boot.

Common pitfalls

  • Not mounting =/mnt/boot= before =mkinitcpio -P= or a kernel upgrade. New vmlinuz-* / initramfs-* files land in the root LV’s /boot/ placeholder (shadowed by the real boot partition once normally booted). Symptom: GRUB error file '/initramfs-linux-fallback.img' not found on next boot.
  • Not mounting =/mnt/boot/EFI= before =grub-install=. New grubx64.efi ends up under the root LV and the firmware never sees it.
  • Lowercase =/efi= vs uppercase =/EFI= — same shadow-vs-real problem. Always match fstab.
  • Missing the fallback entry in mkinitcpio presets. If a preset under /etc/mkinitcpio.d/ only has PRESETS=('default'), no fallback initramfs is generated, but GRUB’s auto-generated config still references it. Fix:
    sed -i "s/PRESETS=('default')/PRESETS=('default' 'fallback')/" \
        /etc/mkinitcpio.d/linux.preset    # adjust for whichever kernels you have
    mkinitcpio -P
        
  • Editing files in =/mnt/home/<user>/= without lv_home mounted — silent no-op.

Old x220 laptop (legacy BIOS, single sda root LV — historical note)

BIOS boot, no separate /boot partition, no EFI partition; /boot lives inside the root LV. For that machine: vgchange -ay, mount lv_root + lv_home only (skip /mnt/boot, /mnt/boot/EFI, and the efivars mount), then arch-chroot /mnt.

20250506 upgrade rescue

the commands below were emergency-only after confirming pacman was genuinely wedged mid-upgrade. on old x220 laptop, pacman Syu was mid-upgrading when laptop hung and had to power it off. Followed the chroot instructions to finish running pacman Syu but i had to first do

rm /var/lib/pacman/db.lck

when it complained it could not lock the database, and then

pacman -Syu --overwrite '*'

when it complained that files existed already on system and no packages were upgraded. Then it booted but once i tried to log in exec startx was failing so i had to go back to chroot and use this to comment out those lines

sed -i '11,13 s/^/#/' .bash_profile

once there startx was crashing due to a bunch of corrupt shared objects, e.g.

ldconfig # shows a lot of truncated so in /usr/lib

i could heal one like this:

pacman -Qo /usr/lib/libgs.so # find out owned by ghostscript
sudo pacman -Sw ghostscript # redownload ghostscript
sudo pacman -U --noconfirm --overwrite '*' /var/cache/pacman/pkg/ghostscript-10.04.0-1-x86_64.pkg.tar.zst # reinstall it

so i repeated that for the rest of them. Eventually was left with only “empty file” libm17n* shared objects, i deleted them. Then emacs wouldnt start so i did the above (-Sw followed by -U) for the m17n-db and m17n-lib packages and then both emacs and startx were all healed

20241110 upgrade rescue

ran

grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck
grub-mkconfig -o /boot/grub/grub.cfg

above worked, i was able to confirm it looked sane by running efibootmgr -v i could see the grub_uefi as the first option and it seemed to point to the right place. (stack exchange solution thread)