My ArchLinux Install Guide

· 12min · Pondo
My Arch Linux install guide

My custom Arch Linux setup is a minimal, secure, and efficient environment tailored for a daily workflow.

At its core, this system uses a custom-built DWM (Dynamic Window Manager) and a complete suckless toolkit (including dwm, dmenu, dwmblocks, st, all with custom patches), offering a fast, keyboard-driven experience without unnecessary bloat.

The installation is designed with security and performance in mind:

  • Full disk encryption using LUKS2 for protection against theft or unauthorized access.

  • Secure Boot with a signed Unified Kernel Image (UKI) to ensure the integrity of the boot process.

  • Filesystem: XFS, optimized for NVMe performance.

  • Swap handled either via a dedicated encrypted partition or optionally with zram for systems with less memory.

While heavily inspired by Bai-Chiang's Secure Arch Guide and the philosophy of creators like Luke Smith, this setup replaces btrfs with XFS for its simplicity and performance in specific workloads. My primary focus is on the security of the boot process, not system-level hardening like SELinux. I do not use a TPM for automatic LUKS2 unlocking; the combination of a signed UKI and a LUKS2 passphrase provides the desired protection.

Whether you're setting this up for a personal laptop or a minimal dev machine, this guide walks through every step to get it running—securely and cleanly.

My Arch desktop

Packages overview

info
Note

Packages marked (AUR) require an AUR helper (e.g. yay).

CategoryPackages
Base & CLIgit, htop, bashtop, base-devel, reflector, rsync, openssh, man-db, wget, lsof, usbutils, ncdu, mediainfo, xarchiver
Desktop & Filesthunar, thunar-volman, gvfs, gvfs-mtp, udisks2, polkit-gnome, ffmpegthumbnailer, tumbler, gnome-keyring, libsecret, libjxl, nsxiv, rclone, nextcloud-client
Media & Netmpv, ffmpeg, qbittorrent
Devrust
Themingadwaita-icon-theme, adwaita-icon-theme-legacy, libadwaita, gnome-themes-extra
DWM stackslock, xdotool, xclip, xorg-xprop, xcompmgr, xorg-xset, xorg-xinit, xorg-xwininfo, xorg-server, libxft, xterm, noto-fonts, noto-fonts-emoji, bc, dunst, xwallpaper, libnotify, ttf-fira-code, python-pywal, xorg-xrandr, less, xf86-input-evdev, scrot, xss-lock
Audiopipewire-pulse, wireplumber, pulsemixer, pipewire-jack
Virtualizationqemu-desktop, qemu-img, libvirt, virt-install, virt-manager, virt-viewer, edk2-ovmf, dnsmasq, iptables-nft, swtpm
Extras (AUR)brave-bin (AUR), localsend-bin (AUR), bambustudio-bin (AUR), rustrover (AUR), rustrover-jre (AUR), pycharm-professional (AUR), telegram-desktop-bin (AUR), windscribe-v2-bin (AUR), ab-av1 (AUR), obsidian (AUR)
sudo pacman -S --needed \
  git htop bashtop base-devel reflector rsync openssh man-db wget lsof usbutils ncdu mediainfo xarchiver \
  thunar thunar-volman gvfs gvfs-mtp udisks2 polkit-gnome ffmpegthumbnailer tumbler gnome-keyring libsecret libjxl nsxiv \
  rclone nextcloud-client mpv ffmpeg qbittorrent rust \
  adwaita-icon-theme adwaita-icon-theme-legacy libadwaita gnome-themes-extra \
  slock xdotool xclip xorg-xprop xcompmgr xorg-xset xorg-xinit xorg-xwininfo xorg-server libxft xterm \
  noto-fonts noto-fonts-emoji bc dunst xwallpaper libnotify ttf-fira-code python-pywal xorg-xrandr less xf86-input-evdev scrot xss-lock \
  pipewire-pulse wireplumber pulsemixer pipewire-jack \
  qemu-desktop qemu-img libvirt virt-install virt-manager virt-viewer edk2-ovmf dnsmasq iptables-nft swtpm
yay -S --needed brave-bin localsend-bin bambustudio-bin rustrover rustrover-jre \
  pycharm-professional telegram-desktop-bin windscribe-v2-bin ab-av1 obsidian

Part 1: Live Environment Preparation

This section covers preparing the live installation environment.

1.1. Boot and Verify UEFI Mode

Ensure the system has booted in UEFI mode. This command should return 64 without an error.

cat /sys/firmware/efi/fw_platform_size

1.2. Check Secure Boot Status

At this stage, Secure Boot should be disabled.

bootctl status | grep "Secure Boot"

The output should show Secure Boot: disabled (setup mode).

1.3. Verify UEFI Boot Manager

Check that efibootmgr can read the current boot variables.

efibootmgr --unicode

This should return a list of boot entries, for example:

BootCurrent: 0004
BootOrder: 0004,0000,0001,0002,0003
Timeout: 30 seconds
Boot0000* Diskette Drive(device:0)
Boot0004* Arch Linux

1.4. Set Keyboard Layout

loadkeys pl

1.5. Connect to the Internet

Use ip a to identify your wireless interface (e.g., wlan0).

iwctl
station <interface_name> scan
station <interface_name> get-networks
station <interface_name> connect "Your_WiFi_Name"
exit

Verify the connection:

ping archlinux.org

1.6. Synchronize the System Clock

You can list all available timezones with timedatectl list-timezones.

timedatectl set-ntp true
timedatectl set-timezone Europe/Warsaw
systemctl enable --now systemd-timesyncd.service

Part 2: Disk Partitioning and Formatting

This section details how to prepare the target disk for installation.

2.1. Identify the Target Disk

lsblk
DISK=/dev/sdX # e.g., /dev/nvme0n1 or /dev/sda
danger
Danger

All steps below erase data on $DISK.

2.2. (Optional) Check and Set 4K Sector Size

For NVMe drives, using the native 4K sector size can improve performance. Read more here. Check for support:

nvme id-ns -H $DISK

The output should show available LBA Formats, for example:

LBA Format  0 : Metadata Size: 0 bytes - Data Size: 512 bytes - Relative Performance: 0x2 Good
LBA Format  1 : Metadata Size: 0 bytes - Data Size: 4096 bytes - Relative Performance: 0x1 Better (in use)

If 4K is supported and you wish to use it, execute the following (this will format the drive):

nvme format --lbaf=1 --force $DISK
danger
note

If you do this, remember to add the --sector-size 4096 flag to the cryptsetup command.

2.3. Wipe and Partition the Disk (sgdisk)

Completely wipe the disk's partition table.

blkdiscard -f $DISK
sgdisk --zap-all "$DISK"

Option A: With a dedicated SWAP partition (Recommended) Swap size should ideally be equal to your RAM amount.

sgdisk \
  -n1:1MiB:+2GiB -t1:ef00 -c1:EFI \
  -n2:0:+8GiB    -t2:8200 -c2:SWAP \
  -n3:0:0        -t3:8304 -c3:ROOT \
  "$DISK"

# Assign partition variables
EFI=${DISK}1
SWAP=${DISK}2
ROOTFS=${DISK}3

Option B: Without a SWAP partition

sgdisk \
  -n1:1MiB:+2GiB -t1:ef00 -c1:EFI \
  -n2:0:0        -t2:8304 -c2:ROOT \
  "$DISK"

# Assign partition variables (use 'p' prefix for NVMe drives)
EFI=${DISK}p1
ROOTFS=${DISK}p2

Reload the partition table and verify:

lsblk "$DISK"

2.4. Encrypt the Root Partition (LUKS2)

Set a strong passphrase for your disk encryption.

# remove --sector-size 4096 if your drive does not support 4K sectors
cryptsetup --type luks2 --sector-size 4096 --verify-passphrase --verbose luksFormat ${ROOTFS}

# Open the encrypted container
cryptsetup open ${ROOTFS} cryptroot

2.5. Format the Filesystems (mkfs, mkswap)

# EFI Partition
mkfs.fat -F32 ${EFI}

# Root XFS Filesystem Remove -s size=4096 if your drive dont support it 
mkfs.xfs -s size=4096 /dev/mapper/cryptroot
danger
Uwaga – nieodwracalne

Run mkswap only if you created a swap partition:

# Optional: run only if using a swap partition ⚠️
[ ! -z "$SWAP" ] && mkswap ${SWAP}

2.6. Mount the Filesystems

mount /dev/mapper/cryptroot /mnt
mount --mkdir ${EFI} /mnt/efi
danger
Uwaga – nieodwracalne

Run swapon only if you created a swap partition:

# Optional: run only if using a swap partition ⚠️
[ ! -z "$SWAP" ] && swapon ${SWAP}

Part 3: Installation and Base Configuration

3.1. Install Base System and Essential Packages (pacstrap)

Install all necessary packages at once to avoid running pacman multiple times inside the chroot.

# Choose amd-ucode or intel-ucode
pacstrap -K /mnt base base-devel linux linux-firmware neovim \
networkmanager wpa_supplicant \
sbctl efibootmgr <amd-ucode|intel-ucode>

3.2. Generate FSTAB

genfstab -U /mnt >> /mnt/etc/fstab
vim /mnt/etc/fstab

Tip: After generating, you can nvim /mnt/etc/fstab and change relatime to noatime for your root filesystem on an SSD to reduce write operations.

3.3. Enter Chroot Environment with Variables

This clever trick uses bash -c to pass our environment variables into the chroot session.

arch-chroot /mnt /bin/bash -c "
export DISK='$DISK'
export EFI='$EFI'
export ROOTFS='$ROOTFS'
[ ! -z \"$SWAP\" ] && export SWAP='$SWAP'
export PS1='(chroot) # '
exec /bin/bash"

You can now use variables like echo $DISK inside the chroot.

Part 4: System Configuration (Inside Chroot)

You are now operating inside the newly installed system.

4.1. Set Timezone

ln -sf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
hwclock --systohc

4.2. Configure Localization (Language & Keyboard)

Uncomment pl_PL.UTF-8 UTF-8 and en_US.UTF-8 UTF-8 in /etc/locale.gen. You can list all locales with locale -a and all keymaps with localectl list-keymaps.

nvim /etc/locale.gen
locale-gen

echo "LANG=pl_PL.UTF-8" > /etc/locale.conf
echo "KEYMAP=pl" > /etc/vconsole.conf

4.3. Set Hostname

echo "BasedArch" > /etc/hostname

4.4. Configure Networking

The packages were installed via pacstrap; now we just enable the services.

systemctl enable NetworkManager.service
systemctl enable wpa_supplicant.service
systemctl enable systemd-resolved.service

# Link the systemd resolver stub file for DNS
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

4.5. Key Step: Configure the Boot Process (UKI + systemd)

Now, in the correct order, we configure everything needed to boot the system.

4.5.1. Configure Initramfs (/etc/mkinitcpio.conf)

Edit the file to use systemd and sd-encrypt hooks for unlocking the LUKS partition at boot.

nvim /etc/mkinitcpio.conf

Find the HOOKS line and replace it with:

HOOKS=(base systemd autodetect modconf keyboard sd-vconsole sd-encrypt microcode kms block filesystems)
4.5.2. Create Kernel Command Line File (/etc/kernel/cmdline)

This file will contain parameters passed to the kernel at every boot.

# Get the UUID of the encrypted ROOT partition
ROOT_UUID=$(lsblk -dno UUID ${ROOTFS})

# Create the cmdline file. If you plan to use zram, add zswap.enabled=0
echo "root=/dev/mapper/cryptroot" > /etc/kernel/cmdline
4.5.3. Create Initramfs Crypttab (/etc/crypttab.initramfs)

This file tells sd-encrypt (inside the initramfs) which partition to decrypt. The discard option is recommended for SSDs. See dm-crypt/Specialties for more info.

# Use the same UUID from the previous step
LUKS_UUID="$(cryptsetup luksUUID "$ROOTFS")"
echo "cryptroot UUID=${LUKS_UUID} - password-echo=no,no-read-workqueue,no-write-workqueue,discard" > /etc/crypttab.initramfs
4.5.4. Modify mkinitcpio Preset for UKI

Edit the .preset file so mkinitcpio builds the UKIs directly on the EFI partition.

nvim /etc/mkinitcpio.d/linux.preset

Modify the file to look like this:

ALL_kver="/boot/vmlinuz-linux"
PRESETS=('default')

default_uki="/efi/EFI/Linux/ArchLinux.efi"
# Optional: add a splash screen
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
4.5.5 (Optional) Swap Encryption

To use UUID instead of /dev/sdX3 in the /etc/crypttab, we need to create a small 1MiB sized filesystem at /dev/sdX3, see dm-crypt/Swap encryption#UUID and LABEL. First deactivate swap partition

(chroot) # swapoff /dev/sdX3

Then create a 1MiB ext2 filesystem with label cryptswap

(chroot) # mkfs.ext2 -F -F -L cryptswap /dev/sdX3 1M

Add /etc/crypttab entry

# <name>   <device>         <password>   <options>
cryptswap  UUID=_SWAP_UUID_  /dev/urandom  swap,offset=2048

Get SWAP_UUID with command lsblk -dno UUID /dev/sdX3. The option offset is the start offset in 512-byte sectors. So 2048 of 512 bytes is 1MiB. Edit the swap entry in /etc/fstab, change UUID=xxxx to /dev/mapper/cryptswap

# <filesystem>    <dir>  <type>  <options>  <dump>  <pass>
/dev/mapper/swap  none   swap    defaults   0       0
4.5.6 (Optional) ZRAM

Install the zram-generator package. Then create Edit /etc/systemd/zram-generator.conf

[zram0]
zram-size = min(ram / 2, 4 * 1024)
compression-algorithm = zstd
fs-type = swap

zram-size is a function of ram variable, your total memory size. min(ram / 2, 4 * 1024) will create a zram as a swap device with size of half of your total memory, up to 4GB maximum. See zram-generator.conf(5) § OPTIONS for more supported arithmetic operators and functions.

Create following config file to optimize zram

edit /etc/sysctl.d/99-vm-zram-parameters.conf

vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0

Since officially supported kernels have zswap enabled by default. To disable it, we need to add zswap.enabled=0 to kernel parameters

4.5.7. Generate the Unified Kernel Images (mkinitcpio -P)

With all configurations in place, generate the images.

mkdir -p /efi/EFI/Linux

# Generate the UKIs
mkinitcpio -P

If successful, you will find two .efi files in /efi/EFI/Linux/.

4.6. (Optional) Configure Secure Boot (sbctl)

4.6.1. Create and Enroll Keys

Using the --microsoft flag is recommended for maximum hardware compatibility. Pick your poison:

sbctl create-keys

sbctl enroll-keys
# or
sbctl enroll-keys --microsoft
# or delete Microshit keys
sbctl enroll-keys --no-microsoft
4.6.2. Sign the Unified Kernel Images

The -s (--save) flag overwrites the original file with the signed version.

sbctl sign -s /efi/EFI/Linux/ArchLinux.efi

Verify signed files

sbctl sign -s /efi/EFI/Linux/ArchLinux.efi
4.6.3. Verify Automatic Signing Hook

sbctl installs a pacman hook to automatically sign the kernel after every update. You can check its status:

sbctl status

4.7. Create UEFI Boot Entries (efibootmgr)

Check the boot order:

efibootmgr
warning
Caution

Deleting wrong entries may make other OSes unbootable.

efibootmgr --bootnum 000X --delete-bootnum --unicode

Now, we inform the UEFI firmware about our signed images.:

# Use --part 1 or the correct partition number for your ESP
# Note the quotes and backslashes for the loader path
efibootmgr --create --disk "$DISK" --part 1 --label "Arch Linux" \
  --loader 'EFI\Linux\ArchLinux.efi' --unicode

If needed, adjust the boot order (replace 0003,0004,0005 with your desired order):

efibootmgr --bootorder 0003,0004,0005 --unicode

**4.8. Set Root Password

passwd

4.9. Exit Chroot and Reboot

The configuration is almost done!

exit 
umount -R /mnt
systemctl reboot --firmware-setup

The computer will reboot into the UEFI/BIOS settings. This is the time to enable Secure Boot (set to "Enabled" or "User Mode"). Save the changes and let the system boot from the disk.

Part 5: Finalization and Customization (Post-Reboot)

Log in with your newly created user account to complete the setup.

5.1. First Login

After rebooting and entering your LUKS passphrase, log in as root

Add user

useradd -m -G wheel sieciowiec
passwd sieciowiec
EDITOR=nvim visudo
warning
Sudo policy

Enabling NOPASSWD for the wheel group is convenient but weakens security. Consider requiring a password.

uncoment %wheel ALL=(ALL:ALL) NOPASSWD: ALL

relogin to new user here

5.2. (Optional) Configure Encrypted Swap

If you created a dedicated swap partition and want to encrypt it, follow these steps. For more details, see the Arch Wiki on Swap Encryption. First, deactivate the swap partition if it was enabled automatically.

sudo swapoff ${SWAP}

Create a small ext2 filesystem on the partition to assign it a UUID.

sudo mkfs.ext2 -F -L cryptswap ${SWAP} 1M

Add an entry to /etc/crypttab.

# Get SWAP_UUID with 'lsblk -dno UUID ${SWAP}'
# Then add this line to /etc/crypttab
# <name>      <device>         <password>     <options>
cryptswap   UUID=<SWAP_UUID>   /dev/urandom   swap,offset=2048,cipher=aes-xts-plain64,size=256

Finally, edit /etc/fstab and change the swap entry to point to the mapped device.

# <filesystem>           <dir>  <type> <options>  <dump> <pass>
/dev/mapper/cryptswap  none   swap   defaults   0      0

5.3. (Optional) Configure zram

As an alternative to a swap partition, you can use zram. Install the generator:

sudo pacman -S zram-generator

Create a configuration file:

# /etc/systemd/zram-generator.conf
[zram0]
zram-size = min(ram / 2, 8 * 1024)
compression-algorithm = zstd

To optimize zram, create /etc/sysctl.d/99-vm-zram-parameters.conf:

vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0

Remember to add zswap.enabled=0 to /etc/kernel/cmdline and regenerate your UKI (sudo mkinitcpio -P) if you use zram.

5.4. Configure Pacman (Parallel Downloads)

Edit /etc/pacman.conf and uncomment ParallelDownloads.

ParallelDownloads = 10

Optional: uncoment Color and VerbosePkgLists

5.5. Optimize Mirrorlist (reflector)

sudo pacman -S reflector
sudo reflector --country Poland,Germany --latest 10 --sort rate --save /etc/pacman.d/mirrorlist

You can also enable the reflector.timer to update this list weekly.

5.6. Enable Periodic TRIM for SSDs

sudo systemctl enable --now fstrim.timer

Your base system is now fully configured. From here, you can proceed with installing a graphical environment, audio servers, and your personal dotfiles.

TMPFS in RAM - add this to /etc/fstab

sudo nvim /etc/fstab

tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0

apply changes and check if tmp is tmpfs now

sudo mount -a
findmnt /tmp

it should display something like this:

[sieciowiec@sieciowiec ~]$ findmnt /tmp
TARGET SOURCE FSTYPE OPTIONS
/tmp   tmpfs  tmpfs  rw,nosuid,nodev,size=15938524k,nr_inodes=1048576,inode64

Make systemd logs in ram - logs will not persist across reboots.

sudo nvim /etc/systemd/journald.conf

# set Storage=
Storage=volatile

5.7. TPM2 Binding -> wont work with crypttab

Check if your device has TPM2

$ cat /sys/class/tpm/tpm0/device/description
TPM 2.0 Device

systemd-analyze has-tpm2

systemd-cryptenroll --tpm2-device=list

Check luks keyslots of your cryptroot:

sudo cryptsetup luksDump /dev/sdXpX

Create tpm binding read more

sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+2+7+11 /dev/sdXpX

Restore dotfiles

git clone --bare https://github.com/Pondiniii/dotfiles.git $HOME/.dotfiles

rm .bashrc

alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'

dotfiles checkout

It may show an error of conflicting files that already exist in your home directory would be overwritten. Since this is fresh installed system, we simply delete them. Or run this command then checkout again

dotfiles checkout 2>&1 | egrep "\s+\." | awk {'print $1'} | xargs -I{} rm {}
dotfiles checkout

If using GitHub change the remote url to use SSH key ~/.dotfiles/config

...bash
[remote "origin"]
    url = git@github.com:_username_/dotfiles.git
...
dotfiles push

Installing suckless utils

cd .local/src/
ls 

for every folder here dmenu dwm dwmblocks st cd in to it and execute: sudo make install

cd dwm
sudo make clean install
cd ..
cd dmenu
sudo make clean install
cd ..
cd st
sudo make clean install
cd ..
cd dwmblocks
sudo make clean install
cd 

create .xinitrc symlink

cd
ln -s ~/.config/x11/.xinitrc ~/.xinitrc

start dwm

startx

configure dpi -> change 120 to your prefered dpi. after setting restart DWM (leave dwm -> startx again)

echo "120" > .config/x11/.dpi

(optional) keeping firmware up to date

sudo pacman -S fwupd
sudo fwupdmgr refresh
sudo fwupdmgr get-updates
sudo fwupdmgr update

Installing YAY AUR helper

git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
cd ..
rm -r yay

Optimize AUR building

Remove any -march and -mtune CFLAGS, then add -march=native in /etc/makepkg.conf.

sudo nvim /etc/makepkg.conf

CFLAGS="-march=native -O2 -pipe ..." then add -C target-cpu=native to RUSTFLAGS: RUSTFLAGS="-C opt-level=2 -C target-cpu=native" change MAKEFLAGS=j2 to MAKEFLAGS="-j$(nproc)"

Packages:

git htop bashtop base-devel reflector rsync obsidian openssh keepassxc thunar man-db mpv qbittorrent ffmpeg openssh gparted telegram-desktop-bin linux-headers dkms rust usbutils lsof wget docker docker-compose mediainfo xarchiver ncdu rclone nextcloud-client gnome-keyring libsecret libjxl nsxiv

thunar plugins: thunar-volman gvfs gvfs-mtp udisks2 polkit-gnome ffmpegthumbnailer tumbler

hack dev: usbipd

DWM: slock xdotool xclip xorg-xprop xcompmgr xorg-xset xorg-xinit xorg-xwininfo xorg-server libxft xterm noto-fonts noto-fonts-emoji bc dunst xwallpaper notify-send ttf-fira-code python-pywal xorg-xrandr less xf86-input-evdev scrot xss-lock

AUR: brave-bin localsend-bin bambustudio-bin rustrover rustrover-jre pycharm-professional
windscribe-v2-bin ab-av1

dark theme: adwaita-icon-theme adwaita-icon-theme-legacy libadwaita gnome-themes-extra

audio: sudo pacman -S pipewire-pulse wireplumber pulsemixer pipewire-jack systemctl --user restart pipewire.service pipewire-pulse.service wireplumber.service

Virt: sudo pacman -S qemu-desktop qemu-img libvirt virt-install virt-manager virt-viewer
edk2-ovmf dnsmasq iptables-nft swtpm

  • qemu-full - user-space KVM emulator, manages communication between hosts and VMs
  • qemu-img - provides create, convert, modify, and snapshot, offline disk images
  • libvirt - an open-source API, daemon, and tool for managing platform virtualization
  • virt-install - CLI tool to create guest VMs
  • virt-manager - GUI tool to create and manage guest VMs
  • virt-viewer - GUI console to connect to running VMs
  • edk2-ovmf - enables UEFI support for VMs
  • dnsmasq - lightweight DNS forwarder and DHCP server
  • swtpm - TPM (Trusted Platform Module) emulator for VMs
  • guestfs-tools - provides a set of extended CLI tools for managing VMs
  • libosinfo - a library for managing OS information for virtualization.
  • tuned - system tuning service for linux allows us to optimise the hypervisor for speed.

define custom interface name

sudo nvim /etc/udev/rules.d/70-persistent-net.rules

and add

SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="XX:XX:XX:XX:XX:XX", NAME="enp11s0"

remember to change XX:XX to real mac

reboot

Virt setup guide

enable service:

sudo systemctl enable libvirtd --now

add current user:

sudo usermod -aG libvirt $USER

networking setup:

sudo virsh net-list --all
sudo virsh net-start default
sudo virsh net-autostart default

define your main pc interface

INTERFACE_NAME=lan

create bridge network

sudo nmcli connection add type bridge con-name br-home ifname br-home
sudo nmcli connection add type ethernet slave-type bridge con-name 'br-home-port' \
    ifname $INTERFACE_NAME master br-home
sudo nmcli connection modify br-home connection.autoconnect-slaves 1
sudo nmcli connection up br-home
sudo nmcli device status
sudo virsh net-define /dev/stdin <<EOF
<network>
  <name>home-lan</name>
  <forward mode="bridge"/>
  <bridge name="br-home"/>
</network>
EOF

sudo virsh net-start home-lan
sudo virsh net-autostart home-lan

kvm isolation gpu

append intel_iommu=on or amd_iommu=on

etc /etc/kernel/cmdline

find gpu

lspci -nn | grep -i vga

blacklist gpu and drivers in /etc/modprobe.d/vfio.conf

options vfio-pci ids=10de:2c05,10de:22e9
blacklist nouveau
blacklist nvidia

X11 amdgpu config file

config file for igpu on x

/usr/share/X11/xorg.conf.d/amd.conf

Section "Device"
	Identifier "AMD"
	Driver "modesetting" 
	BusID "PCI:16:0:0"
EndSection


Section "Screen"
    Identifier "Screen0"
    Device "AMD"
    Monitor "Monitor0"
    DefaultDepth 24
    SubSection "Display"
        Depth 24
        Modes "3840x2160_120.00"
    EndSubSection
EndSection