dot

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

264 lines9785 bytesNix
1# What CachyOS adds on top of plain Arch: its kernel and the cachyos-settings
2# package (sysctl, udev rules, systemd defaults), ported file by file. The CachyOS
3# file each part comes from is named next to it, so they can be compared when
4# CachyOS changes something.
5#
6# Not ported, because it does nothing on this machine: the laptop audio power
7# saving and touchpad rules, the old-Radeon (SI/CIK) amdgpu options, and
8# debuginfod. Snapper root snapshots are replaced by NixOS generations: every
9# rebuild is a boot menu entry you can go back to.
10{
11 inputs,
12 lib,
13 pkgs,
14 ...
15}:
16let
17 # cachyos-settings: /usr/bin/game-performance. Runs a game with the
18 # "performance" power profile held, and the screensaver inhibited. Use it as
19 # a Steam launch option: game-performance %command%
20 game-performance = pkgs.writeShellApplication {
21 name = "game-performance";
22 runtimeInputs = [ pkgs.power-profiles-daemon pkgs.systemd ];
23 text = ''
24 if ! powerprofilesctl list | grep -q 'performance:'; then
25 exec "$@"
26 fi
27 if [ -n "''${GAME_PERFORMANCE_SCREENSAVER_ON:-}" ]; then
28 exec powerprofilesctl launch -p performance \
29 -r "Launched with CachyOS game-performance utility" -- "$@"
30 else
31 exec systemd-inhibit --why "CachyOS game-performance is running" powerprofilesctl launch \
32 -p performance -r "Launched with CachyOS game-performance utility" -- "$@"
33 fi
34 '';
35 };
36
37 # cachyos-settings: /usr/bin/dlss-swapper. Steam launch option:
38 # dlss-swapper %command%
39 dlss-swapper = pkgs.writeShellScriptBin "dlss-swapper" ''
40 export PROTON_ENABLE_NGX_UPDATER=1
41 export DXVK_NVAPI_DRS_NGX_DLSS_RR_OVERRIDE=on
42 export DXVK_NVAPI_DRS_NGX_DLSS_SR_OVERRIDE=on
43 export DXVK_NVAPI_DRS_NGX_DLSS_FG_OVERRIDE=on
44 export DXVK_NVAPI_DRS_NGX_DLSS_RR_OVERRIDE_RENDER_PRESET_SELECTION=render_preset_latest
45 export DXVK_NVAPI_DRS_NGX_DLSS_SR_OVERRIDE_RENDER_PRESET_SELECTION=render_preset_latest
46 exec "$@"
47 '';
48in
49{
50 # --- Kernel ----------------------------------------------------------------
51
52 # The overlay pins the kernel to the nixpkgs it was built with, so the build
53 # doesn't change with this system's nixpkgs.
54 nixpkgs.overlays = [ inputs.nix-cachyos-kernel.overlays.pinned ];
55
56 # git.granstrm.com builds the kernel, its modules and the NVIDIA driver every
57 # night the kernel changes (flake.nix's `ci`), and serves them from its
58 # binary cache.
59 nix.settings = {
60 substituters = [ "https://cache.git.granstrm.com" ];
61 trusted-public-keys = [ "cache.git.granstrm.com-1:Y6BjEJMQZ02kt2oOJ/99RU+NTDZDsBY8tqIiypq1ong=" ];
62 };
63
64 # Same build as linux-cachyos on CachyOS's znver4 repo: EEVDF scheduler,
65 # 1000 Hz, full preemption, Clang ThinLTO, tuned for Zen 4 (also right for
66 # this Zen 5 CPU, as on CachyOS).
67 boot.kernelPackages = pkgs.cachyosKernels.linuxPackages-cachyos-latest-lto-zen4;
68
69 boot.kernelParams = [
70 "nowatchdog"
71 # cachyos-settings: udev/rules.d/30-zram.rules turns zswap off once zram is
72 # up; it is always up here, so it is simply off from boot.
73 "zswap.enabled=0"
74 ];
75
76 # modprobe.d/blacklist.conf
77 boot.blacklistedKernelModules = [
78 "iTCO_wdt"
79 "sp5100_tco"
80 ];
81
82 # modules-load.d/ntsync.conf: Wine/Proton's NT synchronization primitives.
83 boot.kernelModules = [ "ntsync" ];
84
85 boot.extraModprobeConfig = ''
86 # modprobe.d/nvidia.conf
87 options nvidia NVreg_InitializeSystemMemoryAllocations=0
88 # cachyos-iw-set-regdomain: the Wi-Fi regulatory domain, from the time zone.
89 options cfg80211 ieee80211_regdom="NO"
90 '';
91
92 # --- sysctl.d/70-cachyos-settings.conf --------------------------------------
93
94 boot.kernel.sysctl = {
95 # 150 rather than the file's 100: 30-zram.rules raises it to 150 as soon as
96 # zram is active, which on CachyOS is always.
97 "vm.swappiness" = 150;
98 "vm.vfs_cache_pressure" = 50;
99 "vm.dirty_bytes" = 268435456;
100 "vm.page-cluster" = 0;
101 "vm.dirty_background_bytes" = 67108864;
102 "vm.dirty_writeback_centisecs" = 1500;
103 "kernel.nmi_watchdog" = 0;
104 "kernel.unprivileged_userns_clone" = 1;
105 "kernel.printk" = "3 3 3 3";
106 "kernel.kptr_restrict" = 2;
107 "net.core.netdev_max_backlog" = 4096;
108 "fs.file-max" = 2097152;
109 };
110
111 # --- udev rules ---------------------------------------------------------------
112
113 services.udev.extraRules = ''
114 # 60-ioschedulers.rules
115 ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
116 ACTION=="add|change", KERNEL=="sd[a-z]*|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
117 ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="kyber"
118
119 # 40-hpet-permissions.rules, 99-cpu-dma-latency.rules
120 KERNEL=="rtc0", GROUP="audio"
121 KERNEL=="hpet", GROUP="audio"
122 DEVPATH=="/devices/virtual/misc/cpu_dma_latency", OWNER="root", GROUP="audio", MODE="0660"
123
124 # 50-sata.rules
125 ACTION=="add", SUBSYSTEM=="scsi_host", KERNEL=="host*", ATTR{link_power_management_supported}=="1", ATTR{link_power_management_policy}=="*", ATTR{link_power_management_policy}="max_performance"
126
127 # 71-nvidia.rules: runtime power management for the NVIDIA GPU.
128 ACTION=="add|bind", SUBSYSTEM=="pci", DRIVERS=="nvidia", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", TEST=="power/control", ATTR{power/control}="auto"
129 ACTION=="remove|unbind", SUBSYSTEM=="pci", DRIVERS=="nvidia", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", TEST=="power/control", ATTR{power/control}="on"
130 '';
131
132 # --- tmpfiles.d ---------------------------------------------------------------
133
134 systemd.tmpfiles.rules = [
135 # thp.conf, thp-shrinker.conf
136 "w! /sys/kernel/mm/transparent_hugepage/defrag - - - - defer+madvise"
137 "w! /sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_none - - - - 409"
138 # coredump.conf
139 "e /var/lib/systemd/coredump - - - 3d"
140 ];
141
142 # --- systemd ------------------------------------------------------------------
143
144 # system.conf.d/00-timeout.conf, 10-limits.conf
145 systemd.settings.Manager = {
146 DefaultTimeoutStartSec = "15s";
147 DefaultTimeoutStopSec = "10s";
148 DefaultLimitNOFILE = "2048:2097152";
149 };
150 # user.conf.d/00-timeout.conf, 10-limits.conf
151 systemd.user.settings.Manager = {
152 DefaultTimeoutStartSec = "15s";
153 DefaultTimeoutStopSec = "10s";
154 DefaultLimitNOFILE = "1024:1048576";
155 };
156
157 # journald.conf.d/00-journal-size.conf
158 services.journald.settings.Journal.SystemMaxUse = "50M";
159
160 # timesyncd.conf.d/10-timesyncd.conf
161 services.timesyncd = {
162 servers = [ "time.cloudflare.com" ];
163 fallbackServers = [
164 "time.google.com"
165 "0.nixos.pool.ntp.org"
166 "1.nixos.pool.ntp.org"
167 ];
168 };
169
170 # system/user@.service.d/delegate.conf: lets user services (and ananicy)
171 # manage their own CPU, I/O and memory controllers.
172 systemd.services."user@".serviceConfig.Delegate = "cpu cpuset io memory pids";
173
174 # system/rtkit-daemon.service.d/override.conf
175 security.rtkit.enable = true;
176 systemd.services.rtkit-daemon.serviceConfig.LogLevelMax = "info";
177
178 # systemd-oomd per-slice defaults (system.slice.d, user-.slice.d,
179 # session.slice.d).
180 systemd.oomd.enable = true;
181 systemd.slices = {
182 "system".sliceConfig = {
183 ManagedOOMSwap = "kill";
184 ManagedOOMMemoryPressure = "kill";
185 ManagedOOMMemoryPressureLimit = "80%";
186 };
187 "user-".sliceConfig = {
188 ManagedOOMSwap = "kill";
189 ManagedOOMMemoryPressure = "kill";
190 ManagedOOMMemoryPressureLimit = "80%";
191 };
192 };
193 systemd.user.slices.session.sliceConfig.ManagedOOMPreference = "omit";
194
195 # system/pci-latency.service + /usr/bin/pci-latency
196 systemd.services.pci-latency = {
197 description = "Adjust latency timers for PCI peripherals";
198 wantedBy = [ "multi-user.target" ];
199 serviceConfig.Type = "oneshot";
200 path = [ pkgs.pciutils ];
201 script = ''
202 setpci -v -s '*:*' latency_timer=20
203 setpci -v -s '0:0' latency_timer=0
204 setpci -v -d "*:*:04xx" latency_timer=80
205 '';
206 };
207
208 # security/limits.d/20-audio.conf
209 security.pam.loginLimits = [
210 {
211 domain = "@audio";
212 item = "rtprio";
213 type = "-";
214 value = "99";
215 }
216 {
217 domain = "@audio";
218 item = "nice";
219 type = "-";
220 value = "-11";
221 }
222 ];
223
224 hardware.wirelessRegulatoryDatabase = true;
225
226 # --- CachyOS services ---------------------------------------------------------
227
228 # ananicy-cpp with CachyOS's rules: renices games, compilers, browsers etc.
229 services.ananicy = {
230 enable = true;
231 package = pkgs.ananicy-cpp;
232 rulesProvider = pkgs.ananicy-rules-cachyos;
233 };
234
235 # bpftune: auto-tunes network and other kernel settings (enabled on CachyOS).
236 services.bpftune.enable = true;
237
238 # sched-ext schedulers, as CachyOS's scx-scheds. Off there too (scx_loader was
239 # disabled); to try one:
240 # services.scx = { enable = true; scheduler = "scx_lavd"; };
241
242 # power-profiles-daemon, with the profile you had set on CachyOS.
243 services.power-profiles-daemon.enable = true;
244 # Started with the daemon itself (wanting it from multi-user.target makes an
245 # ordering cycle). Skipped where there is no performance profile, e.g. in a VM.
246 systemd.services.power-profile-performance = {
247 description = "Select the performance power profile";
248 after = [ "power-profiles-daemon.service" ];
249 bindsTo = [ "power-profiles-daemon.service" ];
250 wantedBy = [ "power-profiles-daemon.service" ];
251 serviceConfig.Type = "oneshot";
252 path = [ pkgs.power-profiles-daemon ];
253 script = ''
254 if powerprofilesctl list | grep -q 'performance:'; then
255 powerprofilesctl set performance
256 fi
257 '';
258 };
259
260 environment.systemPackages = [
261 game-performance
262 dlss-swapper
263 ];
264}