Skip to content

Instantly share code, notes, and snippets.

@FixeQD
Last active May 2, 2026 00:02
Show Gist options
  • Select an option

  • Save FixeQD/7fd980fbc2f385f0008f3a72a797cbe1 to your computer and use it in GitHub Desktop.

Select an option

Save FixeQD/7fd980fbc2f385f0008f3a72a797cbe1 to your computer and use it in GitHub Desktop.
My Arch Installation Cheat Sheet, so I won't mess it up.

My Artix + dinit Installation Cheat Sheet

Personal reference, but feel free to steal it. UEFI + GPT + btrfs subvolumes on linux-zen. NVMe optimized. dinit as PID 1, no systemd anywhere.

Warning

Everything gets wiped. Run lsblk first and confirm your NVMe name - usually /dev/nvme0n1, but verify.

This uses the Artix Linux ISO, not Arch. Same AUR, same packages, same rolling release, no systemd. Download from artixlinux.org.


0. Pre-Flight

loadkeys pl
ping -c 1 artixlinux.org
reflector --country Poland,Germany --age 12 --protocol https --sort rate --save /etc/pacman.d/mirrorlist

1. Partition the Disk

cfdisk /dev/nvme0n1
Partition Size Type Purpose
/dev/nvme0n1p1 512M EFI System ESP - mounted at /boot, kernel lives here
/dev/nvme0n1p2 32G Linux swap Hibernation target - match your RAM
/dev/nvme0n1p3 Rest Linux filesystem btrfs

Note

Swap stays even with ZRAM. ZRAM is the fast in-RAM layer, NVMe swap is the hibernation target. You can't hibernate to ZRAM.


2. Format & btrfs Subvolume Setup

mkfs.fat -F32 /dev/nvme0n1p1
mkswap /dev/nvme0n1p2 && swapon /dev/nvme0n1p2
mkfs.btrfs -f -L artix /dev/nvme0n1p3

Mount temporarily and create subvolumes:

mount /dev/nvme0n1p3 /mnt

btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@opt
btrfs subvolume create /mnt/@var_log
btrfs subvolume create /mnt/@pkg
btrfs subvolume create /mnt/@snapshots

umount /mnt

Note

/var stays inside @ so rollbacks stay consistent. Only /var/log and /var/cache/pacman/pkg are separate - logs and package cache should survive a snapshot restore.

Mount with NVMe-optimized options:

mount -o noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvol=@ /dev/nvme0n1p3 /mnt

Note

compress=zstd:1 - level 1 instead of default 3. On fast NVMe the CPU is the compression bottleneck, not I/O. Level 1 gives ~80% of the savings at 2-3x the throughput.

mkdir -pv /mnt/{boot,home,opt,.snapshots}
mkdir -pv /mnt/var/log /mnt/var/cache/pacman/pkg

mount /dev/nvme0n1p1 /mnt/boot
mount -o noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvol=@home      /dev/nvme0n1p3 /mnt/home
mount -o noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvol=@opt       /dev/nvme0n1p3 /mnt/opt
mount -o noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvol=@var_log   /dev/nvme0n1p3 /mnt/var/log
mount -o noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvol=@pkg       /dev/nvme0n1p3 /mnt/var/cache/pacman/pkg
mount -o noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvol=@snapshots /dev/nvme0n1p3 /mnt/.snapshots

lsblk -f

3. Install Base System

grep -m1 "vendor_id" /proc/cpuinfo   # GenuineIntel or AuthenticAMD

Note

Artix uses basestrap instead of pacstrap.

Intel:

basestrap /mnt base base-devel linux-zen linux-zen-headers linux-firmware \
  intel-ucode sudo btrfs-progs reflector nvim \
  dinit elogind-dinit \
  networkmanager networkmanager-dinit \
  cronie cronie-dinit \
  booster

AMD:

basestrap /mnt base base-devel linux-zen linux-zen-headers linux-firmware \
  amd-ucode sudo btrfs-progs reflector nvim \
  dinit elogind-dinit \
  networkmanager networkmanager-dinit \
  cronie cronie-dinit \
  booster

Tip

Why linux-zen? Lower-latency scheduler, better for desktop and real-time workloads than vanilla linux.

Important

NVIDIA: Use nvidia-dkms, not nvidia. The nvidia package only builds against linux, the module won't exist on linux-zen.

basestrap /mnt nvidia-dkms nvidia-utils

Add to /etc/booster.yaml after chroot:

modules_force_load: nvidia,nvidia_modeset,nvidia_uvm,nvidia_drm

4. fstab

Note

Artix uses fstabgen instead of genfstab.

fstabgen -U /mnt >> /mnt/etc/fstab
cat /mnt/etc/fstab   # verify all subvolumes and UUIDs
echo 'tmpfs /tmp tmpfs rw,nosuid,nodev,relatime,size=4G,mode=1777 0 0' >> /mnt/etc/fstab

5. chroot & Configure

artix-chroot /mnt /bin/bash

Locale, keyboard, timezone, hostname

nvim /etc/locale.gen   # uncomment pl_PL.UTF-8 UTF-8
locale-gen
echo LANG=pl_PL.UTF-8 > /etc/locale.conf
echo KEYMAP=pl > /etc/vconsole.conf
ln -sf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
hwclock --systohc --utc
echo HP-Zbook > /etc/hostname

Network

ln -s /etc/dinit.d/NetworkManager /etc/dinit.d/boot.d/

Artix + Arch Repos

pacman -S artix-archlinux-support

Add to /etc/pacman.conf after [galaxy]:

[extra]
Include = /etc/pacman.d/mirrorlist-arch
[multilib]
Include = /etc/pacman.d/mirrorlist-arch

Important

Artix repos (system, world, galaxy) must always be above Arch repos in pacman.conf. Never enable Arch's [core] - it's replaced by [system] and will break everything.

pacman -Sy

Mirrors

No reflector.timer without systemd, use cronie:

ln -s /etc/dinit.d/cronie /etc/dinit.d/boot.d/
echo '@weekly root /usr/bin/reflector --country Poland,Germany --age 12 --protocol https --sort rate --save /etc/pacman.d/mirrorlist' >> /etc/cron.d/reflector

Chaotic AUR (optional)

pacman-key --recv-key 3056513887B78AEB --keyserver keyserver.ubuntu.com
pacman-key --lsign-key 3056513887B78AEB
pacman -U 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst'
pacman -U 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst'

Add to /etc/pacman.conf below Artix repos, above Arch:

[chaotic-aur]
Include = /etc/pacman.d/chaotic-mirrorlist
pacman -Sy

6. initramfs - booster

Replaces mkinitcpio. Written in Go, faster generation, leaner early userspace, auto-embeds CPU microcode - no separate ucode entry needed in the bootloader.

nvim /etc/booster.yaml
compression: zstd
extra_files: busybox,fsck,fsck.btrfs

Note

Booster runs automatically via pacman hook on install and every kernel update. No manual build needed.


7. Bootloader - EFISTUB

No bootloader at all. UEFI loads the kernel directly. ESP is mounted at /boot so vmlinuz and initrd sit on the FAT32 partition and UEFI can read them natively.

Get your UUIDs first:

blkid /dev/nvme0n1p3   # btrfs root - UUID=
blkid /dev/nvme0n1p2   # swap - UUID=

Register the boot entry:

efibootmgr -c -d /dev/nvme0n1 -p 1 -L "Artix Linux" \
  -l /vmlinuz-linux-zen \
  -u "root=UUID=<btrfs-uuid> rootflags=subvol=@ rw rootfstype=btrfs quiet loglevel=3 resume=UUID=<swap-uuid> zswap.enabled=0 initrd=\intel-ucode.img initrd=\booster-linux-zen.img"

AMD - swap intel-ucode.img for amd-ucode.img.

Important

NVIDIA + Wayland: Add nvidia-drm.modeset=1 to the -u string.

Verify the entry was created:

efibootmgr -v

Note

Secure Boot: Sign the kernel and initrd with sbctl.

sbctl create-keys
sbctl enroll-keys -m
sbctl sign -s /boot/vmlinuz-linux-zen
sbctl sign -s /boot/booster-linux-zen.img

sbctl has a pacman hook that re-signs automatically on kernel updates.


8. Kernel & System Tweaks

ZRAM

pacman -S zramen zramen-dinit
nvim /etc/zramen.conf
ZRAMEN_SIZE=half
ZRAMEN_ALGO=zstd
ln -s /etc/dinit.d/zramen /etc/dinit.d/boot.d/

Note

half = half your RAM as ZRAM. On 32GB that's 16GB. zstd compresses further so effective capacity is higher. ZRAM gets higher swap priority than NVMe automatically.

sysctl - Swappiness + Write Latency

Default vm.dirty_ratio=20% on 32GB = ~6GB dirty pages before flush. That destroys desktop latency. Use absolute byte limits instead:

mkdir -p /etc/sysctl.d
cat > /etc/sysctl.d/99-performance.conf << EOF
vm.swappiness=180
vm.page-cluster=0
vm.dirty_background_bytes=67108864
vm.dirty_bytes=268435456
vm.dirty_expire_centisecs=3000
vm.dirty_writeback_centisecs=1500
EOF

Note

Background flush starts at 64MB dirty, hard cap at 256MB. On NVMe writing 3-5GB/s this is milliseconds of stall, not seconds.

NVMe I/O Scheduler

NVMe has its own internal queue, a software scheduler only adds overhead:

echo 'ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"' > /etc/udev/rules.d/60-ioscheduler.rules

Periodic TRIM

discard=async handles per-op TRIM. Monthly batch as a backup:

echo '@monthly root /usr/bin/fstrim -av' >> /etc/cron.d/fstrim

9. Root Password

passwd

10. Enable elogind

Handles seat management, power keys, session tracking. Required by Hyprland and most DEs.

ln -s /etc/dinit.d/elogind /etc/dinit.d/boot.d/

11. Exit & Reboot

exit
umount -R /mnt
swapoff /dev/nvme0n1p2
reboot

12. Post-Boot

User + sudo

useradd -m -G wheel,storage,power,audio,video,optical,network -s /bin/bash fixeq
passwd fixeq
EDITOR=nvim visudo   # uncomment: %wheel ALL=(ALL:ALL) ALL
sudo pacman -Syu

Note

From this point dinit is running as PID 1, so use dinitctl enable instead of manual symlinks - it does the same thing but properly.

AUR Helper

sudo pacman -S paru

Session Management - turnstile + dbus

turnstile handles user session activation (replaces systemd --user). dbus needs to run both system-wide and per-user.

sudo pacman -S turnstile turnstile-dinit dbus-dinit dbus-dinit-user
sudo dinitctl enable turnstiled

Reboot, then enable dbus for both system and user:

sudo dinitctl enable dbus
dinitctl enable dbus

Audio - PipeWire

sudo pacman -S pipewire pipewire-jack pipewire-pulse wireplumber \
  pipewire-dinit pipewire-pulse-dinit wireplumber-dinit

Enable system-wide and per-user:

sudo dinitctl enable pipewire
dinitctl enable pipewire
sudo dinitctl enable wireplumber
dinitctl enable wireplumber
sudo dinitctl enable pipewire-pulse
dinitctl enable pipewire-pulse

auto-cpufreq

paru -S auto-cpufreq
ls /etc/dinit.d/ | grep cpufreq   # check if service file exists

If it exists:

sudo dinitctl enable auto-cpufreq
sudo dinitctl start auto-cpufreq

If not, write it manually:

sudo nvim /etc/dinit.d/auto-cpufreq
type = process
command = /usr/bin/auto-cpufreq --daemon
restart = true
sudo dinitctl enable auto-cpufreq
sudo dinitctl start auto-cpufreq
sudo auto-cpufreq --stats

dinit Quick Reference

What Command
Enable at boot (daemon running) dinitctl enable <svc>
Enable at boot (from chroot/pre-boot) ln -s /etc/dinit.d/<svc> /etc/dinit.d/boot.d/
Start now dinitctl start <svc>
Stop dinitctl stop <svc>
Status dinitctl status <svc>
List all dinitctl list
Restart dinitctl restart <svc>

Note

sudo dinitctl enable = system service. dinitctl enable without sudo = user service (per-user session).


btrfs Maintenance

Scrub

Monthly via cronie:

echo '@monthly root /usr/bin/btrfs scrub start -B /' >> /etc/cron.d/btrfs-scrub

Run manually:

sudo btrfs scrub start / && sudo btrfs scrub status /

Balance

Run when fragmentation builds up, skip on fresh installs:

sudo btrfs balance start -dusage=50 /

Disk Usage

sudo btrfs filesystem df /
sudo compsize /   # paru -S compsize

Snapshots

sudo pacman -S snapper
sudo snapper -c root create-config /
sudo snapper -c root create --description "before update"

After restoring a snapshot, rebuild initramfs. no bootloader config update needed:

sudo booster build --force /boot/booster-linux-zen.img

Troubleshooting

Won't Boot

Check efibootmgr entries:

efibootmgr -v   # entry must exist and point to \vmlinuz-linux-zen

If entry is missing, re-register it (see step 7). If entry exists but doesn't boot - wrong UUID in the cmdline string. Delete and recreate:

efibootmgr -B -b <XXXX>   # XXXX = boot entry number from efibootmgr -v
# then re-run the efibootmgr -c command from step 7 with correct UUIDs

Hibernation Not Working

blkid /dev/nvme0n1p2   # UUID must match resume= in your efibootmgr entry
swapon --show          # swap must be active

If UUID is wrong - delete the boot entry and recreate it with the correct one:

efibootmgr -v          # find the entry number
efibootmgr -B -b <XXXX>
# re-run efibootmgr -c from step 7 with correct resume=UUID

ZRAM Not Active

zramctl
swapon --show
dinitctl status zramen

Service Not Starting at Boot

ls -la /etc/dinit.d/boot.d/   # symlink must exist
ln -s /etc/dinit.d/<svc> /etc/dinit.d/boot.d/

NVIDIA - Black Screen / DKMS Didn't Build

pacman -Q | grep nvidia   # must be nvidia-dkms
dkms status
sudo booster build --force /boot/booster-linux-zen.img

What's Next

  • Desktop: Hyprland works with elogind out of the box
  • GPU drivers:
    • AMD: mesa vulkan-radeon - modesetting is in the kernel, don't install xf86-video-amdgpu
    • NVIDIA: nvidia-dkms nvidia-utils lib32-nvidia-utils
    • Intel: mesa vulkan-intel intel-media-driver
  • Firewall: ufw ufw-dinit

Done. Go build something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment