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)
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, andefibootmgr -v
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
exitto 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 abovemostly 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.
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 truenext
pacman -Sy #sync latest
fdisk /dev/sdx #your disk - type g for a new GPT partition tablemake 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 #Bootfor 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 -aynext 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/homewith 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 /mntfirst set the timezone and hwclock
ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohcname 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 NetworkManagernow edit /etc/mkinitcpio.conf and in HOOKS between block and filesystems add lvm2 entry
and then one can run
mkinitcpio -Pgenerate 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/fstabready to go at this point so exit; umount -R /mnt; reboot
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 nslookupif old laptop also grab linux-firmware
get sensors to be able to monitor system
sudo pacman -S lm_sensors
sudo sensors-detectinstall 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.confuse 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 ~/.gitignorethis is the main path i want to follow on a fresh machine.
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 truewill 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/cryptrootmount /dev/mapper/cryptroot /mnt
mount --mkdir /dev/nvme0n1p1 /mnt/efi
mount --mkdir /dev/nvme0n1p2 /mnt/bootuncomment 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 itinstall 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-ucodegenfstab -U /mnt >> /mnt/etc/fstab
arch-chroot /mntfallocate -l 38G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap defaults 0 0' >> /etc/fstabln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
hwclock --systohc # generates /etc/adjtime
systemctl enable systemd-timesyncd.servicelocale-gen # after uncomment en_US.UTF-8 UTF-8 from /etc/locale.gencreate /etc/locale.conf with content LANG=en_US.UTF-8
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
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
systemctl enable NetworkManageredit /etc/mkinitcpio.conf in the HOOKS line and add encrypt between block and filesystems
regenerate mkinitcpio -P
grub-install --efi-directory=/efi --boot-directory=/boot --target=x86_64-efi --bootloader-id=grub_uefi --recheckbecause 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 nvme0n1p3then 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 tooexit chroot and reboot into new system
exit
umount -R /mnt
reboot # remove the usb nownot 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/nvmefor 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 Monospacebootstrap 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 gitconfigedit /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 Bthen
sudo grub-mkconfig -o /boot/grub/grub.cfgto 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 lostcontrol behaviors in /etc/systemd/logind.conf then bounce the daemon sudo systemctl restart systemd-logind
| link | notes |
| 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 |
these are not required to get Arch installed; they are the extras i usually add on my own machines.
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 -bsudo pacman -S openbox obconf
# mkdir p ~/.config && cp -r ~/development/dotfiles/.config/openbox ~/.config/ # if bootstrapping from githubthen add exec openbox-session to bottom of xinitrc
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 existingto purge an old snapshot
sudo lvremove /dev/vg0/root_snapshot_YYYYMMDDyou can check volume group stats (like free space) with sudo vgs
use xprop | grep CLASS command (package xorg-xprop) to click on windows and see their class names
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)
youtube source: https://www.youtube.com/watch?v=O-wIUZaywBc
install this package:
sudo pacman -S networkmanager-openvpngo 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-appletthen 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
Useful packages to have on any system
| Package | Notes | Command |
|---|---|---|
| isync | yields mbsync used by mu4e to pull email | sudo pacman -S isync |
| mu-git | mu and mu4e in AUR | git clone https://aur.archlinux.org/mu.git then makepkg -si |
| virtualbox | needs AUR extension | sudo pacman -S virtualbox git git clone https://aur.archlinux.org/virtualbox-ext-oracle.git |
| telegram-desktop | sudo pacman -S telegram-desktop | |
| telega | emacs equivalent (see packageNotes.org) | AUR for tdlib, git from src for the rest (incuding a C server) |
| mlocate | for updatedb to do custom helm locates | sudo pacman -S mlocate |
| ctags | to generate TAGS | sudo pacman -S ctags |
| clang | llvm frontend | sudo pacman -S clang |
| llvm | llvm libs | sudo pacman -S llvm |
| lsof | sudo pacman -S lsof | |
| strace | sudo pacman -S strace | |
| valgrind | sudo pacman -S valgrind | |
| stdman | c++11/14 man pages | git clone https://aur.archlinux.org/stdman-git.git then makepkg -si |
| python-black | /usr/bin/black | sudo pacman -S python-black |
| python-pip | sudo pacman -S python-pip | |
| jupyterlab | for elpy use of course | sudo pacman -S jupyterlab |
| perf | perf events | sudo pacman -S perf |
| peek | gif recorder | sudo pacman -S peek |
| ghostscript | pdf manip | sudo pacman -S ghostscript |
| pdftk | pdf manip | sudo pacman -S pdftk |
| libvterm | for vterm in emacs | sudo pacman -S libvterm |
| texlive | covers needs for tex | sudo pacman -S texlive |
| qpdf | encrypt/decrypt pdfs | sudo pacman -S qpdf |
| xournalpp | annotate pdfs (e.g. to sign them) | sudo pacman -S xournalpp |
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)
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 donefor 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)
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)
in development
mkdir home && git init --separate-git-dir home $HOMEthen 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
routine maintenance plus the break-glass notes i have actually used.
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.backupif 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_rootto save state - use
sudo pacman -Syu --ignore emacsto upgrade - reboot
- use
sudo lvremove /dev/vg0/root_snapshot_20210117to remove the oldest snapshot
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)
these are rescue notes from real incidents, not a normal install checklist.
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.
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 # confirmOptional 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_keysThen 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>.
vgscan # should list vg0
vgchange -ay # activates lv_root, lv_home, any snapshots
lvs # confirmLayout (confirm against this system’s /etc/fstab):
| Device | FS | Mount at | fstab path |
|---|---|---|---|
| /dev/nvme0n1p1 | vfat | /mnt/boot/EFI | /boot/EFI |
| /dev/nvme0n1p2 | ext4 | /mnt/boot | /boot |
| /dev/vg0/lv_root | ext4 | /mnt | / |
| /dev/vg0/lv_home | ext4 | /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 rightAlways 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).
arch-chroot /mntarch-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.
- 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
exit # leave the chroot shell
cd / # avoid "umount: target is busy"
sync
umount -R /mnt
reboot # or shutdown nowPull the USB during POST so the installed bootloader takes over on next boot.
- 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 errorfile '/initramfs-linux-fallback.img' not foundon next boot. - Not mounting =/mnt/boot/EFI= before =grub-install=. New
grubx64.efiends 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 hasPRESETS=('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.
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.
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.lckwhen 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_profileonce there startx was crashing due to a bunch of corrupt shared objects, e.g.
ldconfig # shows a lot of truncated so in /usr/libi 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 itso 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
ran
grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck
grub-mkconfig -o /boot/grub/grub.cfgabove 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)