dot

vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks

1ea8543

Install with disko on a wiped drive

By Gustaf Granström

The NVMe drive is partitioned and formatted by disko (hosts/desktop/disko.nix)
instead of NixOS moving in next to CachyOS. MIGRATION.md now backs up the home
folder to the spare SATA SSD, saves the built system and the disko script
there so the installer builds nothing, and restores home after the install.
The user's uid is pinned to 1000 to match the restored files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

9 files changed +228 −99

modifiedMIGRATION.md
@@ -1,68 +1,111 @@
11 # Moving from CachyOS to NixOS
22
3-The plan keeps your disk as it is. NixOS goes into new btrfs subvolumes next
4-to CachyOS's, and `/home` stays the same `@home` subvolume. Your files, game
5-libraries, app data, `~/.ssh`, Firefox profile and Steam settings never move,
6-and CachyOS stays bootable until you remove it.
3+The install wipes the whole NVMe drive (`nvme0n1`, the 980 PRO) and lays it out
4+again with disko, as `hosts/desktop/disko.nix` describes. CachyOS and everything
5+in it are gone afterwards, so your home folder goes to the Kingston SATA SSD
6+(`sda`) first and comes back after the install. Game installs aren't backed up
7+(see `backup-filter`): Steam games and WoW download again. WoW's settings and
8+addons are kept.
9+
10+The other SATA SSD (`sdb`) isn't touched at any point. disko only knows the
11+NVMe drive, by its serial number.
12+
13+## 1. Before you start (on CachyOS)
14+
15+- [ ] Push this repo and the latest `Eiziv/philly`.
16+- [ ] Get the NixOS installer (26.05, minimal is enough) on a USB stick, and
17+ make sure Secure Boot is off in the firmware, as it is for Limine now.
18+- [ ] Optional, but this is the last chance: record WoW's performance on
19+ CachyOS, to compare with NixOS later. In Faugus, edit Battle.net, turn
20+ on MangoHud and add this line to the launch arguments:
21+ `MANGOHUD_CONFIG=read_cfg,output_folder=/home/vizie/benchmarks,log_duration=60`.
22+ In game, stand somewhere you can return to (a busy city), keep the camera
23+ still and press Left Shift+F2. Do it three times. The logs land in
24+ `~/benchmarks`, which the backup includes.
25+
26+**Prepare the backup drive.** This erases `sda`, the 112 GB Kingston, which
27+is empty now. Check that the name points at `sda` first:
28+
29+```bash
30+ls -l /dev/disk/by-id/ata-KINGSTON_SA400S37120G_50026B76820FD3CE
31+sudo mkfs.btrfs -L backup /dev/disk/by-id/ata-KINGSTON_SA400S37120G_50026B76820FD3CE
32+sudo mkdir -p /mnt/backup
33+sudo mount -o compress=zstd /dev/disk/by-label/backup /mnt/backup
34+sudo install -d -o vizie /mnt/backup/nix-cache /mnt/backup/wow
35+```
36+
37+**Save the built system.** The finished system and the disko script go onto
38+the backup drive, so the installer doesn't have to build anything (or compile
39+the CachyOS kernel, if its binary cache is still down):
40+
41+```bash
42+cd ~/git/dot
43+sys=$(nix build --no-link --print-out-paths .#nixosConfigurations.desktop.config.system.build.toplevel)
44+disko=$(nix build --no-link --print-out-paths .#nixosConfigurations.desktop.config.system.build.diskoScript)
45+nix copy --to 'file:///mnt/backup/nix-cache?compression=zstd' "$sys" "$disko"
46+echo "$sys" > /mnt/backup/nix-cache/system
47+echo "$disko" > /mnt/backup/nix-cache/disko
48+```
49+
50+**Back up WoW's settings and addons** (`WTF` is keybinds, macros and addon
51+settings, `Interface` is the addons):
52+
53+```bash
54+cp -a ~/Games/battlenet/drive_c/'Program Files (x86)'/'World of Warcraft'/_retail_/{WTF,Interface} /mnt/backup/wow/
55+```
56+
57+**Back up your home folder.** Quit Signal, Discord, Firefox, Claude and the
58+games first, so their databases aren't copied halfway through a write. About
59+83 GB before compression, and the saved system adds roughly 10 GB, so it fits
60+the 112 GB drive with some room. If it runs out of space, leave out repos that
61+are pushed to GitHub (the biggest are `git/skate3`, 23 GB, and `git/philly`,
62+16 GB) with an extra `--exclude=/git/skate3/`:
763
8-## 1. Before you start
64+```bash
65+sudo rsync -aHAXx --info=progress2 --filter='merge /home/vizie/git/dot/backup-filter' /home/vizie/ /mnt/backup/vizie/
66+```
967
10-- [ ] Push this repo (`git push`) and the latest `Eiziv/philly`. The install
11- fetches philly from GitHub.
12-- [ ] Back up what you can't get back to another disk or machine, in case
13- something goes wrong with the partition: `~/.ssh`, `~/.config/keys`
14- (the imsh upload key), `~/.config/Signal` (including `config.json`, which
15- holds the key to Signal's database), `~/.config/mozilla`, game saves that
16- aren't in a cloud.
17-- [ ] Optional: a read-only snapshot of /home to roll back to:
18- `sudo btrfs subvolume snapshot -r /home /home/.snapshot-pre-nixos`
19-- [ ] Get the NixOS installer (26.05, graphical or minimal) on a USB stick.
68+Check that it looks complete (`ls -a /mnt/backup/vizie`, `du -sh /mnt/backup/*`),
69+then `sudo umount /mnt/backup`.
2070
2171 ## 2. Install
2272
23-Boot the installer. Wired network works out of the box.
73+Boot the installer. Wired network works out of the box; the install itself
74+doesn't need it.
2475
2576 ```bash
2677 sudo -i
2778
28-# The btrfs partition's top level, to make NixOS's subvolumes.
29-mkdir -p /mnt/top
30-mount -o subvolid=5 /dev/nvme0n1p2 /mnt/top
31-btrfs subvolume create /mnt/top/@nixos
32-btrfs subvolume create /mnt/top/@nix
33-btrfs subvolume create /mnt/top/@nixos-log
34-umount /mnt/top
79+# The backup drive, read-only. Not under /mnt: disko unmounts everything there.
80+mkdir /backup
81+mount -o ro /dev/disk/by-label/backup /backup
82+sys=$(cat /backup/nix-cache/system)
83+disko=$(cat /backup/nix-cache/disko)
3584
36-# Mount the new system the way hosts/desktop/hardware-configuration.nix does.
37-o=noatime,compress=zstd
38-mount -o subvol=@nixos,$o /dev/nvme0n1p2 /mnt
39-mkdir -p /mnt/{nix,var/log,home,boot}
40-mount -o subvol=@nix,$o /dev/nvme0n1p2 /mnt/nix
41-mount -o subvol=@nixos-log,$o /dev/nvme0n1p2 /mnt/var/log
42-mount -o subvol=@home,$o /dev/nvme0n1p2 /mnt/home
43-mount /dev/nvme0n1p1 /mnt/boot
85+# The disko script. It doesn't ask before it wipes, so check that the drive it
86+# names is the 980 PRO (nvme0n1) one last time.
87+ls -l /dev/disk/by-id/nvme-Samsung_SSD_980_PRO_1TB_S5GXNF1R877751D
88+nix --extra-experimental-features nix-command copy --no-check-sigs --from file:///backup/nix-cache "$disko"
4489
45-# Compare the generated hardware config with the one in the repo; if the
46-# kernel modules or anything else differ, keep the generated lines.
47-nixos-generate-config --root /mnt --show-hardware-config > /tmp/hw.nix
48-diff /tmp/hw.nix /mnt/home/vizie/git/dot/hosts/desktop/hardware-configuration.nix
49-
50-# philly is a private repo: sign in to GitHub for this root shell.
51-nix --extra-experimental-features 'nix-command flakes' shell nixpkgs#gh -c gh auth login
52-git config --global credential.helper '!gh auth git-credential'
90+# Wipe, partition, format and mount the NVMe drive at /mnt.
91+"$disko"
5392
54-# Install. The extra cache is where the CachyOS kernel comes from.
55-nixos-install --flake /mnt/home/vizie/git/dot#desktop \
56- --option extra-substituters https://attic.xuyh0120.win/lantian \
57- --option extra-trusted-public-keys lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc=
93+# Copy the system onto it and install it, with the boot loader.
94+nix --extra-experimental-features nix-command copy --no-check-sigs \
95+ --from file:///backup/nix-cache --to 'local?root=/mnt' "$sys"
96+nixos-install --system "$sys" --no-channel-copy
97+# It asks for a root password at the end.
5898
59-# It asks for a root password at the end. Then set yours:
99+# Your home folder back, owned by you (uid 1000, group users).
100+rsync -aHAX --info=progress2 --chown=1000:100 /backup/vizie/ /mnt/home/vizie/
60101 nixos-enter --root /mnt -c 'passwd vizie'
61102 reboot
62103 ```
63104
64-The NixOS boot menu (systemd-boot) becomes the default. CachyOS's Limine stays
65-in the firmware boot menu (F8 at the ASUS logo), and also on the ESP, next to it.
105+If something in `/backup/nix-cache` is missing, install from the flake instead
106+(this needs the network, and compiles the kernel if its cache is down):
107+`nixos-install --flake /backup/vizie/git/dot#desktop` after
108+`nix run github:nix-community/disko/latest -- --mode destroy,format,mount /backup/vizie/git/dot/hosts/desktop/disko.nix`.
66109
67110 ## 3. First boot
68111
@@ -112,16 +155,30 @@
112155 - **sched-ext** schedulers stay off, as before. See the comment in
113156 `modules/nixos/cachyos.nix` to try one.
114157
115-## 5. Going back to CachyOS
158+## 5. Games
116159
117-It still boots (firmware boot menu). Its `~/.config` links now point into
118-NixOS's store, which CachyOS doesn't have, so rerun the old repo's script there:
119-`~/git/dotfiles/symlink.sh`.
160+- **Steam**: your settings, Proton versions and game saves (`compatdata`) are
161+ back. The games in `~/Games/SteamLibrary` and Steam's own library show as
162+ not installed; install them again. Steam may need the library folder
163+ re-added (Settings → Storage).
164+- **WoW**: in Faugus, remove the old Battle.net entry and add Battle.net again
165+ (Faugus installs it into a new prefix at `~/Games/battlenet`). Pick the same
166+ runner, `Proton-CachyOS Latest` (it's back in
167+ `~/.local/share/Steam/compatibilitytools.d`), and the same launch arguments:
168+ `WINE_SIMULATE_WRITECOPY=1` and `PROTON_ENABLE_WAYLAND=0`. Install WoW, then
169+ copy your settings and addons back before you start it:
170+
171+ ```bash
172+ sudo mount -o ro /dev/disk/by-label/backup /mnt
173+ cp -a /mnt/wow/{WTF,Interface} ~/Games/battlenet/drive_c/'Program Files (x86)'/'World of Warcraft'/_retail_/
174+ sudo umount /mnt
175+ ```
176+
177+- **OSRS**: Bolt installs itself again (see First boot); its data in
178+ `~/.var/app/com.adamcake.Bolt` came back with your home folder, so you
179+ stay signed in.
120180
121181 ## 6. Once you're happy
122182
123-Remove CachyOS: boot NixOS, mount the top level, delete its subvolumes
124-(`@`, `@root`, `@srv`, `@cache`, `@tmp`, `@log`), then its kernels and Limine
125-files from the ESP (look first: `sudo ls -R /boot`; NixOS's own files are
126-`/boot/EFI/nixos`, `/boot/EFI/systemd`, `/boot/EFI/BOOT` and `/boot/loader`),
127-and its firmware boot entry (`efibootmgr`).
183+The backup on `sda` stays until you need the drive for something else. NixOS
184+doesn't mount it; `sudo mount /dev/disk/by-label/backup /mnt` gets you into it.
modifiedREADME.md
@@ -6,13 +6,15 @@
66 the patched Waybar and the Eww control centre, the CachyOS kernel and the CachyOS
77 system tweaks.
88
9-Moving from CachyOS: see [MIGRATION.md]MIGRATION.md.
9+Moving from CachyOS: see [MIGRATION.md]MIGRATION.md. The install wipes the
10+NVMe drive and partitions it with [disko]https://github.com/nix-community/disko.
1011
1112 ## Layout
1213
1314 ```
1415 flake.nix inputs, the desktop system, the packages below
15-hosts/desktop/ this machine: hostname, disks, Home Manager
16+hosts/desktop/ this machine: hostname, Home Manager
17+ disko.nix the drive's partitions and btrfs subvolumes
1618 modules/nixos/
1719 base.nix Nix, boot, locale, network, firewall, user
1820 cachyos.nix CachyOS kernel + cachyos-settings, file by file
@@ -1,0 +1,19 @@
1+# rsync filter for backing up /home/vizie before the drive is wiped (see
2+# MIGRATION.md). Everything is kept except what downloads or rebuilds again.
3+
4+# Game installs: Battle.net and WoW are installed again (WoW's settings and
5+# addons are backed up separately), Steam games download again.
6+- /Games/
7+- /.local/share/Steam/steamapps/common/
8+- /.local/share/Steam/steamapps/shadercache/
9+- /.local/share/Steam/steamapps/downloading/
10+# Steam Linux Runtime for umu; it downloads itself again.
11+- /.local/share/umu/
12+
13+# Caches.
14+- /.cache/
15+- /.local/share/Trash/
16+# Claude Desktop's Cowork VM image, downloaded again when Cowork starts.
17+- /.config/Claude/vm_bundles/
18+# The test VM's disk.
19+- /git/dot/desktop.qcow2
modifiedflake.lock
@@ -1,5 +1,26 @@
11 {
22 "nodes": {
3+ "disko": {
4+ "inputs": {
5+ "nixpkgs": [
6+ "nixpkgs"
7+ ]
8+ },
9+ "locked": {
10+ "lastModified": 1768920986,
11+ "narHash": "sha256-CNzzBsRhq7gg4BMBuTDObiWDH/rFYHEuDRVOwCcwXw4=",
12+ "owner": "nix-community",
13+ "repo": "disko",
14+ "rev": "de5708739256238fb912c62f03988815db89ec9a",
15+ "type": "github"
16+ },
17+ "original": {
18+ "owner": "nix-community",
19+ "ref": "latest",
20+ "repo": "disko",
21+ "type": "github"
22+ }
23+ },
324 "flake-compat": {
425 "flake": false,
526 "locked": {
@@ -165,6 +186,7 @@
165186 },
166187 "root": {
167188 "inputs": {
189+ "disko": "disko",
168190 "home-manager": "home-manager",
169191 "imsh-clients": "imsh-clients",
170192 "nix-cachyos-kernel": "nix-cachyos-kernel",
modifiedflake.nix
@@ -9,6 +9,12 @@
99 inputs.nixpkgs.follows = "nixpkgs";
1010 };
1111
12+ # Partitions and formats the drive at install time (hosts/desktop/disko.nix).
13+ disko = {
14+ url = "github:nix-community/disko/latest";
15+ inputs.nixpkgs.follows = "nixpkgs";
16+ };
17+
1218 # CachyOS kernels, built by the maintainer's CI. Its nixpkgs input is left
1319 # alone on purpose: overriding it changes the kernel's hash, so nothing comes
1420 # from the binary cache and the kernel compiles locally.
@@ -3,6 +3,8 @@
33 {
44 imports = [
55 ./hardware-configuration.nix
6+ ./disko.nix
7+ inputs.disko.nixosModules.disko
68 ../../modules/nixos
79 inputs.home-manager.nixosModules.home-manager
810 ];
@@ -1,0 +1,58 @@
1+# The NVMe drive, as disko partitions and formats it at install time (see
2+# MIGRATION.md). Running disko on it erases everything on the drive. The two
3+# SATA drives (sda, sdb) aren't listed, so disko never touches them.
4+#
5+# Same shape as CachyOS had it: an EFI partition for systemd-boot and one btrfs
6+# partition with subvolumes, compressed with zstd. Swap is zram (base.nix).
7+let
8+ mountOptions = [
9+ "noatime"
10+ "compress=zstd"
11+ ];
12+in
13+{
14+ disko.devices.disk.main = {
15+ type = "disk";
16+ device = "/dev/disk/by-id/nvme-Samsung_SSD_980_PRO_1TB_S5GXNF1R877751D";
17+ content = {
18+ type = "gpt";
19+ partitions = {
20+ ESP = {
21+ size = "2G";
22+ type = "EF00";
23+ content = {
24+ type = "filesystem";
25+ format = "vfat";
26+ mountpoint = "/boot";
27+ mountOptions = [ "umask=0077" ];
28+ };
29+ };
30+ root = {
31+ size = "100%";
32+ content = {
33+ type = "btrfs";
34+ extraArgs = [ "-f" ];
35+ subvolumes = {
36+ "@" = {
37+ mountpoint = "/";
38+ inherit mountOptions;
39+ };
40+ "@home" = {
41+ mountpoint = "/home";
42+ inherit mountOptions;
43+ };
44+ "@nix" = {
45+ mountpoint = "/nix";
46+ inherit mountOptions;
47+ };
48+ "@log" = {
49+ mountpoint = "/var/log";
50+ inherit mountOptions;
51+ };
52+ };
53+ };
54+ };
55+ };
56+ };
57+ };
58+}
@@ -3,24 +3,14 @@
33 # nixos-generate-config --show-hardware-config --root /mnt
44 # and keep the generated one if they differ.
55 #
6-# Disk layout: the existing btrfs partition is kept. NixOS gets subvolumes of
7-# its own (@nixos for /, @nix for /nix, @nixos-log for /var/log) next to
8-# CachyOS's, and /home is CachyOS's @home, so your files stay where they are.
9-# See MIGRATION.md.
6+# The file systems aren't here: disko.nix defines the drive's layout, and
7+# disko turns it into fileSystems entries.
108 {
119 config,
1210 lib,
1311 modulesPath,
1412 ...
1513 }:
16-let
17- btrfs = "/dev/disk/by-uuid/6e57f546-3dd3-43f6-9d1b-1c57f3b489ad";
18- subvol = name: [
19- "subvol=${name}"
20- "noatime"
21- "compress=zstd"
22- ];
23-in
2414 {
2515 imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
2616
@@ -33,36 +23,6 @@
3323 "sd_mod"
3424 ];
3525 boot.kernelModules = [ "kvm-amd" ];
36-
37- fileSystems."/" = {
38- device = btrfs;
39- fsType = "btrfs";
40- options = subvol "@nixos";
41- };
42- fileSystems."/nix" = {
43- device = btrfs;
44- fsType = "btrfs";
45- options = subvol "@nix";
46- };
47- fileSystems."/var/log" = {
48- device = btrfs;
49- fsType = "btrfs";
50- options = subvol "@nixos-log";
51- neededForBoot = true;
52- };
53- fileSystems."/home" = {
54- device = btrfs;
55- fsType = "btrfs";
56- options = subvol "@home";
57- };
58- fileSystems."/boot" = {
59- device = "/dev/disk/by-uuid/DDCE-5209";
60- fsType = "vfat";
61- options = [
62- "fmask=0077"
63- "dmask=0077"
64- ];
65- };
6626
6727 # The second drive (sdb, ext4) was commented out in CachyOS's fstab too.
6828 # fileSystems."/home/vizie/Games" = {
@@ -87,6 +87,9 @@
8787
8888 users.users.vizie = {
8989 isNormalUser = true;
90+ # The same uid as on CachyOS, so the home folder restored from the backup
91+ # (MIGRATION.md) belongs to you.
92+ uid = 1000;
9093 description = "Gustaf Granström";
9194 shell = pkgs.zsh;
9295 extraGroups = [