dot

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

256 lines9433 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. Its binary
53 # cache isn't used, so the kernel compiles locally.
54 nixpkgs.overlays = [ inputs.nix-cachyos-kernel.overlays.pinned ];
55
56 # Same build as linux-cachyos on CachyOS's znver4 repo: EEVDF scheduler,
57 # 1000 Hz, full preemption, Clang ThinLTO, tuned for Zen 4 (also right for
58 # this Zen 5 CPU, as on CachyOS).
59 boot.kernelPackages = pkgs.cachyosKernels.linuxPackages-cachyos-latest-lto-zen4;
60
61 boot.kernelParams = [
62 "nowatchdog"
63 # cachyos-settings: udev/rules.d/30-zram.rules turns zswap off once zram is
64 # up; it is always up here, so it is simply off from boot.
65 "zswap.enabled=0"
66 ];
67
68 # modprobe.d/blacklist.conf
69 boot.blacklistedKernelModules = [
70 "iTCO_wdt"
71 "sp5100_tco"
72 ];
73
74 # modules-load.d/ntsync.conf: Wine/Proton's NT synchronization primitives.
75 boot.kernelModules = [ "ntsync" ];
76
77 boot.extraModprobeConfig = ''
78 # modprobe.d/nvidia.conf
79 options nvidia NVreg_InitializeSystemMemoryAllocations=0
80 # cachyos-iw-set-regdomain: the Wi-Fi regulatory domain, from the time zone.
81 options cfg80211 ieee80211_regdom="NO"
82 '';
83
84 # --- sysctl.d/70-cachyos-settings.conf --------------------------------------
85
86 boot.kernel.sysctl = {
87 # 150 rather than the file's 100: 30-zram.rules raises it to 150 as soon as
88 # zram is active, which on CachyOS is always.
89 "vm.swappiness" = 150;
90 "vm.vfs_cache_pressure" = 50;
91 "vm.dirty_bytes" = 268435456;
92 "vm.page-cluster" = 0;
93 "vm.dirty_background_bytes" = 67108864;
94 "vm.dirty_writeback_centisecs" = 1500;
95 "kernel.nmi_watchdog" = 0;
96 "kernel.unprivileged_userns_clone" = 1;
97 "kernel.printk" = "3 3 3 3";
98 "kernel.kptr_restrict" = 2;
99 "net.core.netdev_max_backlog" = 4096;
100 "fs.file-max" = 2097152;
101 };
102
103 # --- udev rules ---------------------------------------------------------------
104
105 services.udev.extraRules = ''
106 # 60-ioschedulers.rules
107 ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
108 ACTION=="add|change", KERNEL=="sd[a-z]*|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
109 ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="kyber"
110
111 # 40-hpet-permissions.rules, 99-cpu-dma-latency.rules
112 KERNEL=="rtc0", GROUP="audio"
113 KERNEL=="hpet", GROUP="audio"
114 DEVPATH=="/devices/virtual/misc/cpu_dma_latency", OWNER="root", GROUP="audio", MODE="0660"
115
116 # 50-sata.rules
117 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"
118
119 # 71-nvidia.rules: runtime power management for the NVIDIA GPU.
120 ACTION=="add|bind", SUBSYSTEM=="pci", DRIVERS=="nvidia", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", TEST=="power/control", ATTR{power/control}="auto"
121 ACTION=="remove|unbind", SUBSYSTEM=="pci", DRIVERS=="nvidia", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", TEST=="power/control", ATTR{power/control}="on"
122 '';
123
124 # --- tmpfiles.d ---------------------------------------------------------------
125
126 systemd.tmpfiles.rules = [
127 # thp.conf, thp-shrinker.conf
128 "w! /sys/kernel/mm/transparent_hugepage/defrag - - - - defer+madvise"
129 "w! /sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_none - - - - 409"
130 # coredump.conf
131 "e /var/lib/systemd/coredump - - - 3d"
132 ];
133
134 # --- systemd ------------------------------------------------------------------
135
136 # system.conf.d/00-timeout.conf, 10-limits.conf
137 systemd.settings.Manager = {
138 DefaultTimeoutStartSec = "15s";
139 DefaultTimeoutStopSec = "10s";
140 DefaultLimitNOFILE = "2048:2097152";
141 };
142 # user.conf.d/00-timeout.conf, 10-limits.conf
143 systemd.user.settings.Manager = {
144 DefaultTimeoutStartSec = "15s";
145 DefaultTimeoutStopSec = "10s";
146 DefaultLimitNOFILE = "1024:1048576";
147 };
148
149 # journald.conf.d/00-journal-size.conf
150 services.journald.settings.Journal.SystemMaxUse = "50M";
151
152 # timesyncd.conf.d/10-timesyncd.conf
153 services.timesyncd = {
154 servers = [ "time.cloudflare.com" ];
155 fallbackServers = [
156 "time.google.com"
157 "0.nixos.pool.ntp.org"
158 "1.nixos.pool.ntp.org"
159 ];
160 };
161
162 # system/user@.service.d/delegate.conf: lets user services (and ananicy)
163 # manage their own CPU, I/O and memory controllers.
164 systemd.services."user@".serviceConfig.Delegate = "cpu cpuset io memory pids";
165
166 # system/rtkit-daemon.service.d/override.conf
167 security.rtkit.enable = true;
168 systemd.services.rtkit-daemon.serviceConfig.LogLevelMax = "info";
169
170 # systemd-oomd per-slice defaults (system.slice.d, user-.slice.d,
171 # session.slice.d).
172 systemd.oomd.enable = true;
173 systemd.slices = {
174 "system".sliceConfig = {
175 ManagedOOMSwap = "kill";
176 ManagedOOMMemoryPressure = "kill";
177 ManagedOOMMemoryPressureLimit = "80%";
178 };
179 "user-".sliceConfig = {
180 ManagedOOMSwap = "kill";
181 ManagedOOMMemoryPressure = "kill";
182 ManagedOOMMemoryPressureLimit = "80%";
183 };
184 };
185 systemd.user.slices.session.sliceConfig.ManagedOOMPreference = "omit";
186
187 # system/pci-latency.service + /usr/bin/pci-latency
188 systemd.services.pci-latency = {
189 description = "Adjust latency timers for PCI peripherals";
190 wantedBy = [ "multi-user.target" ];
191 serviceConfig.Type = "oneshot";
192 path = [ pkgs.pciutils ];
193 script = ''
194 setpci -v -s '*:*' latency_timer=20
195 setpci -v -s '0:0' latency_timer=0
196 setpci -v -d "*:*:04xx" latency_timer=80
197 '';
198 };
199
200 # security/limits.d/20-audio.conf
201 security.pam.loginLimits = [
202 {
203 domain = "@audio";
204 item = "rtprio";
205 type = "-";
206 value = "99";
207 }
208 {
209 domain = "@audio";
210 item = "nice";
211 type = "-";
212 value = "-11";
213 }
214 ];
215
216 hardware.wirelessRegulatoryDatabase = true;
217
218 # --- CachyOS services ---------------------------------------------------------
219
220 # ananicy-cpp with CachyOS's rules: renices games, compilers, browsers etc.
221 services.ananicy = {
222 enable = true;
223 package = pkgs.ananicy-cpp;
224 rulesProvider = pkgs.ananicy-rules-cachyos;
225 };
226
227 # bpftune: auto-tunes network and other kernel settings (enabled on CachyOS).
228 services.bpftune.enable = true;
229
230 # sched-ext schedulers, as CachyOS's scx-scheds. Off there too (scx_loader was
231 # disabled); to try one:
232 # services.scx = { enable = true; scheduler = "scx_lavd"; };
233
234 # power-profiles-daemon, with the profile you had set on CachyOS.
235 services.power-profiles-daemon.enable = true;
236 # Started with the daemon itself (wanting it from multi-user.target makes an
237 # ordering cycle). Skipped where there is no performance profile, e.g. in a VM.
238 systemd.services.power-profile-performance = {
239 description = "Select the performance power profile";
240 after = [ "power-profiles-daemon.service" ];
241 bindsTo = [ "power-profiles-daemon.service" ];
242 wantedBy = [ "power-profiles-daemon.service" ];
243 serviceConfig.Type = "oneshot";
244 path = [ pkgs.power-profiles-daemon ];
245 script = ''
246 if powerprofilesctl list | grep -q 'performance:'; then
247 powerprofilesctl set performance
248 fi
249 '';
250 };
251
252 environment.systemPackages = [
253 game-performance
254 dlss-swapper
255 ];
256}