HON’s Wiki # Arch (i3)

Home / Personal Devieces

Contents

For Arch with LUKS encrypted root, using the i3 window manager.

Resources

Arch

i3

TODO

Installation

Note: The use of sudo in the text below is a bit inconsistent, but you should know when you need it and when you don’t.

Live Image Install

  1. (Pre install) Download and burn an Arch ISO:
    • Arch downloads.
    • Always verify the ISO’s hash or PGP signature found on the Arch download page (not from the download mirrors).
  2. (Pre install) Disable secure boot in the BIOS settings.
  3. Boot into the Arch live image:
    1. Make sure you’re in UEFI BIOS mode. Disable CSM in the BIOS settings if you don’t need legacy BIOS for anything, to avoid future complications.
    2. Avoid broken display drivers: In the GRUB bootloader menu, press E on the main entry, add nomodeset at the end, and press enter to boot.
  4. Set the keymap:
    1. (Optional) List available keymaps: ls /usr/share/kbd/keymaps/**/*.map.gz | less
    2. (Optional) Find the appropriate keymap, e.g. the Norwegian no for /usr/share/kbd/keymaps/i386/qwerty/no.map.gz
    3. Load: loadkeys <keymap> (e.g. loadkeys no)
  5. Verify the (UEFI) boot mode:
    1. Check efivar --list or ls /sys/firmware/efi/efivars. If either exists, it’s in UEFI mode.
  6. Setup live-OS networking:
    1. (Note) For cabled Ethernet with DHCP, it should already be working. For WLAN or exotic setups, check the wiki.
    2. (Optional) Test it somehow (e.g. with ping or curl).
  7. Setup live-OS time:
    1. Enable NTP: timedatectl set-ntp true
    2. (Optional) Check the “synchronized” line from timedatectl.
  8. If your live-OS is outdated, update the keyring: pacman -Sy && pacman -S archlinux-keyring
  9. Partition the main disk (for LUKS encryption):
    1. Find the main disk: lsblk
    2. (Optional) Overwrite the full disk to get rid of all traces of the previous install: dd if=/dev/zero of=/dev/<disk> bs=1M conv=fsync status=progress
    3. (Note) Create these partitions by repeatedly running the steps below:
      • Partition 1: Size 512MiB, type ESP (type 1 in fdisk and EF00 in gdisk), mountpoint /boot/efi/.
      • Partition 2: Remaining space, type doesn’t matter (leave as-is). Will contain the encrypted root filesystem.
      • TODO Maybe add an encrypted swap partition. For hibernation support and stuff, idk.
    4. Setup and partition the disk: fdisk /dev/<disk>
      1. Create a new GPT partition table: g
      2. Start the new partition wizard (for each partition): n
        • Partition number: See table.
        • First sector: Default.
        • Last sector (effectively partition size): See table. e.g. +512M for a 512MiB volume or nothing to fill it all.
      3. Set the partition type (for each partition): t
        • Partition number and type: See table.
      4. Show partitions: p
      5. Write to disk and exit: w
  10. Format the ESP (first partition):
    1. mkfs.fat -F32 /dev/<partition-1>
  11. Create encrypted root volume (second partition):
    1. (Note) GRUB currently has limited support for LUKS2, so use LUKS1.
    2. Check which cryptohash and encryption algorithms are fastest on the system: cryptsetup benchmark
    3. Create: cryptsetup luksFormat --type=luks1 --use-random -h sha256 -i 1000 -c aes-xts-plain64 -s 256 /dev/<partition-2> (example parameters)
    4. Enter the password to unlock the system during boot.
    5. (Note) There is a later step for avoiding entering the password twice during boot.
  12. Unlock the encrypted root volume:
    1. cryptsetup luksOpen /dev/<partition> crypt_root (for example name crypt_root)
  13. Format the root volume:
    1. mkfs.ext4 /dev/mapper/crypt_root
  14. Mount the volumes:
    • Mount root: mount /dev/mapper/crypt_root /mnt
    • Mount ESP: mkdir -p /mnt/boot/efi && mount /dev/<partition-1> /mnt/boot/efi
  15. Install packages to the new root:
    • Base command and packages: pacstrap /mnt <packages>
    • Base packages: base linux linux-firmware intel-ucode amd-ucode archlinux-keyring polkit sudo bash-completion man-db man-pages xdg-utils xdg-user-dirs vim tar zip unzip curl
    • Extra packages: smartmontools lm_sensors hwloc zsh htop base-devel git jq rsync openssh tmux screen usbutils tcpdump nmap inetutils bind sipcalc
    • Wireless networking packages: iwd (or wpa_supplicant)
  16. Generate the fstab file:
    1. genfstab -U /mnt >> /mnt/etc/fstab
    2. Check it for errors or duplicates.
  17. Chroot into the new root:
    1. arch-chroot /mnt
  18. Setup localization:
    1. Set time zone: ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
    2. Update the hardware clock (using UTC): hwclock --systohc
    3. Uncomment locales to generate: vim /etc/locale.gen
      • Always include en_US.UTF-8 UTF-8.
      • Norway is nb_NO.UTF-8 UTF-8.
    4. Generate selected locales: locale-gen
    5. Set the locale: In /etc/locale.conf, set LANG=<locale> (e.g. LANG=en_US.UTF-8).
    6. Set the TTY keyboard layout: In /etc/vconsole.conf, set KEYMAP=<keymap> (e.g. KEYMAP=no).
  19. Set hostname:
    1. echo <hostname> > /etc/hostname
  20. Set the root password:
    1. passwd
  21. Create the initial ramdisk:
    1. Add extra hooks: In /etc/mkinitcpio.conf, find the HOOKS=() line. Add encrypt after block and keymap after keyboard (ordering matters).
    2. Create the initial ramdisk: mkinitcpio -P
  22. Setup GRUB:
    1. Install bootloader: pacman -S grub efibootmgr
    2. Enable encrypted disk support: In /etc/default/grub, set GRUB_ENABLE_CRYPTODISK=y.
    3. Find the UUID of the encrypted root physical partition: blkid
    4. Add kernel parameters for the encrypted root (e.g. /dev/sda2): In /etc/default/grub, in the GRUB_CMDLINE_LINUX variable, add cryptdevice=UUID=<device-UUID>:crypt_root root=/dev/mapper/crypt_root.
    5. Install GRUB to ESP: grub-install --target=x86_64-efi --efi-directory=/boot/efi
    6. Generate GRUB config: grub-mkconfig -o /boot/grub/grub.cfg
  23. Exit the chroot and reboot:
    1. exit
    2. reboot
  24. Remove the installation media.
  25. Wait for the GRUB screen or decryption prompt.

Post Install Setup

  1. Boot into the newly installed system:
    1. (Optional) Avoid broken display drivers (typically needed for NVIDIA cards): In the GRUB bootloader menu, press E on the main entry and add nomodeset at the end of the linux line. Press Ctrl+X to continue. After proper display drivers are installed, this is no longer required.
  2. (Optional) Disable the beeper:
    1. Unload the module: rmmod pcspkr
    2. Blacklist the module: echo blacklist pcspkr > /etc/modprobe.d/nobeep.conf
  3. Enable SSD periodic TRIM:
    1. Enable timer: systemctl enable fstrim.timer
  4. Setup swap file:
    1. (Note) You should have enough memory installed to never need swapping, but it’s a nice backup to prevent the system from potentially crashing if anything bugs out and eats up too much memory.
    2. Show if swap is already enabled: swapon --show
    3. Allocate the swap file: fallocate -l <size> /swapfile (e.g. 16G)
    4. Fix the permissions: chmod 600 /swapfile
    5. Setup the swap file: mkswap /swapfile
    6. Activate the swap file: swapon /swapfile
      • Check: swapon --show
    7. Add it to /etc/fstab using this line: /swapfile swap swap defaults 0 0
      • Check: mount -a
  5. Setup default editor:
    • Create a new profile file: /etc/profile.d/editor.sh
    • Set the editor: export EDITOR=vim
    • Set the visual editor: export VISUAL=vim
  6. Setup basic, wired networking:
    1. Enable: systemctl enable systemd-networkd
    2. Don’t wait for network during boot: systemctl disable systemd-networkd-wait-online.service
    3. Add a config for the main interface (or all interfaces): See the section with an example below.
    4. (Re)start: systemctl restart systemd-networkd
    5. Wait for connectivity.
      • networkctl should show the interface as anything but “unmanaged”.
      • ip a should show a routable IP address after a few seconds if using DHCP/RA.
  7. (Optional) Setup wireless networking (excluding tray icon and GUI):
    • Note: The remainder of the instructions assume you picked iwd here.
    • Preparations:
      1. Make sure a driver is loaded for the WLAN device:
        • ip a should show a wlp* interface for the device.
        • lspci -k (for PCIe) or lsusb -v (for USB) should show a loaded module.
      2. Make sure the radio device isn’t blocked: rfkill (should show “unblocked”)
      3. Create the netdev group to allow users to control iwd/wpa_supplicant: groupadd -r netdev
    • Using iwd (recommended):
      1. Install: pacman -S iwd
      2. Configure: See example config below for config /etc/iwd/main.conf.
      3. Enable: systemctl enable --now iwd.service
        • If this fails, you may need to reboot.
      4. Setup the network config:
        1. Create a systemd-network config similar to the one for the wired interface, but add IgnoreCarrierLoss=5s to the Network section to allow for roaming without disconnects.
        2. Restart systemd-networkd.
      5. (Example) Connect to WPA2/WPA3 personal network (using iwctl):
        1. (Note) iwctl has extenside tab-complete support.
        2. Enter iwctl: iwctl
        3. Show devices: device list
        4. Show device info: device <device> show
        5. Scan for networks: station <device> scan
        6. Show networks: station <device> get-networks
        7. Connect to network: station <device> connect <SSID>
        8. Show connection info: station <device> show
        9. Disconnect from the network: station <device> disconnect
        10. Show known networks: known-networks list
        11. Forget known network: known-networks <SSID> forget
      6. (Example) Connect to eduroam:
        1. (Note) See the wiki for more info.
        2. Go to the eduroam configuration assistant tool (CAT) to download a config script for your organization. Don’t run it, it doesn’t support iwd.
        3. Create the private credentials dir: mkdir /var/lib/iwd/ && chown root:root /var/lib/iwd/ && chmod 700 /var/lib/iwd/
        4. Create the config file /var/lib/iwd/eduroam.8021x (name-sensitive), containing the template snippet below with values found in the eduroam script.
      7. (Extra) Troubleshooting (as root):
        1. Run it in debug mode (stop the service first): IWD_TLS_DEBUG=TRUE IWD_WSC_DEBUG_KEYS=1 /usr/lib/iwd/iwd
        2. Check the debug certificate file (if the log says it stored it): cat /tmp/iwd-tls-debug-server-cert.pem
        3. Force it to try to connect (if nothing happens): iwctl station wlan0 connect <SSID>
    • Using wpa_supplicant (not recommended):
      1. Install: sudo pacman -S wpa_supplicant
      2. Configure:
        • See example config below for config /etc/wpa_supplicant/wpa_supplicant.conf.
        • Fix the permissions (it contains secrets): sudo chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf
        • Create a place to put certs and protect it: sudo mkdir -p /var/lib/wpa_supplicant/certs; sudo chmod 700 /var/lib/wpa_supplicant
        • Using update_config allows it to update its config, which may change file permissions to something “readable by everyone”, according to the Arch wiki. If you don’t need this, set it to 0.
        • Set country to your country code.
      3. (Optional) Test the daemon and config:
        1. Start it in debug mode: sudo wpa_supplicant -B -i <interface> -c /etc/wpa_supplicant/wpa_supplicant.conf -d
        2. See if you successfully connect by running and watching sudo wpa_cli.
        3. (Optional) Check that you can see all networks:
          1. sudo wpa_cli scan
          2. sudo wpa_cli scan_results
        4. Kill it: sudo pkill wpa_supplicant
      4. TODO:
        • Update the main service to use the correct config and enable it.
        • Configure for specific interfaces, e.g. for differente wired and wireless config? https://wiki.archlinux.org/title/wpa_supplicant#At_boot_(systemd)
  8. Setup DNS server(s):
    1. echo "nameserver 1.1.1.1" >> /etc/resolv.conf (Cloudflare)
    2. echo "nameserver 2606:4700:4700::1111" >> /etc/resolv.conf (Cloudflare)
  9. Setup Pacman:
    1. Enable color: In /etc/pacman.conf, uncomment Color.
    2. Enable the multilib repo (for 32-bit apps): In /etc/pacman.conf, uncomment the [multilib] section.
    3. Update/upgrade: pacman -Syu
  10. Install display driver and utils:
    • For NVIDIA Maxwell and newer GPUs: pacman -S nvidia nvidia-utils nvidia-settings.
      • (Optional) For CUDA: pacman -S cuda
    • For newer AMD GPUs: pacman -S mesa xf86-video-amdgpu vulkan-radeon libva-mesa-driver
    • For newer Intel integrated GPUs: pacman -S mesa lib32-mesa vulkan-intel intel-media-driver
  11. Avoid having to enter the encryption password twice during boot:
    1. (Note) To avoid entering the password once for GRUB and then for the initramfs, we can create a keyfile and embed it into the initramfs. If the keyfile fails, it will fall back to asking for a password again.
    2. Secure the boot dir (to protect the embedded key in the initramfs): chmod 700 /boot
    3. Generate keyfile:
      1. (umask 0077; mkdir -p /var/lib/keys/luks)
      2. dd if=/dev/random of=/var/lib/keys/luks/crypt_root bs=2048 count=1 iflag=fullblock
    4. Add key to LUKS: cryptsetup luksAddKey /dev/<partition> /var/lib/keys/luks/crypt_root
    5. Add key to initramfs: In /etc/mkinitcpio.conf, set FILES=(/var/lib/keys/luks/crypt_root).
    6. Recreate initramfs: mkinitcpio -P
    7. Add extra kernel parameters for the keyfile: In /etc/default/grub, in the GRUB_CMDLINE_LINUX variable, add cryptkey=rootfs:/var/lib/keys/luks/crypt_root.
    8. Update GRUB config: grub-mkconfig -o /boot/grub/grub.cfg
    9. (Optional) Reboot to make sure it works. If not, it should fall back to the extra password prompt.
  12. Setup sudo:
    1. (Note) Both the wheel and sudo groups are commonly used for giving sudo access, but I personally prefer sudo since wheel may also be used by polkit rules, su (pam_wheel), etc.
    2. Install: pacman -S sudo
    3. Add the sudo group: groupadd -r sudo
    4. Enter the config: EDITOR=vim visudo
    5. Add line to allow sudo group without password: %sudo ALL=(ALL:ALL) NOPASSWD: ALL
  13. Add a personal admin user:
    1. Create the user and add it to relevant groups (remove missing groups): useradd -m -G sudo,adm,sys,uucp,proc,systemd-journal,video,netdev <user>
    2. Set its password: passwd <user>
    3. (Optional) Relog to test the user.
  14. (Optional) Reboot.
  15. Install yay to access the AUR (as non-root):
    1. (Note) This needs to be done as non-root.
    2. Install requirements: sudo pacman -S --needed base-devel git
    3. Clone and enter: git clone https://aur.archlinux.org/yay.git
    4. Install: cd yay && makepkg -si
    5. Remove the tmp. repo: cd .. && rm -rf yay
    6. Idk (once): yay -Y --gendb
    7. (Note) Yay needs to be run as a normal user, not as root and not with sudo.
  16. Enable early numlock (initramfs phase):
    1. Install package: yay -S mkinitcpio-numlock
    2. Add numlock to the HOOKS list in /etc/mkinitcpio.conf somewhere before encrypt (assuming the system is encrypted) (e.g. before modconf).
    3. Regenerate the initramfs: sudo mkinitcpio -P
  17. Tweak the PAM login faillock:
    1. (Note) It applies to password logins only, not SSH keys.
    2. (Note) To unlock a user, run faillock --reset --user <user>.
    3. Increase the failed login count threshold: In /etc/security/faillock.conf, set deny = 5.
  18. Setup the local DNS resolver (systemd):
    1. (Note) The systemd-resolve config is /etc/systemd/resolved.conf.
    2. (Optional) Configure static upstream DNS servers (don’t use any provided by DHCP/SLAAC): In the confug, set DNS=1.1.1.1 2606:4700:4700::1111.
    3. (Optional) Set the domain/search string: In the config, set Domains=<domains>.
    4. Disable DNSSEC validation (enabling it may cause NTP problems): In the config, set DNSSEC=no.
    5. Enable and start it: systemctl enable --now systemd-resolved
    6. Setup resolv.conf: ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
    7. Check: resolvectl query vg.no and curl google.com
  19. Setup the NTP client (systemd):
    1. (Note) The default server pool is fine.
    2. Enable: sudo timedatectl set-ntp true
    3. Check: timedatectl (see the “synchronized” field)
  20. Setup firewall (IPTables):
    1. Install IPTables: sudo pacman -S iptables
    2. Enable the IPTables services: sudo systemctl enable --now iptables.service ip6tables.service
    3. Download my IPTables script (or do it yourself): sudo curl https://raw.githubusercontent.com/HON95/scripts/master/iptables/iptables.sh -o /etc/iptables/config.sh
    4. Make it executable: sudo chmod +x /etc/iptables/config.sh
    5. Modify it.
      • It currently defaults to Debian-specific stuff, so remove those lines and uncomment the Arch-specific lines.
    6. Run it: sudo /etc/iptables/config.sh
  21. (Optional) Setup colored man pages:
    1. (Note) Most breaks on wide displays (e.g. UHD), so don’t use it if that may be a problem.
    2. Install the most pager: sudo pacman -S most
    3. Set it as the default pager: In .bashrc and/or .zshrc, set export PAGER=most
  22. Setup a BASH command completion dir (also used by ZSH for CLI apps that don’t support ZSH):
    1. Create dir /etc/bash_completion.d.
    2. Setup /etc/profile.d/completion.sh, see the example below.
  23. (Optional) Reboot.

Setup the Xorg Display Server

  1. Install: sudo pacman -S xorg-server xorg-xinit xorg-xrandr xorg-xinput

Setup the LightDM or Ly Display Manager

Note: Install either the LightDM (X11 GUI) or Ly (TTY TUI) display manager, not both. Ly is more minimalistic but doesn’t work well with multiple monitors where you may want to specify the layout in Xorg.

LightDM (Alternative 1)

  1. Setup LightDM:
    1. (Note) User-local configuration/profile-stuff should be placed in ~/.xprofile.
    2. Install: sudo pacman -S lightdm
    3. Enable: systemctl enable lightdm
  2. Setup the LightDM GTK+ greeter (aka login screen) (one of many):
    1. (Note) The GTK+ greeter may be configured in /etc/lightdm/lightdm-gtk-greeter.conf or using the lightdm-gtk-greeter-settings GUI.
    2. Install: sudo pacman -S lightdm-gtk-greeter
    3. Set it as the default: In /etc/lightdm/lightdm.conf, under the [Seat:*] section, set greeter-session=lightdm-gtk-greeter.
    4. (Optional) Set the background: In /etc/lightdm/lightdm-gtk-greeter.conf, under the [greeter] section, set background=<image-path>. The /usr/share/pixmaps dir is recommended for storing backgrounds.
  3. Enable numlock on by default in X11:
    1. Install: sudo pacman -S numlockx
    2. Configure: In /etc/lightdm/lightdm.conf, under the [Seat:*] section, set greeter-setup-script=/usr/bin/numlockx on.

Ly (Alternative 2)

  1. Setup Ly:
    1. (Note) The config file is /etc/ly/config.ini.
    2. Install: yay -S ly
    3. Enable: sudo systemctl enable ly
    4. Add fire background: In the config, set animate = true and hide_borders = true.
  2. Enable numlock on by default in X11:
    1. Install: sudo pacman -S numlockx
    2. Configure: Create /etc/X11/xinit/xinitrc.d/90-numlock.sh, containing #!/bin/sh and numlockx &. Make it executable.

Setup the i3 Window Manager Basics

  1. (Note) Some notes about i3:
    • Se i3 for more personal notes about i3.
    • Use Mod+Shift+R to reload the i3 config.
    • Use Mod+Shift+E to exit i3.
    • Use Mod+Enter to open a terminal.
    • Use the terminal to open the web browser, since launchers aren’t set up yet.
    • exec_always config statements will be run again during reload but execstatements will only run when starting i3.
  2. Setup fonts:
    1. Install basic font with emoji support: sudo pacman -S noto-fonts noto-fonts-emoji
  3. Install i3:
    1. Install: sudo pacman -S i3-wm
    2. (Note) Vital parts are missing in the i3 config, follow the remaining steps before attempting to use i3.
  4. Fix the keyboard layout for X11:
    1. Set: sudo localectl set-x11-keymap <keymap> (e.g. no)
  5. Install temporary apps to get the remaining of the setup done:
    1. Install terminal emulator and web browser: sudo pacman -S alacritty firefox
      • If asked, select pipewire-jack and wireplumber.
  6. Reboot.
  7. Arrive at window manager (LightDM/Ly).
    • Use Ctrl+Alt+F1 if you need to enter a terminal TTY (TTY1). Ly/LightDM uses one of the first TTYs, the rest are terminal TTYs.
  8. Select the i3 WM and log in.
  9. If prompted, follow the basic i3 setup wizard:
    1. Generate a new config.
    2. Win as default modifier.
  10. Press Mod+Enter to open a terminal.

Setup Post-Window Manager Stuff

  1. Setup displays:
    1. (Note) Using an xrandr script instead of Xorg config due to problems with 144Hz displays and reduced flexibility.
    2. (Note) DPMS (Display Power Management Signaling) is automatically enabled for all displays.
    3. Show displays: xrandr
    4. (Example) Temporarily configure displays:
      1. Main display example: xrandr --output eDP --auto
      2. Rotated right display example: xrandr --output HDMI-A-0 --right-of eDP --rotate left --auto
      3. Set full RGB range:
        • Intel GPUs: xrandr --output DP-1 --set "Broadcast RGB" "Full"
        • AMD GPUs: xrandr --output DP-1 --set "output_csc" "bypass"
    5. Create an executable script $HOME/.config/xrandr.sh containing the configure commands for all displays. Call it from the i3 config.
  2. (Touchpad) Setup touchpad (Synaptics):
    1. Install driver: sudo pacman -S libinput
    2. Add touchpad config to Xorg: In /etc/X11/xorg.conf.d/70-synaptics.conf, add the config snippet from below. TODO
    3. TODO fix this
  3. (Touchscreen) Setup touchscreen:
    1. (Note) The touchscreen should be mostly plug-and-play, but the mapping might be wrong when using multiple displays.
    2. Show input devices (should list the touchscreen): xinput --list
    3. (Example) Map the touchscreen to the main display: xinput --map-to-output 'x' eDP (for touchscreen x)
  4. (Laptop) Fix display brightness buttons:
    1. (Note) This is an alternative to using the xorg-xbacklight package, which didn’t work for me neither on AMD nor Intel laptops.
    2. Try manually changing the backlight:
      1. Find the backlight controller in /sys/class/backlight.
      2. Find the maximum brightness in /sys/class/backlight/<x>/max_brightnes.
      3. Set a new brightness: echo 10 | sudo tee /sys/class/backlight/<x>/brightness
      4. Verify that it actually changed. If not, this won’t work.
    3. Add udev rules to allow changing the brightness through the video group:
      1. In /etc/udev/rules.d/backlight.rules, add the following (template, using <x> from above):
         ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="<x>", RUN+="/bin/chgrp video /sys/class/backlight/<x>/brightness"
         ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="<x>", RUN+="/bin/chmod g+w /sys/class/backlight/<x>/brightness"
        
      2. (Optional) Reboot and try writing to the file without root.
    4. Add a script/program for changing the brightness:
      1. Create a /usr/local/bin/display-backlight script to control the backlight. Example script.
    5. Add i3 keybinds:
      1. In the i3 config, add:
         bindsym XF86MonBrightnessUp exec --no-startup-id /usr/local/bin/display-backlight +1
         bindsym XF86MonBrightnessDown exec --no-startup-id /usr/local/bin/display-backlight -1
        
  5. (Optional) Setup better console font:
    1. (Note) Using the MesloLGS font. See this for more info.
    2. Create the TTF dir: sudo mkdir -p /usr/share/fonts/TTF
    3. Download fonts: for x in Regular Bold Italic Bold\ Italic; do sudo curl -sSfL "https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20${x/ /%20}.ttf" -o "/usr/share/fonts/TTF/$x.ttf"; done
  6. Setup the Polybar system bar:
    1. (Note) i3bar, the default i3 system bar, shows workspaces and tray icons. It can include extra info like IP addresses and resource usage using i3status or i3blocks. Polybar is a replacement for i3bar.
    2. Disable i3bar: Comment the whole bar section of the i3 config.
    3. Install polybar: yay -S polybar
    4. Create the config: mkdir ~/.config/polybar && cp /usr/share/doc/polybar/examples/config.ini ~/.config/polybar/config
    5. Customize config:
      • Rename the “example” bar to e.g. “main” (or create one from scratch).
      • Set the font: In the bar section, remove the existing font-<n> statements. Set font0 = <family>:style=<s>:size=<n>;<vertical-offset> (e.g. font-0 = "MesloLGS NF:style=Regular:size=9;2"). Use fc-list | grep <font-name> (the part after the first colon) to search for fonts. Make sure to use a Unicode-compatible font (which the default may not be.
      • For the bar, set bottom = true to move it to the bottom.
      • For the bar, comment radius to disable rounded corners.
      • For the bar, comment border-size to disable the padding/border around the bar.
      • For the date module, customize how time should appear. “Alt” variants are swapped to when the module is clicked.
      • For the network/”eth” module, use %local_ip6% for the IPv6 address (one of them). Maybe clone the module to have one for IPv4 and one for IPv6.
      • Update the panel modules in the modules-{left,center,right} variables.
    6. Create a startup script: See the section below to use the new “main” bar. Make it executable.
    7. Add to i3: In the i3 config, add exec_always --no-startup-id $HOME/.config/polybar/launch.sh.
  7. Setup the Alacritty terminal emulator (or some other):
    1. Install: sudo pacman -S alacritty
    2. Create the config dir: mkdir ~/.config/alacritty/
    3. (Optional) Download the Dracula theme: curl https://raw.githubusercontent.com/dracula/alacritty/master/dracula.yml -o ~/.config/alacritty/dracula.yml
    4. Configure: Setup ~/.config/alacritty/alacritty.yml, see the example config below.
    5. Setup i3: In the i3 config, replace the bindsym $mod+Return ... line with bindsym $mod+Return exec alacritty
    6. (Note) Press Ctrl+Shift+Space to enter vi mode, allowing you to e.g. move around (and scroll up) using arrow keys and select text using V or Shift+V. Press Ctrl+Shift+Space again to exit.
  8. Setup the Rofi application launcher:
    1. Install: sudo pacman -S rofi
    2. Install rofimoji for emoji menu: sudo pacman -S rofimoji xdotool
    3. (Optional) Find a theme interactively (without selecting any): rofi-theme-selector (e.g. glue_pro_blue)
    4. Configure Rofi: Create ~/.config/rofi/config.rasi, see the example below.
    5. Configure Rofimoji: Create ~/.config/rofimoji.rc and set action = copy (copy to clipboard by default).
    6. Disable old i3 dmenu shortcut: In the i3 config, comment the bindsym $mod+d line.
    7. Setup i3 drun shortcut: In the i3 config, set bindsym $mod+d exec rofi -show drun.
    8. Setup i3 window shortcut: In the i3 config, set bindsym $mod+shift+d exec rofi -show window.
    9. Setup i3 emoji shortcut: In the i3 config, set bindsym $mod+mod1+d exec rofi -modi "emoji:rofimoji" -show emoji.
  9. Setup background image:
    1. Download a desktop image.
    2. Install the FEH image viewer: sudo pacman -S feh
    3. Update i3: In the i3 config, set exec_always --no-startup-id feh --bg-scale $HOME/Pictures/background.png (example).
  10. (Optional) Disable mouse hover window focus (you can still click windows to focus):
    1. In the i3 config, set focus_follows_mouse no.
  11. (Optional) Setup i3 gaps:
    1. (Note) Requires i3-gaps instead of normal i3, which should work as a drop-in replacement with more options.
    2. Replace i3 with i3-gaps: sudo pacman -S i3-gaps (then replace i3-wm with i3-gaps)
    3. Disable window title bar (required): In the i3 config, add for_window [class=".*"] border pixel 4 to only show the border and no title bar, or 0 to remove the border too.
    4. Add gaps around windows: In the i3 config, add gaps inner 8.
  12. Install clipboard manager:
    1. sudo pacman -S xsel
    2. TODO Fix this. Basic copy-pase doesn’t require xsel. Copying from a terminal and closing it erases the copy content, which is undesirable.
  13. (Optional) Setup wireless networking tray icon and GUI (for iwd):
    1. (Note) Make sure your user is a member of the netdev group to allow controling iwd.
    2. Install (with snixembed compat library for Polybar): yay -S iwgtk snixembed-git
    3. Start snixembed in i3 config: exec --no-startup-id snixembed
    4. (Optional) Remove the XDG autostart file: rm /etc/xdg/autostart/iwgtk-indicator.desktop
    5. (Optional) Start tray icon in i3 config instead: exec --no-startup-id iwgtk -i
    6. (Example) Test: iwgtk (GUI) or iwgtk -i (tray icon)
      • Might fail until relog/reboot.
  14. Setup desktop notifications:
    1. Install the dunst server and the libnotify support library: sudo pacman -S dunst libnotify
    2. (Optional) Modify the config:
      1. (Note) The global config is /etc/dunst/dunstrc.
      2. Create and open it: mkdir -p ~/.config/dunst && vim ~/.config/dunst/dunstrc
      3. For high-res displays, fix scaling (doesn’t affect text size): In the global section, set e.g. scale = 2.
      4. Change the font and font size: In the global section, set e.g. font = MesloLGS NF 8 (or 12 for high-res).
    3. Restart dunst (if any changes): systemctl --user restart dunst
    4. (Optional) Test it: notify-send 'Hello world!' 'This is an example notification.' --icon=dialog-information
  15. Setup screen locking:
    1. Install the i3lock-color screen locker: yay -S i3lock-color
    2. Install the the xss-lock automatic locker: sudo pacman -S xss-lock
    3. Set a variable to run i3lock in i3: In the i3 config, before anything i3lock related, set e.g. set $i3lock i3lock --nofork --ignore-empty-password --pass-media-keys, to avoid repetition.
    4. (Optional) Specify an i3lock background image: To the above command, add e.g. --image Pictures/background.png.
    5. Set a locking keybind in i3: In the i3 config, add bindsym $mod+l exec --no-startup-id $i3lock. This may conflict with some focus keybinds you probably don’t need, so just remove those (i3 will tell you about it if you don’t remove them).
    6. Update i3 for automatic locking: In the i3 config, find the example xss-lock line and replace it with exec --no-startup-id xss-lock --transfer-sleep-lock -- $i3lock. (Test with loginctl lock-session after restarting or relogging.)
  16. Setup autostarting of desktop applications:
    1. (Note) Desktop applications are applications with <name>.desktop files. These applications may be autostarted using a tool like dex, following the XDG Autostart spec.
    2. (Note) To enable autostarting for a desktop application, find/create a .desktop entry file for it in /etc/xdg/autostart (system) ~/.config/autostart (user). A simple method is to find the entry in e.g. /usr/share/applications/ (system) or ~/.local/share/applications/ (user), then symlink it into the appropriate autostart directory (e.g. ln -s /usr/share/applications/discord.desktop ~/.config/autostart).
    3. Install dex: sudo pacman -S dex
    4. Add this to your i3 config: exec --no-startup-id dex --autostart --environment i3
    5. (Optional) Test it: dex --autostart --environment i3 &>/dev/null

Setup Audio

Note: We’re using the PipeWire sound server, a modern, security-focused and compatible replacement for both PulseAudio and JACK. See PipeWire (Applications) for more config info.

  1. Install ALSA stuff:
    1. (Note) ALSA itself is already provided as built-in kernel modules and ALSA drivers will just work.
    2. Install ALSA utils and firmware: sudo pacman -S alsa-utils alsa-firmware
  2. Install PipeWire (including WirePlumber and adapters):
    1. Install: sudo pacman -S pipewire pipewire-alsa pipewire-pulse pipewire-jack pipewire-v4l2 pipewire-x11-bell wireplumber pavucontrol
    2. Start the PulseAudio adapter (to avoid relogging): systemctl --user start pipewire-pulse
  3. Configure inputs and outputs:
    1. Run pavucontrol to configure volumes, inputs, outputs and stuff.
  4. (Optional) Test it:
    1. Try playing something from the browser or whatever. It should work.
  5. (Optional) Install useful audio applications:
    1. Install the Helvum patchbay to patch nodes and endpoints (inputs and outputs for all audio devices): sudo pacman -S helvum
    2. See the PipeWire page (Arch Wiki).
  6. Setup media keys:
    1. (Note) Install e.g. Spotify (aur/spotify, official) to test with.
    2. Install the playerctl utility for easy control: sudo pacman -S playerctl
    3. Add the following to the i3 config: See the i3 media keys config snippet below.
  7. Tweak audio volume keys:
    1. Install pamixer (like ALSA’s amixer but for PulseAudio): sudo pacman -S pamixer
    2. Open the i3 config and find the bindsym XF86AudioRaiseVolume and similar lines.
    3. See the config i3 volume keys snippet below.
  8. Setup a Spotify module for Polybar:
    1. Install: yay -S polybar-spotify-git
    2. In the Polybar config (~/.config/polybar/config), add a module spotify (see config snipper below) and add it to some bar module section.

Setup Bluetooth

  1. (Note) Make sure rfkill or some hardware switch isn’t disabling/blocking the adapter.
  2. Setup the base stack:
    1. (Note) The canonical Bluetooth implementation is BlueZ.
    2. Install: sudo pacman -S bluez bluez-utils
    3. Enable and start: sudo systemctl enable --now bluetooth.service
    4. (Optional) Allow users to use Bluetooth networking or something: Add the users to the lp group.
    5. (Optional) Enable auto power-on after boot and resume: In /etc/bluetooth/main.conf, in the Policy section, set AutoEnable = true.
  3. Setup audio:
    1. (Note) Using PipeWire and its PulseAudio adapter (pipewire-pulse), which should already have been set up and includes support for Bluetooth.
  4. Setup Blueman:
    1. (Note) Blueman is a Bluetooth manager with a practical tray icon.
    2. Install: sudo pacman -S blueman
    3. (Optional) Try to run it. It’s the “Bluetooth Manager” entry in e.g. Rofi.
  5. (Example) Connect a device using bluetoothctl:
    1. (Note) To avoid entering the interactive TUI and run single commands instead, use bluetoothctl -- <cmd>.
    2. Enter the TUI: bluetoothctl
    3. (Optional) List controllers: list
    4. (Optional) Select a controller: select <mac>
    5. Enable the controller: power on
    6. Enable scanning: scan on
    7. Wait for devices to appear in the terminal.
    8. List available devices: devices
    9. (Optional) Enable the pairing agent: agent on
    10. (Optional) Set the agent as default: default-agent
    11. Pair with device: pair <mac>
    12. Wait for pairing to complete.
    13. (Optional) Trust it (sometimes required): trust <mac>
    14. (Optional) Reconnect to device: connect <mac>
    15. Exit: Ctrl+D

Setup Applications

  1. Setup terminal emulator:
    1. Already done.
  2. Setup the ZSH shell:
    1. See Applications: ZSH (includes font, theme and plugins).
  3. Setup the VLC video and audio player:
    1. Install: sudo pacman -S vlc
  4. Setup the Mirage image viewer:
    1. Install: yay -S mirage
  5. Setup the GIMP image editor:
    1. Install: sudo pacman -S gimp
  6. Setup the Thunar graphical file manager:
    1. Install: sudo pacman -S thunar
  7. Setup the Ranger terminal file explorer:
    1. Install: sudo pacman -S ranger
  8. Setup the VS Code text editor/IDE:
    1. (Alternative 1) Install the Arch-built: sudo pacman -S code
    2. (Alternative 2) Install the Microsoft binary distribution with tracking and Microsoft extensions: yay -S visual-studio-code-bin
  9. Setup the LibreOffice office document suite:
    1. Install: sudo pacman -S libreoffice-fresh
  10. Setup the Okular PDF reader:
    1. Install: sudo pacman -S okular
  11. Setup the screenshot tool Maim (for keybinds and easy CLI usage):
    1. Install: sudo pacman -S maim
    2. Setup i3 keybinds: See the i3 config snippet below.
  12. Setup the screenshot tool Flameshot (for GUI and on-screen editing):
    1. Install: sudo pacman -S flameshot
    2. (Usage) Start the tray icon: Run the “Fireshot” desktop application.
    3. (Usage) Directly open the capture GUI from the terminal: fireshot gui
  13. Setup the 7-Zip CLI/GUI archiver:
    1. Install: yay -S p7zip-gui
    2. (Note) Don’t use the .7z file format, it doesn’t preserve owner info.
  14. Setup network tools:
    1. Install: sudo pacman -S nmap tcpdump wireshark-qt
  15. Set default applications (after installation):
    1. Web browser: xdg-settings set default-web-browser firefox.desktop

Extra (Optional)

Config Snippets

systemd-networkd Network Config

File: /etc/systemd/network/en.network (example)

This example sets up any interface starting with en (i.e. wired Ethernet interfaces) to use DHCPv4 and SLAAC/DHCPv6. The DHCP and IPv6AcceptRA sections are optional, the default values are typically fine. Use RouteMetric=2048 for WLAN interfaces to prefer LAN when both are connected. For WLAN interfaces, add IgnoreCarrierLoss=5s to the Network section to prevent it from going down during short connection issues. Add LLDP=yes to capture LLDP info (but not emit it), if you’re into that. Use Anonymize for DHCPv4 to hide client info and emulate a Windows client (DHCPv6 doesn’t send any too revealing info).

[Match]
Name=en*

[Network]
DHCP=yes
IPv6AcceptRA=yes
IPv6PrivacyExtensions=yes
#LLDP=yes

[DHCPv4]
RouteMetric=1024
UseDNS=yes
UseNTP=no
UseHostname=no
UseDomains=yes
Anonymize=yes

[DHCPv6]
RouteMetric=1024
UseDNS=yes
UseNTP=no
UseHostname=no
UseDomains=yes

[IPv6AcceptRA]
RouteMetric=1024
UseDNS=yes
UseDomains=yes

iwd Config

File: /etc/iwd/main.conf

[General]
AddressRandomization=network

[Settings]
AutoConnect=true

[Scan]
DisablePeriodicScan=no

iwd Config

File: /var/lib/iwd/eduroam.8021x (for SSID eduroam)

The following values from the eduroam configuration assistant tool (CAT) are required (from Arch iwd wiki page):

iwd eduroam Comment
File name Config.ssids (one) Typically eduroam, with 8021x file ending.
EAP-Method Config.eap_outer  
EAP-Identity Config.anonymous_identity @Config.user_realm if missing.
EAP-PEAP-CACert Config.CA Place the cert data in a file and specify the path.
EAP-PEAP-ServerDomainMask Config.servers (one) Without DNS: prefix.
EAP-PEAP-Phase2-Method Config.eap_inner  
EAP-PEAP-Phase2-Identity <username>  
EAP-PEAP-Phase2-Password <password>  

Place the CA certificate in /var/lib/iwd/eduroam.crt.

NTNU eduroam template:

[Security]
EAP-Method=PEAP
EAP-Identity=@ntnu.no
EAP-PEAP-CACert=/var/lib/iwd/eduroam.crt
EAP-PEAP-ServerDomainMask=DNS:radius.ntnu.no
EAP-PEAP-Phase2-Method=MSCHAPV2
EAP-PEAP-Phase2-Identity=<username>@ntnu.no
EAP-PEAP-Phase2-Password=<password>

[Settings]
AutoConnect=true

wpa_supplicant Config

File: /etc/wpa_supplicant/wpa_supplicant.conf

ctrl_interface=/run/wpa_supplicant
ctrl_interface_group=netdev
# Allow wpa_cli to add networks and change the config?
# File permissions may get fucked.
update_config=0
country=NO
# More agressive scanning for roaming
bgscan="simple:30:-70:3600"

# Example networks below, omit these

# WPA Personal
# Use "wpa_passphrase <ssid>" to generate a network stub with a PSK-hashed password to avoid cleartext.
network={
    ssid="Example"
    psk="HelloWorld"
}

# WPA Enterprise (PEAP-MSCHAPv2) (NTNU eduroam example)
network={
    key_mgmt=WPA-EAP
    pairwise=CCMP
    group=CCMP TKIP
    eap=PEAP
    phase2="auth=MSCHAPV2"
    # Point to actual EAP CA cert
    ca_cert="/var/lib/wpa_supplicant/certs/eduroam.crt"
    altsubject_match="DNS:radius.ntnu.no"
    anonymous_identity="@ntnu.no"
    # Your credentials
    identity="[email protected]"
    password="user_password"
}

# dot1x wired (PEAP-MSCHAPv2)
# NOT TESTED
network={
    key_mgmt=IEEE8021X
    eap=PEAP
    identity="user_name"
    password="user_password"
    phase2="autheap=MSCHAPV2"
}

Polybar Launch Script

File: ~/.config/polybar/launch.sh

#!/bin/bash

killall -q polybar

#polybar main &>>/tmp/polybar.log &
polybar main >/dev/null 2>&1 &

Polybar Spotify Module

File: ~/.config/polybar/config

[module/spotify]
type = custom/script
interval = 1
format = <label>
#exec = python /usr/share/polybar/scripts/spotify_status.py -f '[{artist}] {song}' -t 50 -q
exec = python /usr/share/polybar/scripts/spotify_status.py -f '{song}' -t 25 -q
format-underline = #1db954

Alacritty Config

File: ~/.config/alacritty/alacritty.yml

font:
  # normal:
  #   family: MesloLGS NF
  #   style: Regular
  size: 9

env:
  TERM: xterm-256color

import:
  # Theme
  - ~/.config/alacritty/dracula.yml

Rofi Config

file: ~/.config/rofi/config.rasi

configuration {
    font: "MesloLGS NF 10";
}
@theme "glue_pro_blue"

Xorg Monitors

File: /etc/X11/xorg.conf.d/10-monitor.conf

Section "Monitor"
    Identifier "DP-4"
    Option "Primary" "true"
EndSection

Section "Monitor"
    Identifier "DVI-I-1"
    Option "RightOf" "DP-4"
    Option "Rotate" "left"
EndSection

Xorg DPMS

File: /etc/X11/xorg.conf.d/20-dpms.conf

Section "ServerFlags"
    # In minutes, 0 to disable
    Option "StandbyTime" "0"
    Option "SuspendTime" "0"
    Option "OffTime" "30"
    Option "BlankTime" "0"
EndSection

Alternatively, to disable DPMS completely:

Section "Extensions"
    Option "DPMS" "Disable"
EndSection

BASH Command Completion Configs

File: /etc/profile.d/completion.sh

# Don't include /usr/share/bash-completion/bash_completion,
# assume bashrc or something already includes it.
# We don't want that when reading /etc/profile with ZSH anyways.

if [[ $PS1 && -d /etc/bash_completion.d/ ]]; then
    for f in /etc/bash_completion.d/*; do
        test -r "$f" && . "$f"
    done
    unset f
fi

i3 Media Keys

File: ~/.config/i3/config

Requires playerctl.

# Media keys
bindsym XF86AudioPlay exec --no-startup-id playerctl play-pause
bindsym XF86AudioPause exec --no-startup-id playerctl play-pause
bindsym XF86AudioStop exec --no-startup-id playerctl stop
bindsym XF86AudioPrev exec --no-startup-id playerctl previous
bindsym XF86AudioNext exec --no-startup-id playerctl next

i3 Volume Keys

File: ~/.config/i3/config

Requires pamixer.

# Volume keys
bindsym XF86AudioRaiseVolume exec --no-startup-id pamixer -i 5
bindsym XF86AudioLowerVolume exec --no-startup-id pamixer -d 5
bindsym XF86AudioMute exec --no-startup-id pamixer -t
bindsym XF86AudioMicMute exec --no-startup-id pamixer --default-source -t

i3 Maim Screenshot Keys

File: ~/.config/i3/config

Requires maim.

# Capture screen (active window and full)
bindsym $mod+Print exec maim -i $(xdotool getactivewindow) $HOME/Downloads/Screenshot_$(date -Iseconds).png
bindsym $mod+Shift+Print exec maim $HOME/Downloads/Screenshot_$(date -Iseconds).png

Troubleshooting

Fix Boot

  1. Boot into live-OS.
  2. Find the disk: lsblk
  3. Decrypt it: cryptsetup luksOpen /dev/<partition> crypt_root
  4. Mount it: mount /dev/mapper/crypt_root /mnt
  5. Mount the EFI partition: mount /dev/<partition-1> /mnt/boot/efi
  6. Chroot into it: arch-chroot /mnt
  7. Fix GRUB: grub-install --target=x86_64-efi --efi-directory=/boot/efi && grub-mkconfig -o /boot/grub/grub.cfg
  8. Fix initramfs: mkinitcpio -P

If the GRUB or initramfs commands didn’t work (e.g. if it broke during an Pacman upgrade and lots of packages are corrupt):

  1. Exit the chroot (if inside it).
  2. Mount other stuff:
    • mount -t proc /proc /mnt/proc
    • mount --rbind /sys /mnt/sys
    • mount --rbind /dev /mnt/dev
  3. (Maybe) Fix DNS: rm /mnt/etc/resolv.conf; echo nameserver 1.1.1.1 > /mnt/etc/resolv.conf
  4. (Maybe) Remove the Pacman DB lock: rm /mnt/var/lib/pacman/db.lck
  5. (Maybe) Overwrite the Pacman mirrorlist: cp /etc/pacman.d/mirrorlist /mnt/etc/pacman.d/mirrorlist
  6. Reinstall all packages:
    1. Get packages: pacman --sysroot /mnt -Qq >tmp.txt
    2. Remove non-Pacman packages (e.g. from yay) from the text file until the next command succeeds.
    3. Reinstall: pacman --sysroot /mnt -S --overwrite "*" - <tmp.txt
  7. Fix boot dir perms: chmod 700 /mnt/boot
  8. Fix resolvconf: ln -sf /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf
  9. Reboot into fixed OS.
  10. Fix AUR packages: yay -Qqm | yay -S -

hon.one | HON95/wiki | Edit page