This guide is licensed under the GNU Free Documentation License 1.3, it is originally uploaded to codeberg and github.
Configuration files with my installation can be found on codeberg and github(You might see few files linking to ./dotfiles/path/to/file, its in this repository).
Most of the post-install configuration can be automated by running my post-install script AT YOUR OWN RISK:
partition:
- LVM on LUKS
- Hibernation to encrypted swap partition
boot:
- Firmware: UEFI
- Bootloader: systemd-boot
- Secure Boot: sbctl
- initramfs: mkinitcpio with systemd
NAME SIZE TYPE MOUNTPOINTS
nvme1n1 931.5G disk
└─nvme1n1p1 931.5G part
└─cryptdata 931.5G crypt /data
nvme0n1 476.9G disk
├─nvme0n1p1 1G part /boot
├─nvme0n1p2 76G part
│ └─cryptlvm 76G crypt
│ ├─vg0-swap 16G lvm [SWAP]
│ └─vg0-root 60G lvm /
└─nvme0n1p3 399.9G part
└─crypthome 399.9G crypt /home
window manager & Wayland compositor options:
| display protocols | window manager / compositor |
|---|---|
| Wayland | dwl · kwm · river-classic · sway |
| X11 | dwm · i3wm |
Verify the PGP signature
# You might need to change DNS resolve e.g. `1.1.1.1` if you have trouble # connecting to a key server, or manually download Arch developer's public key: # You can visit Pierre's website for details: https://pierre-schmitz.com/gpg-keys/ gpg --keyserver-options auto-key-retrieve --verify archlinux-version-x86_64.iso.sig # or on an existing arch system pacman-key -v archlinux-version-x86_64.iso.sig
Bootable ISO USB drive created with ventoy-1.0.99
set -o visetfont /usr/share/kbd/consolefonts/iso01-12x22.psfu.gz
1.3 connect to wifi (hidden)
# get full manual of iwct iwctl help | less -R # list network interface for <device> name iwctl device list # connect hidden wifi iwctl --passphrase <passphrase> station <device> connect-hidden <ssid> # check connection ip a ping -c 3 archlinux.org
timedatectl set-timezone Region/City
# check NTP (unsynchronized time could cause package installing issues)
timedatectlSkip this step when reinstall Arch to a disk with the old partitions.
# read `fdisk`'s manual fdisk /dev/nvme0n1 <<< m | less # `<<<` is the "here string", this command send `m` to `fdisk /dev/nvme0n1` and # pipe to `less`, useful when console screen isn't enough # Use the following `fdisk` subcommands to perform partitioning # `p` print # `F` Free # `d` delete # `n` new # `t` type # `w` write # `q` quit
The partition type for /boot need to be changed to ESP, for bootctl update to work.
# format the bootloader's partition mkfs.fat -F 32 /dev/nvme0n1p1 # format the encrypt partitions cryptsetup luksFormat /dev/nvme0n1p2 # unlock the encrypted partitions cryptsetup open /dev/nvme0n1p2 cryptlvm cryptsetup open /dev/nvme0n1p3 crypthome cryptsetup open /dev/nvme1n1p1 cryptdata # create physical volume for LVM on the top of the LUKS container pvcreate /dev/mapper/cryptlvm # check with pvdisplay pvdisplay # create the volume group for LVM, name it `vg0` vgcreate vg0 /dev/mapper/cryptlvm # check with vgdisplay vgdisplay # create the logical volumes inside the volume group lvcreate -L 16G -n swap vg0 lvcreate -l 100%FREE -n root vg0 # check with lvdisplay lvdisplay # format the logical volumes for root mkfs.ext4 /dev/vg0/root # or mkfs.ext4 /dev/mapper/vg0-root # both paths links to the same device `/dev/dm-2 # format the logical volumes for swap mkswap /dev/vg0/swap # format the crypted home mkfs.ext4 /dev/mapper/crypthome
# mount root (ext4 on lvm on luks) mount /dev/vg0/root /mnt # create mount points for other partitions mkdir -p /mnt/{boot,home,data} # mount boot (esp, not encrypted because of secure boot) mount /dev/nvme0n1p1 /mnt/boot # mount home (ext4 on luks) mount /dev/mapper/crypthome /mnt/home # mount data (ext4 on luks on another ssd) mount /dev/mapper/cryptdata /mnt/data # enable swap (swap on lvm on luks) swapon /dev/vg0/swap
# config pacman sed -i '/^#Color$/s/#//' /etc/pacman.conf sed -i '/^#ParallelDownloads = 5/s/#//' /etc/pacman.conf # change mirrorlist priority reflector --save /etc/pacman.d/mirrorlist # update keyring pacman -Sy && pacman -S archlinux-keyring # When you use an Arch Linux ISO that was released months ago, the included # keyring may be outdated. The Arch Linux keyring contains the public keys used # to verify the signatures of packages. # install packages pacstrap -K /mnt base base-devel linux linux-headers linux-firmware fwupd intel-ucode lvm2 vim neovim networkmanager man-db man-pages bash-completion # explaining packages # base minimal package set to define a basic arch linux # installation # base-devel basic tools to build arch linux packages # linux the kernel # intel-ucode ucode for intel cpu, amd cpu install `amd-ucode` # lvm2 if this package is not installed, root filesystem on the # logical volume won't be able to be used # man-db database for `man` # bash-completion completion for sub-commands
genfstab -U /mnt >> /mnt/etc/fstabarch-chroot /mnt
set -o vi# make a symbolic link to a timezone ln -sf /usr/share/zoneinfo/Region/City /etc/localtime # sync system time to the hardware clock on the computer's motherboard hwclock --systohc
uncomment in /etc/locale.gen
sed -i '/^#en_US.UTF-8/s/^#//' /etc/locale.genGenerate locales
locale-gen
append /etc/locale.conf
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
# replace `fx507` with your hostname echo 'fx507' > /etc/hostname
edit /etc/hosts into:
# replace `fx507` with your hostname
127.0.0.1 localhost
::1 localhost
127.0.1.1 fx507.localdomain fx507
cd /root # generate a ramdon 4096 byte key file dd if=/dev/urandom of=/root/cryptkey bs=1024 count=4 # read-only chmod 400 cryptkey # immutable chattr +i cryptkey cryptsetup luksAddKey /dev/nvme0n1p3 /root/cryptkey # get UUIDs echo '#'$(blkid | grep '/dev/nvme0n1p3') >> /etc/crypttab
edit /etc/crypttab
#<mapper_name> UUID=<uuid> <password> <options>
crypthome UUID=abcd-1234-xyz /root/cryptkey luks,discard
If you are re-using the existing LUKS container and have obsoleted keys:
# list all key slots cryptsetup luksDump /dev/nvme0n1p3 | less # kill slot 1 for instance cryptsetup luksKillSlot /dev/nvme0n1p3 1 # you will be prompted for the key's password, # and you cannot kill a key with its own password
This guide is switching to systemd-based initramfs, for more details see the hook list.
Edit hooks in /etc/mkinitcpio.conf, note that the hooks order does matter.
# remove: # - kms (disable early KMS start to avoid resolution change while sd-encrypt # prompting passphrase) # add: # - sd-encrypt # _ lvm2 HOOKS=(base systemd autodetect microcode modconf keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)
Then build initramfs image(s) according to all presets.
# create a dummy vconsole.conf to avoid mknitcpio errors if needed
touch /etc/vconsole.conf
mkinitcpio -P# create root password passwd # create new user, adding to the wheel group, creating home directory if # not existing useradd -G wheel -m nate passwd nate # allow users of wheel group to use sudo visudo
uncomment
-#%wheel ALL=(ALL:ALL) ALL +%wheel ALL=(ALL:ALL) ALL
# install systemd-boot to `/boot`
bootctl installedit /boot/loader/loader.conf
default arch.conf
timeout 3
console-mode 0
get encrypted device and root partition UUID
# get UUID of the encrypted physical volume echo '#'$(blkid | grep 'nvme0n1p2') > /boot/loader/entries/arch.conf # get UUID of the logic volume of root echo '#'$(blkid | grep 'vg0-root') >> /boot/loader/entries/arch.conf
edit /boot/loader/entries/arch.conf, replace the UUID with the actual ones.
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options rd.luks.name=275798bf-a33c-4cde-a489-625a3957899f=cryptlvm root=UUID=91e69c07-65c4-4fb9-b51e-448fe20564a3 modprobe.blacklist=pcspkr
- If another kernel is installed, change
/vmlinuz-linux. - If the device is not encrypted, omit
rd.luks.name=<uuid>=cryptlvm. - Add
modprobe.blacklist=pcspkrormodule.blacklist=pcspkrto disable PC speaker on Thinkpad. - A separate
initrdfor microcode is unnecessary since mkinitcpio v38.
enable systemd-boot's auto update
systemctl enable systemd-boot-update.service`
# leave chroot exit # unmount partitions umount -R /mnt swapoff -a # leave archiso reboot
login as root
setfont -d
2.2 enable networkmanager and connect to hidden wifi
systemctl enable --now NetworkManager.service # run the following twice, as the first attemp would fail for ssid not found nmcli device wifi connect <ssid> password <password> hidden yes
# export installed packages to a list file pacman -Qmq | sort > "$HEART"/aur.list pacman -Qenq | sort > "$HEART"/arch.list # install packages from a package list ARCH_LIST="/path/to/arch.list" [ -f "$ARCH_LIST" ] && pacman -S --noconfirm --needed $(cat "$ARCH_LIST") 2>/dev/null
official repo packages[aur packages]<source packages>
### base dash zsh zsh-syntax-highlighting vim neovim lf fzf <dvtm> <abduco> git rsync openssh openbsd-netcat udisks2 zip unzip 7zip unrar-free stow tree bc calc pacman-contrib archlinux-contrib arch-wiki-docs rebuild-detector arch-install-scripts dosfstools exfat-utils wget [yay] ### system networkmanager brightnessctl tlp ufw firejail cronie bluez-utils bluetui efibootmgr sbctl ### monitoring btop ncdu iftop sysstat smartmontools powertop ### file sharing android-tools android-file-transfer samba qrtool ### web browser w3m qutebrowser python-adblock ### wayland foot wlr-randr kanshi wl-clipboard cliphist wf-recorder wl-mirror [wshowkeys-mao-git] swaybg swayidle waylock wmenu <mew> wtype libnotify dunst gammastep slurp grim wob wev [lswt] fcft tllist wayland-protocols [wlrctl] sway wlroots 0.19 <river-classic> <dam> <river-shifttags> <river> <kwm> <dwl> wlroots 0.18 ### xorg xorg-server xorg-xinit xorg-xrandr xorg-xsetroot xorg-xset xsel xwallpaper xorg-xkill xorg-xev xorg-xinput unclutter xss-lock xdotool slock picom redshift clipmenu maim slop autorandr screenkey i3-wm <dwm> <st> <dmenu> <nsxiv> <xob> <xbanish> ### audio server pipewire pipewire-alsa pipewire-pulse pipewire-jack noise-suppression-for-voice pulsemixer ### fonts adobe-source-code-pro-fonts noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra woff2-font-awesome ttf-nerd-fonts-symbols ### file viewer swayimg zathura zathura-pdf-mupdf bat catimg chafa lsix gnome-epub-thumbnailer poppler ffmpegthumbnailer odt2txt ### multi-media player mpv ncmpcpp mpd mpc ### multi-media editor ffmpeg python-mutagen imagemagick mediainfo perl-image-exiftool perl-rename kdenlive gimp ### virtualization virt-manager qemu-base libvirt virt-install dnsmasq openbsd-netcat qemu-hw-display-qxl qemu-hw-display-virtio-gpu qemu-hw-display-virtio-gpu-pci qemu-chardev-spice qemu-audio-spice ### IME fcitx5 fcitx5-chinese-addons fcitx5-configtool fcitx5-gtk fcitx5-qt fcitx5-anthy [fcitx5-skin-fluentdark-git] ### downloader & torrent yt-dlp yt-dlp-ejs transmission-cli httrack ### personal tools newsboat task calcurse ttyper dict [dict-gcide] [dict-wn] ### offline email neomutt isync *cyrus-sasl-xoauth2-git* ### coding jdk-openjdk openjdk-src openjdk-doc xorg-xwayland xwayland-satellite zig scdoc meson nodejs tree-sitter-cli code npm jdk21-openjdk openjdk21-doc openjdk21-src ## 2.3.1 ### themes qt6ct gnome-themes-extra [adwaita-qt5-git] [adwaita-qtr-git] ### nvidia nvidia-open nvidia-utils nvtop > [!Note] > The nvidia-open driver regression introduced since `580.105.08` causes > system hibernation not reaching ACPI S4 power-off on my ASUS > laptop(Intel iGPU + Nvidia dGPU) with Arch Linux. The screen turns off > but not the fans keep spinning forever. > > There's no trouble in writing the RAM into swap and resuming from the > image, after long pressing the power button to power off the laptop and > manually power it on. > > The issues happens among `580.105.08`, `580.119.02`, `590.48.01`, which > lasts for more than a month, and is not caused by kernels but Nvidia > drivers. > > A workaround is to switch to an older version of dkms drivers > (`580.95.05`) and ignore the driver update until the regression is > fixed. > > See: > - https://forums.developer.nvidia.com/t/580-105-08-regression-hibernate-s4-no-longer-powers-off-fans-stay-on-resume-still-works/351504 > - https://archive.archlinux.org/packages/n/nvidia-open/ > - https://archive.archlinux.org/packages/n/nvidia-utils/ ### office libreoffice-still
git clone https://aur.archlinux.org/yay.git
makepkg
sudo pacman -U yay-*.pkg.tar.zstwhich automates most of the rest steps
# clone my dotfiles repo and run
./install-pkgs.sh --install --base
sudo ./dotfiles/install-root.sh
./install-user.shedit /etc/vconsole.conf
FONT=iso01-12x22
# for HiDPI:
FONT=latarcyrheb-sun32
set -o viremove the ~/.bash_profile if exist as ~/.bash_profile would override
~/.profile
-
reboot into UEFI utilities, restore secure boot's factory keys, and enter
setup mode -
boot into system, check
sbctl status, you should see:
Installed: ✘ Sbctl is not installed
Setup Mode: ✘ Enabled
Secure Boot: ✘ Disabled
- create your own keys
sbctl create-keys
- enroll the keys, along with microsoft keys if need dual boot with Windows
sbctl enroll-keys --microsoft
- sign files:
sudo sbctl sign-all sudo sbctl sign -s /boot/EFI/systemd/systemd-bootx64.efi sudo sbctl sign -s /boot/EFI/BOOT/BOOTX64.EFI sudo sbctl sign -s /boot/vmlinuz-linux sudo sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi sudo sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi
-
reboot into UEFI utilities, secure boot should be enabled automatically, if not, do it manually instead
-
boot into system, check
sbctl status, you should see:
Installed: ✓ sbctl is installed
Setup Mode: ✓ Disabled
Secure Boot: ✓ Enabled
Vendor Keys: microsoft
- make sure
systemd-boot-update.serviceis enabled for auto signing the future bootloaders and kernels, for more details see arch wiki.
# remove unused packages weekly by `paccache` command from `pacman-contrib` # package. (default keeps the last 3 versions of a package) systemctl enable --now paccache.timer
uncomment in /etc/tlp.conf
-#STOP_CHARGE_THRESH_BAT1=80 +STOP_CHARGE_THRESH_BAT1=80
start tlp service
sudo systemctl enable --now tlp.servicesudo mandb
# import calendar data file calcurse -i ~/.config/calcurse/calendar.ical
cp ./dotfiles/smb.conf /etc/samba/smb.conf # or curl 'https://git.samba.org/samba.git/?p=samba.git;a=blob_plain;f=examples/smb.conf.default' sudo tee /etc/samba/smb.conf # adding a linux user to samba server sudo smbpasswd -a nate # enable smb service sudo systemctl enable --now smb.service
systemctl enable --now systemd-timesyncd.service timedatectl set-ntp true
edit /etc/ssh/sshd_config
-#PasswordAuthentication no +PasswordAuthentication no
# restart sshd systemctl enable --now sshd.service
systemctl enable --now --user ssh-agent.serviceIf this is a system that you would like to ssh into:
# change directory to where the pub key locates cd ~/.ssh # use smbclient to move pub key to ssh server, replace `nate` with username smbclient //192.168.xx.xx/smb -U nate # `-U nate` can be omitted if samba server's user name is the same # share name shall be identical in /etc/samba/smb.conf like [smb]
in smbclient shell:
# copy the local file to the server
put ~/.ssh/id_rsa.pub
on the samba server
# import pub key for sshd cat ~/smb/id_rsa.pub >> ~/.ssh/authorized_keys sudo systemctl restart sshd.service
If you want to use termux for rsync over ssh on android:
# create termux user for syncing files to android phone sudo useradd -m termux # add user termux to the nate group sudo usermod -aG nate termux # on termux copy `~/.ssh/id_rsa.pub`, write to clipboard.txt on smb share # For wayland, copy to paste cat ~/smb/clipboard.txt | wl-copy # change user to termux with sudo (NEVER create a password for termux user!) sudo su - termux mkdir ~/.ssh # import pub key to server echo "<paste pub key here>" > .ssh/authorized_keys # restart ssh server sudo systemctl restart sshd.service
# make home directory r-x for group nate chmod 750 ~ # make directories for sharing r-x for group nate chmod g+rx ~/doc ~/pic ~/mus ~/vid ~/repo # remove all permisions for other directories for group nate chmod g-rwx ~/.config ~/.local ~/.ssh ~/mnt ~/smb # to sync to android phone, run the following in termux: rsync -avh --delete --progress --ignore-errors --exclude .git termux@192.168.xx.xx:/home/nate/{doc,mus,pic,vid} storage/shared/back/
# allow incoming trafic from LAN through ssh port sudo ufw allow from 192.168.0.0/16 to any app SSH # allow incoming trafic from LAN through CIFS port for Samba server: sudo ufw allow from 192.168.0.0/16 to any app CIFS # enable ufw sudo ufw enable sudo systemctl enable --now ufw.service
# comment out `mkdir` lines to disable creating empty directories on starting # up softwares sudo vim /etc/firejail/newsboat.profile sudo vim /etc/firejail/neomutt.profile # start firejail sudo firecfg
sudo usermod nate -aG kvm,libvirt (take effect on relog)
sudo ufw allow in on virbr0 from any to anyedit /etc/libvirt/network.conf
firewall_backend = "iptables"
sudo systemctl enable --now libvirtd
sudo virsh net-define /etc/libvirt/qemu/networks/default.xml
sudo virsh net-autostart defaultuncomment in /etc/firejail/firecfg.config to fix libvirt/qemu network issue
-dnsmasq +#dnsmasq
set libvirt-qemu dir perms
ln -s /data/virt ~/virt
chmod 750 /data/virt
setfacl -m u:libvirt-qemu:x /data/virt# make sure xdg-desktop-portal package is installed and run: gsettings set org.gnome.desktop.interface gtk-theme "Adwaita-dark"
sudo systemctl enable nvidia-suspend.service sudo systemctl enable nvidia-hibernate.service sudo systemctl enable nvidia-resume.service sudo systemctl enable nvidia-powerd.service
sudo cp /etc/systemd/logind.conf /etc/systemd/logind.conf~
edit /etc/systemd/logind.conf
-#HandlePowerKey=poweroff +HandlePowerKey=hibernate
# a pacman [HOOK](./dotfiles/etc/pacman.d/hooks/default-shell-symlink.hook) is needed to # reassign symlink after every bash upgrade sudo ln -sf /usr/bin/dash /usr/bin/sh chsh -s /usr/bin/zsh
crontab ~/doc/heart/.config/crontab.backup sudo systemctl enable --now cronie.service
:PlugInstall
systemctl enable --now bluetooth.service# add user nate to seat group to have access to seat socket in a GUI environment sudo usermod -aG seat nate systemctl enable --now seatd.service
# unlock and mount the backup disk udisksctl unlock -b /dev/sdx1 udisksctl mount -b /dev/dm-x # sync to home directory rsync -avh --delete --progress /run/media/nate/usb-ssd0/back/{aur,doc,mus,pic,repo,vid} /home/nate/ # unmount and lock the device udisksctl unmount -b /dev/dm-x udisksctl lock -b /dev/sdx1 udisksctl poweroff -b /dev/sdx