Dotfiles managed with chezmoi.
Install chezmoi with:
sh -c "$(curl -fsLS git.io/chezmoi)"Install and apply configuration with:
./bin/chezmoi init https://github.com/nicholaschiang/dotfiles.git --applyFirst, install brew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Then, you can install my preferred development tooling:
brew install atuin bat btop eza fastfetch fish fzf git-delta kubectx k9s mise neovim rust starship tmux uv zoxideYou can then use mise to configure global node and python installations:
mise use --global node@22 python@3When you first launch vim (or, rather, neovim), you will need to:
:PlugInstall
...to install all of my vim plugins (configured via vim-plug).
I also install rust CLI tooling directly using cargo:
cargo install just ruplacerYou can use brew to install my preferred GUI applications on MacOS:
brew install --cask docker-desktop firefox figma font-iosevka notion-calendar raycast wezterm alacrittyI typically use wezterm with tmux on MacOS, but alacritty is also very good.
From my experience, alacritty is faster than wezterm but is less feature rich (e.g. it does not support ligatures).
My preferred distro of choice is currently Arch Linux, primarily because (a) I love that it comes with essentially nothing baked-in, (b) it has absolutely stellar documentation, and (c) it has an incredible package ecosystem in AUR.
First, install Arch. I referenced these two guides (1, 2) when I installed Arch alongside an existing Windows 11 installation. I had to resolve an issue with GRUB and LUKS encryption this way.
To configure WiFi:
❯ iwctl
To configure Bluetooth:
❯ bluetoothctl
To inspect the system:
❯ btop
❯ hostnamectl
❯ fastfetch
❯ neofetch
❯ uname -r
❯ pacman -Qs
I no longer use GRUB (it is slow and bloated).
I no longer encrypt the kernel .img files (doing so is unnecessary).
I was going to setup Limine instead (which Omarchy uses), but Limine lacks the ability to select the next boot entry programmatically, which is a must-have for me to create a Windows desktop shortcut in Arch. I also do not use many of the features of Limine (e.g. snapshots). The CachyOS Wiki has a good bootloader comparison table.
Instead, I use systemd-boot.
I configured systemd-boot via bootctl by referencing the Arch Linux Wiki and this guide.
I copied the necessary kernel options to load my encrypted BTRFS volume from my previous grub.cfg.
I could have also gotten the necessary persistent block device UUIDs from lsblk -f or blkid.
In /boot/efi/loader/entries/arch.conf:
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=UUID=2bdd61b8-be29-44b5-a699-a2118aa6305e rw rootflags=subvol=@ cryptdevice=UUID=1459c007-fe70-4092-a22b-363eda9eaede:root zswap.enabled=0 rootfstype=btrfs
In /boot/efi/loader/entries/arch-fallback.conf:
title Arch Linux (fallback initramfs)
linux /vmlinuz-linux
initrd /initramfs-linux-fallback.img
options root=UUID=2bdd61b8-be29-44b5-a699-a2118aa6305e rw rootflags=subvol=@ cryptdevice=UUID=1459c007-fe70-4092-a22b-363eda9eaede:root zswap.enabled=0 rootfstype=btrfs
My BTRFS setup aligns with the default provided by the archinstall TUI:
❯ sudo btrfs subvolume list /
[sudo] password for nchiang:
ID 256 gen 174764 top level 5 path @
ID 257 gen 174764 top level 5 path @home
ID 258 gen 174764 top level 5 path @log
ID 259 gen 174617 top level 5 path @pkg
ID 260 gen 7603 top level 256 path var/lib/portables
ID 261 gen 7603 top level 256 path var/lib/machines
❯ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1
└─sda2 exfat 1.0 X9 Pro ACA5-33DF
sdb iso9660 Joliet Extension ARCH_202509 2025-09-01-16-37-02-00
├─sdb1 iso9660 Joliet Extension ARCH_202509 2025-09-01-16-37-02-00
└─sdb2 vfat FAT32 ARCHISO_EFI 68B5-CBAE
zram0 swap 1 zram0 585a6947-4e2d-48fe-8411-448e13116955 [SWAP]
nvme0n1
├─nvme0n1p1 vfat FAT32 SYSTEM 48EA-8E84
├─nvme0n1p2
├─nvme0n1p3 BitLocker 2 79e130d4-0616-41ff-b4ed-9fa641aff8a9
├─nvme0n1p4 ntfs 8CE06ED7E06EC754
├─nvme0n1p5 ntfs RESTORE 4EEC1B1BEC1AFD41
├─nvme0n1p6 vfat FAT32 MYASUS 341B-2A97
├─nvme0n1p7 vfat FAT32 FFBD-D04F 150.3M 50% /boot/efi
├─nvme0n1p8 swap 1 27a98047-7832-4e79-b613-5b536d5bc626 [SWAP]
└─nvme0n1p9 crypto_LUKS 2 1459c007-fe70-4092-a22b-363eda9eaede
└─root btrfs 2bdd61b8-be29-44b5-a699-a2118aa6305e 75.3G 50% /var/log
/var/cache/pacman/pkg
/home
/
❯ sudo findmnt -nt btrfs
/ /dev/mapper/root[/@] btrfs rw,relatime,compress=zstd:3,ssd,space_cache=v2,subvolid=256,subvol=/@
├─/home /dev/mapper/root[/@home] btrfs rw,relatime,compress=zstd:3,ssd,space_cache=v2,subvolid=257,subvol=/@home
├─/var/cache/pacman/pkg /dev/mapper/root[/@pkg] btrfs rw,relatime,compress=zstd:3,ssd,space_cache=v2,subvolid=259,subvol=/@pkg
└─/var/log /dev/mapper/root[/@log] btrfs rw,relatime,compress=zstd:3,ssd,space_cache=v2,subvolid=258,subvol=/@log
...the extra partitions on my SSD (nvme0n1) are used by the existing Windows installation.
I copied the kernel files from /boot (which lives on the encrypted BTRFS partition) to /boot/efi (which is the 300MB EFI partition).
Previously, grub handled decrypting /boot before loading the kernel.
This was very slow, required entering the same decryption passphrase twice, and systemd-boot does not support loading encrypted kernel files.
I was unable to copy the initramfs-linux-fallback.img file from the /boot directory (on my encrypted BTRFS partition) due to lack of space (on my 300MB EFI partition mounted to /boot/efi).
While systemd-boot will automatically check at boot time for /EFI/Microsoft/Boot/Bootmgfw.efi, my "Windows Boot Manager" was located in a separate EFI partition and thus required configuration.
I determined the FS alias of the EFI partition by using the UEFI shell (installed via edk2-shell) and comparing the output with sudo blkid:
Shell> map
Mapping table
FSO: Alias(s):CD0f0b:;BLK2:
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0x0)/CDROM(0x1)
FS1: Alias(s):HD1b:;BLK7:
PciRoot(0x0)/Pci(0xE,0x0)/NVMe(0x1,C2-96-5C-3C-01-75-A0-00)/HD(1,GPT,DECF284C-0B62-4D09-A598-8B06198A20EE,0x800,0X82000)
FS2: Alias(s):HD1g:;BLK12:
PciRoot(0x0)/Pci(0xE,0X0)/NVMe(0x1,C2-96-5C-3C-01-75-A0-00)/HD(6,GPT,FF98FCA0-7E96-4279-92FF-C24D7B0A4ED1,0X7733B000,0x82000)
...
❯ sudo blkid
/dev/nvme0n1p9: UUID="1459c007-fe70-4092-a22b-363eda9eaede" TYPE="crypto_LUKS" PARTUUID="143b6881-0878-4534-a943-70e763abb1ea"
/dev/nvme0n1p7: UUID="FFBD-D04F" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="86c94f64-f9d3-49a5-ac2c-ea4f1b26b93e"
/dev/nvme0n1p5: LABEL="RESTORE" BLOCK_SIZE="512" UUID="4EEC1B1BEC1AFD41" TYPE="ntfs" PARTLABEL="Basic data partition" PARTUUID="2b42c37e-564a-4ae0-98e7-973d50744b62"
/dev/nvme0n1p3: UUID="79e130d4-0616-41ff-b4ed-9fa641aff8a9" TYPE="BitLocker" PARTLABEL="Basic data partition" PARTUUID="7ffde51e-2f89-449b-9675-4d3c2fcac1a6"
/dev/nvme0n1p1: LABEL="SYSTEM" UUID="48EA-8E84" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI system partition" PARTUUID="decf284c-0b62-4d09-a598-8b06198a20ee"
/dev/nvme0n1p8: UUID="27a98047-7832-4e79-b613-5b536d5bc626" TYPE="swap" PARTUUID="4b56fe9c-b512-4c31-8929-e9804f9a0a55"
/dev/nvme0n1p6: LABEL="MYASUS" UUID="341B-2A97" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="Basic data partition" PARTUUID="ff98fca0-7e96-4279-92ff-c24d7b0a4ed1"
/dev/nvme0n1p4: BLOCK_SIZE="512" UUID="8CE06ED7E06EC754" TYPE="ntfs" PARTUUID="5f93ca63-50b1-441d-a0e7-f7535faa0b95"
/dev/nvme0n1p2: PARTLABEL="Microsoft reserved partition" PARTUUID="660bc4ee-985b-4a71-bb21-da13bc2a17c9"
/dev/sdb2: LABEL_FATBOOT="ARCHISO_EFI" LABEL="ARCHISO_EFI" UUID="68B5-CBAE" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="2d9d5c0b-02"
/dev/sdb1: BLOCK_SIZE="2048" UUID="2025-09-01-16-37-02-00" LABEL="ARCH_202509" TYPE="iso9660" PARTUUID="2d9d5c0b-01"
/dev/mapper/root: UUID="2bdd61b8-be29-44b5-a699-a2118aa6305e" UUID_SUB="4b804401-8ba4-4014-a088-67feca675a34" BLOCK_SIZE="4096" TYPE="btrfs"
/dev/sda2: LABEL="X9 Pro" UUID="ACA5-33DF" BLOCK_SIZE="512" TYPE="exfat" PARTLABEL="Basic data partition" PARTUUID="80b33855-35c4-4a15-8e81-f0430ec2e66b"
/dev/sda1: PARTLABEL="Microsoft reserved partition" PARTUUID="ecfc4322-72f3-4cc1-b3e6-8d3f63ef2cf0"
/dev/zram0: LABEL="zram0" UUID="585a6947-4e2d-48fe-8411-448e13116955" TYPE="swap"
In /boot/efi/loader/entries/windows.conf:
title Windows
efi /shellx64.efi
options -nointerrupt -nomap -noversion HD1b:EFI\Microsoft\Boot\Bootmgfw.efi
In /boot/efi/loader/loader.conf, I configured systemd-boot to load arch.conf by default:
default arch.conf
timeout 0
console-mode max
After confirming systemd-boot worked as expected, I removed grub:
sudo pacman -Rcnsu grub
sudo rm -rf /boot/grub /boot/efi/grub
I booted from a USB to move /boot/efi to /boot by editing /etc/fstab and removing the contents of /boot.
I use SDDM to automatically login and launch sway after disk decryption.
❯ yay -S sddm
❯ sudo systemctl enable sddm.service
In /etc/sddm.conf.d/autologin.conf:
[Autologin]
User=nchiang
Session=sway
In /usr/share/wayland-sessions/sway.desktop:
[Desktop Entry]
Name=Sway
Comment=An i3-compatible Wayland compositor
Exec=sway --unsupported-gpu
Type=Application
DesktopNames=sway;wlroots
I added the --unsupported-gpu option which is required to use the nvidia-open GPU drivers with sway.
I use Plymouth to enter my disk decryption password on login.
In /etc/mkinitcpio.conf:
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth encrypt filesystems fsck)
To ensure the nvidia-open GPU drivers are loaded before Plymouth runs:
In /etc/modprobe.d/nvidia.conf:
options nvidia_drm modeset=1
In /etc/mkinitcpio.conf:
MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm btrfs)
...these changes were inspired by this Omarchy script.
I then regenerated the initramfs:
❯ sudo mkinitcpio -P
I have a 2023 ASUS ROG Zephyrus M16 (GU604VI-M16.I94070). I had to go into the BIOS and set the display mode to "dGPU" (to always use the discrete NVIDIA 4070 laptop GPU). I had to switch my primary LG 45GX950A-B display cable to the USB 3.2 Gen2 Type-C with DisplayPort 1.4 port (right side). This USB-C port (right side) is connected to the discrete GPU while the USB 4 Type-C with Thunderbolt 4 port (left side) is connected to the integrated Intel GPU. I have a secondary display (a 65" LG TV mounted above my desk) connected to the HDMI 2.1 port (left side). This HDMI port is also connected to the discrete GPU. Other Zephyrus laptops have similar port configurations.
Then, from your fresh Arch installation, install yay:
sudo pacman -S --needed git base-devel
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -siThen, you can install my preferred development tooling. You can either run the script I made:
./install.shOr, run the command yourself manually (cherry-picking which tools to install):
yay -S \
alacritty \
atuin \
base \
base-devel \
bat \
bottom \
btop \
btrfs-progs \
brightnessctl \
chezmoi \
chromium \
dnsmasq \
dunst \
efibootmgr \
eza \
fastfetch \
firefox \
fish \
fzf \
git \
git-delta \
git-lfs \
grub \
gst-plugin-pipewire \
intel-ucode \
iwd \
just \
k9s \
kanshi \
less \
libpulse \
libvirt \
linux \
linux-firmware \
man-db \
mise \
neovim \
openssh \
pamixer \
pipewire \
pipewire-alsa \
pipewire-jack \
pipewire-pulse \
playerctl \
postgresql \
python-poetry \
qemu-full \
ripgrep \
rofi-bluetooth-git \
rofi-wayland \
rust \
sof-firmware \
starship \
sway \
swaybg \
swayidle \
swaylock \
sway-contrib \
swtpm \
tldr \
ttc-iosevka \
ttf-font-awesome \
ttf-iosevka-nerd \
usage \
uv \
virt-manager \
waybar \
wezterm \
wget \
wireplumber \
wl-clipboard \
yay \
yay-debug \
zoxide \
zram-generatorI use fish as my default shell:
chsh -s /usr/bin/fishI also disable Bluetooth reconnecting to avoid erroneously reconnecting my earbuds after I switch to my phone:
# /etc/bluetooth/main.conf
ReconnectAttempts=0
To quickly set a system-wide dark theme:
yay -S gnome-themes-extra adwaita-qt5-git adwaita-qt6-git
export GTK_THEME=Adwaita:dark
export GTK2_RC_FILES=/usr/share/themes/Adwaita-dark/gtk-2.0/gtkrc
export QT_STYLE_OVERRIDE=Adwaita-Dark...these are also set in the fish configuration.
To configure the default browser:
/usr/share/applications🔒
❯ xdg-mime default firefox.desktop x-scheme-handler/http
/usr/share/applications🔒
❯ xdg-mime default firefox.desktop x-scheme-handler/https
Finally, you'll probably want to launch sway:
swayI configure fan curves on my laptop with asusctl:
❯ asusctl fan-curve -m Balanced -e true
Starting version 6.1.12
~
❯ asusctl fan-curve -g
Starting version 6.1.12
CPU: enabled: true, 30c:9%,62c:17%,66c:23%,70c:30%,74c:45%,78c:53%,78c:53%,78c:53%
GPU: enabled: true, 30c:9%,62c:16%,66c:22%,70c:29%,74c:44%,78c:51%,78c:51%,78c:51%
MID: enabled: true, 30c:0%,62c:0%,66c:0%,70c:0%,74c:0%,78c:80%,78c:80%,78c:80%
~
❯ asusctl fan-curve -m Performance -g
Starting version 6.1.12
CPU: enabled: true, 30c:9%,62c:17%,66c:23%,70c:30%,74c:45%,78c:53%,78c:53%,78c:53%
GPU: enabled: true, 30c:9%,62c:16%,66c:22%,70c:29%,74c:44%,78c:51%,78c:51%,78c:51%
MID: enabled: true, 30c:0%,62c:0%,66c:0%,70c:0%,74c:0%,78c:80%,78c:80%,78c:80%
Fan curves for Performance
[
(
fan: CPU,
pwm: (45, 79, 117, 137, 175, 234, 234, 234),
temp: (30, 64, 68, 72, 76, 80, 80, 80),
enabled: false,
),
(
fan: GPU,
pwm: (45, 79, 117, 137, 175, 242, 242, 242),
temp: (30, 64, 68, 72, 76, 80, 80, 80),
enabled: false,
),
(
fan: MID,
pwm: (2, 2, 2, 2, 206, 206, 206, 206),
temp: (30, 64, 68, 72, 76, 80, 80, 80),
enabled: false,
),
]
~
❯ asusctl fan-curve -m Balanced -f cpu -D "30c:0%,62c:0%,66c:10%,70c:20%,74c:35%,78c:55%,78c:80%,78c:95%"
Starting version 6.1.12
~
❯ asusctl fan-curve -m Balanced -f gpu -D "30c:0%,62c:0%,66c:10%,70c:20%,74c:35%,78c:55%,78c:80%,78c:95%"
Starting version 6.1.12
~
❯ asusctl fan-curve -g
Starting version 6.1.12
CPU: enabled: false, 30c:0%,62c:0%,66c:10%,70c:20%,74c:34%,78c:54%,78c:80%,78c:94%
GPU: enabled: false, 30c:0%,62c:0%,66c:10%,70c:20%,74c:34%,78c:54%,78c:80%,78c:94%
MID: enabled: true, 30c:0%,62c:0%,66c:0%,70c:0%,74c:0%,78c:80%,78c:80%,78c:80%