dot
vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks
1415676
- cache kernel
- cache kernel-modules
- cache nvidia NVIDIA driver
- effect update-kernel Commits the latest CachyOS kernel
9 files changed +214 −37
modifiedREADME.md
@@ -43,6 +43,11 @@ | ||
| 43 | 43 | |
| 44 | 44 | |
| 45 | 45 | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 46 | 51 | |
| 47 | 52 | |
| 48 | 53 | |
@@ -96,6 +101,8 @@ | ||
| 96 | 101 | - |
| 97 | 102 | |
| 98 | 103 | |
| 104 | + | |
| 105 | + | |
| 99 | 106 | - |
| 100 | 107 | |
| 101 | 108 | - |
modifiedflake.lock
@@ -42,11 +42,11 @@ | ||
| 42 | 42 | "nixpkgs-lib": "nixpkgs-lib" |
| 43 | 43 | }, |
| 44 | 44 | "locked": |
| 45 | - | |
| 46 | - | |
| 45 | + | |
| 46 | + | |
| 47 | 47 | |
| 48 | 48 | |
| 49 | - | |
| 49 | + | |
| 50 | 50 | |
| 51 | 51 | , |
| 52 | 52 | "original": |
@@ -102,27 +102,26 @@ | ||
| 102 | 102 | "nixpkgs": "nixpkgs" |
| 103 | 103 | }, |
| 104 | 104 | "locked": |
| 105 | - | |
| 106 | - | |
| 105 | + | |
| 106 | + | |
| 107 | 107 | |
| 108 | 108 | |
| 109 | - | |
| 109 | + | |
| 110 | 110 | |
| 111 | 111 | , |
| 112 | 112 | "original": |
| 113 | 113 | |
| 114 | - | |
| 115 | 114 | |
| 116 | 115 | |
| 117 | 116 | |
| 118 | 117 | }, |
| 119 | 118 | "nixpkgs": |
| 120 | 119 | |
| 121 | - | |
| 122 | - | |
| 120 | + | |
| 121 | + | |
| 123 | 122 | |
| 124 | 123 | |
| 125 | - | |
| 124 | + | |
| 126 | 125 | |
| 127 | 126 | |
| 128 | 127 | |
@@ -134,11 +133,11 @@ | ||
| 134 | 133 | }, |
| 135 | 134 | "nixpkgs-lib": |
| 136 | 135 | |
| 137 | - | |
| 138 | - | |
| 136 | + | |
| 137 | + | |
| 139 | 138 | |
| 140 | 139 | |
| 141 | - | |
| 140 | + | |
| 142 | 141 | |
| 143 | 142 | |
| 144 | 143 | |
modifiedflake.nix
@@ -20,10 +20,13 @@ | ||
| 20 | 20 | inputs.nixpkgs.follows = "nixpkgs"; |
| 21 | 21 | }; |
| 22 | 22 | |
| 23 | - # CachyOS kernels. Its nixpkgs input is left alone on purpose: the kernel | |
| 24 | - # stays the exact build upstream tests (it compiles locally, as its binary | |
| 25 | - # cache isn't used). | |
| 26 | - nix-cachyos-kernel.url = "github:xddxdd/nix-cachyos-kernel/release"; | |
| 23 | + # CachyOS kernels, from master: upstream updates it every day with what | |
| 24 | + # CachyOS releases (its release branch only moves once upstream's own CI | |
| 25 | + # has built it, which can lag for weeks). Its nixpkgs input is left alone | |
| 26 | + # on purpose, so the kernel is the build upstream defines. git.granstrm.com | |
| 27 | + # updates it every night and builds the kernel into its binary cache (`ci` | |
| 28 | + # below); the Desktop update leaves it alone (tools/nixos-update). | |
| 29 | + nix-cachyos-kernel.url = "github:xddxdd/nix-cachyos-kernel"; | |
| 27 | 30 | |
| 28 | 31 | imsh-clients = { |
| 29 | 32 | url = "github:echozio/imsh-clients"; |
@@ -90,5 +93,71 @@ | ||
| 90 | 93 | ); |
| 91 | 94 | |
| 92 | 95 | formatter. = pkgs.nixfmt; |
| 96 | + | |
| 97 | + # CI on git.granstrm.com (gt, set up in ~/git/srv: modules/nixos/gt). On | |
| 98 | + # main, every night: tools/update-kernel commits the latest CachyOS kernel, | |
| 99 | + # gt fast-forwards main to it, and CI on that commit builds the kernel, its | |
| 100 | + # modules (nvidia-open among them) and the NVIDIA driver into the public | |
| 101 | + # binary cache, https://cache.git.granstrm.com, which cachyos.nix | |
| 102 | + # substitutes from. | |
| 103 | + ci = | |
| 104 | + { ref, ... }: | |
| 105 | + let | |
| 106 | + desktop = self.nixosConfigurations.desktop.config; | |
| 107 | + nvidia = desktop.hardware.nvidia.package; | |
| 108 | + in | |
| 109 | + nixpkgs.lib.optionalAttrs (ref == "refs/heads/main") { | |
| 110 | + caches = { | |
| 111 | + kernel = { | |
| 112 | + path = desktop.boot.kernelPackages.kernel; | |
| 113 | + label = "CachyOS kernel"; | |
| 114 | + public = true; | |
| 115 | + }; | |
| 116 | + kernel-modules = { | |
| 117 | + path = desktop.system.modulesTree; | |
| 118 | + label = "Kernel modules"; | |
| 119 | + public = true; | |
| 120 | + }; | |
| 121 | + # Built against the kernel, so new with it too. Unfree, but NVIDIA | |
| 122 | + # lets it be redistributed. | |
| 123 | + nvidia = { | |
| 124 | + path = pkgs.linkFarm "nvidia-driver" ( | |
| 125 | + map (output: { | |
| 126 | + name = output; | |
| 127 | + path = nvidia.; | |
| 128 | + }) nvidia.outputs | |
| 129 | + ++ [ | |
| 130 | + { | |
| 131 | + name = "settings"; | |
| 132 | + path = nvidia.settings; | |
| 133 | + } | |
| 134 | + ] | |
| 135 | + ); | |
| 136 | + label = "NVIDIA driver"; | |
| 137 | + public = true; | |
| 138 | + }; | |
| 139 | + }; | |
| 140 | + | |
| 141 | + effects.update-kernel = { | |
| 142 | + drv = pkgs.writeShellApplication { | |
| 143 | + name = "update-kernel"; | |
| 144 | + runtimeInputs = with pkgs; [ | |
| 145 | + nix | |
| 146 | + git | |
| 147 | + jq | |
| 148 | + coreutils | |
| 149 | + ]; | |
| 150 | + text = builtins.readFile ./tools/update-kernel; | |
| 151 | + }; | |
| 152 | + description = "Commits the latest CachyOS kernel"; | |
| 153 | + fastForward = true; | |
| 154 | + on.schedule = [ | |
| 155 | + { | |
| 156 | + cron = "0 2 * * *"; | |
| 157 | + tz = "Europe/Oslo"; | |
| 158 | + } | |
| 159 | + ]; | |
| 160 | + }; | |
| 161 | + }; | |
| 93 | 162 | }; |
| 94 | 163 | } |
modifiedmodules/home/packages.nix
@@ -13,6 +13,7 @@ | ||
| 13 | 13 | name = "nixos-update"; |
| 14 | 14 | runtimeInputs = with pkgs; [ |
| 15 | 15 | git |
| 16 | + jq | |
| 16 | 17 | nvd |
| 17 | 18 | ]; |
| 18 | 19 | runtimeEnv.DOT_REPO = config.dot.repoPath; |
modifiedmodules/home/shell.nix
@@ -57,8 +57,9 @@ | ||
| 57 | 57 | |
| 58 | 58 | # The pacman ones, for NixOS. Built as you, with sudo only for the switch: |
| 59 | 59 | # Nix won't read a git checkout owned by someone else, so a root build |
| 60 | - # of this one fails. | |
| 61 | - update = "nix flake update --flake && nixos-rebuild switch --sudo --flake "; | |
| 60 | + # of this one fails. update, like the control centre's (tools/nixos-update), | |
| 61 | + # takes the kernel git.granstrm.com built (git pull) and updates the rest. | |
| 62 | + update = "git -C pull --ff-only && nix flake update --flake $( -r '.nodes.root.inputs | keys[] | select(. != \"nix-cachyos-kernel\")' /flake.lock) && nixos-rebuild switch --sudo --flake "; | |
| 62 | 63 | rebuild = "nixos-rebuild switch --sudo --flake "; |
| 63 | 64 | cleanup = "sudo nix-collect-garbage --delete-older-than 14d"; |
| 64 | 65 | }; |
modifiedmodules/nixos/cachyos.nix
@@ -49,10 +49,18 @@ | ||
| 49 | 49 | { |
| 50 | 50 | # --- Kernel ---------------------------------------------------------------- |
| 51 | 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. | |
| 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 | 54 | nixpkgs.overlays = [ inputs.nix-cachyos-kernel.overlays.pinned ]; |
| 55 | 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 | + | |
| 56 | 64 | # Same build as linux-cachyos on CachyOS's znver4 repo: EEVDF scheduler, |
| 57 | 65 | # 1000 Hz, full preemption, Clang ThinLTO, tuned for Zen 4 (also right for |
| 58 | 66 | # this Zen 5 CPU, as on CachyOS). |
modifiedtools/nixos-update
@@ -4,8 +4,10 @@ | ||
| 4 | 4 | # control centre's update tile in a kitty window (installed as `nixos-update`, |
| 5 | 5 | # modules/home/packages.nix, which sets DOT_REPO). |
| 6 | 6 | # |
| 7 | -# 1. a temporary worktree of main | |
| 8 | -# 2. nix flake update, committed there | |
| 7 | +# 1. a temporary worktree of main, with the commits git.granstrm.com made since | |
| 8 | +# (the nightly CachyOS kernel, flake.nix's `ci`) | |
| 9 | +# 2. nix flake update of every input but the kernel's, committed there: the kernel | |
| 10 | +# is the one git.granstrm.com built, and comes from its binary cache | |
| 9 | 11 | # 3. nixos-rebuild build, then nvd's list of what changed against the running system |
| 10 | 12 | # 4. asks before going on; then pushes the commit, installs it as the next boot |
| 11 | 13 | # entry (nixos-rebuild boot), brings your checkout's main up to date and reboots |
@@ -42,35 +44,59 @@ | ||
| 42 | 44 | step "Fetching $repo" |
| 43 | 45 | git -C "$repo" worktree prune |
| 44 | 46 | git -C "$repo" fetch origin main |
| 45 | -git -C "$repo" merge-base --is-ancestor origin/main main || | |
| 46 | - die "main in $repo is behind origin/main (or has diverged); pull first." | |
| 47 | -base=$(git -C "$repo" rev-parse main) | |
| 47 | +main=$(git -C "$repo" rev-parse main) | |
| 48 | +# git.granstrm.com's own commits (the kernel) are taken as they are; your own on | |
| 49 | +# main that it doesn't have yet are pushed with the update. | |
| 50 | +if git -C "$repo" merge-base --is-ancestor main origin/main; then | |
| 51 | + base=$(git -C "$repo" rev-parse origin/main) | |
| 52 | +elif git -C "$repo" merge-base --is-ancestor origin/main main; then | |
| 53 | + base=$main | |
| 54 | +else | |
| 55 | + die "main in $repo and origin/main have diverged; rebase main first." | |
| 56 | +fi | |
| 48 | 57 | ahead=$(git -C "$repo" rev-list --count origin/main..main) |
| 49 | 58 | dirty=$(git -C "$repo" status --porcelain) |
| 50 | 59 | |
| 51 | 60 | tmp=$(mktemp -d -t dot-update.XXXXXX) |
| 52 | 61 | step "Creating a worktree of main in $tmp" |
| 53 | -git -C "$repo" worktree add --detach "$tmp" main | |
| 62 | +git -C "$repo" worktree add --detach "$tmp" "$base" | |
| 54 | 63 | cd "$tmp" || die "Could not enter $tmp." |
| 55 | 64 | |
| 56 | -step "Updating flake inputs" | |
| 57 | -nix flake update --commit-lock-file | |
| 58 | -if [ "$(git rev-parse HEAD)" = "$base" ]; then | |
| 65 | +step "Updating flake inputs (all but the kernel's)" | |
| 66 | +mapfile -t inputs < <(jq -r '.nodes.root.inputs | keys[] | select(. != "nix-cachyos-kernel")' flake.lock) | |
| 67 | +nix flake update --commit-lock-file "${inputs[@]}" | |
| 68 | + | |
| 69 | +kernel=$(nix eval --raw "$tmp#nixosConfigurations.desktop.config.boot.kernelPackages.kernel") | |
| 70 | +if ! nix path-info "$kernel" >/dev/null 2>&1 && | |
| 71 | + ! nix path-info --store https://cache.git.granstrm.com "$kernel" >/dev/null 2>&1; then | |
| 72 | + note "The kernel isn't in git.granstrm.com's cache: its CI hasn't built it yet, or failed" | |
| 73 | + note "(https://git.granstrm.com/dot). It would compile here, which takes a while." | |
| 74 | + read -rp "Compile it here? [y/N] " answer || answer="" | |
| 75 | + case $answer in | |
| 76 | + [yY]*) ;; | |
| 77 | + *) | |
| 78 | + echo "Nothing was changed." | |
| 79 | + sleep 1 | |
| 80 | + exit 0 | |
| 81 | + ;; | |
| 82 | + esac | |
| 83 | +fi | |
| 84 | + | |
| 85 | +step "Building" | |
| 86 | +nixos-rebuild build --flake "$tmp" | |
| 87 | +if [ "$(readlink -f "$tmp/result")" = "$(readlink -f /run/current-system)" ]; then | |
| 59 | 88 | printf '\nEverything is already up to date.\n' |
| 60 | 89 | wait_close |
| 61 | 90 | exit 0 |
| 62 | 91 | fi |
| 63 | - | |
| 64 | -step "Building" | |
| 65 | -nixos-rebuild build --flake "$tmp" | |
| 66 | 92 | |
| 67 | 93 | step "What changes" |
| 68 | -git --no-pager log -1 --format=%b | |
| 94 | +git --no-pager log --format='%s%n%n%b' "$main..HEAD" | |
| 69 | 95 | nvd diff /run/current-system "$tmp/result" |
| 70 | 96 | |
| 71 | 97 | echo |
| 72 | 98 | [ -z "$dirty" ] || note "Uncommitted changes in $repo are not part of this update." |
| 73 | -[ "$ahead" -eq 0 ] || note "main has $ahead commit(s) not on GitHub yet; they are pushed too." | |
| 99 | +[ "$ahead" -eq 0 ] || note "main has $ahead commit(s) not on git.granstrm.com yet; they are pushed too." | |
| 74 | 100 | read -rp "Commit, push, install and reboot? [y/N] " answer || answer="" |
| 75 | 101 | case $answer in |
| 76 | 102 | [yY]*) ;; |
@@ -92,7 +118,7 @@ | ||
| 92 | 118 | if [ "$(git -C "$repo" symbolic-ref --quiet --short HEAD)" = main ]; then |
| 93 | 119 | git -C "$repo" merge --ff-only "$commit" |
| 94 | 120 | else |
| 95 | - git -C "$repo" update-ref refs/heads/main "$commit" "$base" | |
| 121 | + git -C "$repo" update-ref refs/heads/main "$commit" "$main" | |
| 96 | 122 | fi |
| 97 | 123 | cd "$repo" |
| 98 | 124 | cleanup |
modifiedtools/server-update
@@ -84,7 +84,7 @@ | ||
| 84 | 84 | |
| 85 | 85 | echo |
| 86 | 86 | [ -z "$dirty" ] || note "Uncommitted changes in $repo are not part of this update." |
| 87 | -[ "$ahead" -eq 0 ] || note "main has $ahead commit(s) not on GitHub yet; they are pushed and deployed too." | |
| 87 | +[ "$ahead" -eq 0 ] || note "main has $ahead commit(s) not on git.granstrm.com yet; they are pushed and deployed too." | |
| 88 | 88 | read -rp "Commit, push and switch the server? [y/N] " answer || answer="" |
| 89 | 89 | case $answer in |
| 90 | 90 | [yY]*) ;; |
addedtools/update-kernel
@@ -1,0 +1,66 @@ | ||
| 1 | +#!/usr/bin/env bash | |
| 2 | +# The nightly CachyOS kernel update on git.granstrm.com (the update-kernel effect, | |
| 3 | +# flake.nix): moves the nix-cachyos-kernel input to the latest commit of its master | |
| 4 | +# branch and commits flake.lock, if the kernel changed (its version, config, | |
| 5 | +# patches or how it's built: the input's kernel-cachyos directory). Upstream's own | |
| 6 | +# daily nixpkgs updates alone don't count, or the kernel would be rebuilt every | |
| 7 | +# night. gt then fast-forwards main to the commit, and CI on it builds the kernel | |
| 8 | +# into the binary cache (cache.git.granstrm.com), so the Desktop update | |
| 9 | +# (tools/nixos-update) downloads it instead of compiling. | |
| 10 | +# | |
| 11 | +# It runs in gt's effect sandbox: a clone of main, the internet, and no Nix daemon, | |
| 12 | +# so the input is fetched into a store of its own under /tmp. | |
| 13 | +set -euo pipefail | |
| 14 | + | |
| 15 | +input=nix-cachyos-kernel | |
| 16 | +store=/tmp/store | |
| 17 | + | |
| 18 | +nix() { command nix --extra-experimental-features 'nix-command flakes' --store "$store" "$@"; } | |
| 19 | + | |
| 20 | +# The input's lock entry, by its name in the root's inputs. | |
| 21 | +locked() { jq -r --arg i "$input" '.nodes[.nodes.root.inputs[$i]].locked' flake.lock; } | |
| 22 | + | |
| 23 | +# Where a lock entry's source is, on disk. | |
| 24 | +source_of() { | |
| 25 | + local path | |
| 26 | + path=$(nix flake prefetch --json "$(jq -r '"github:\(.owner)/\(.repo)/\(.rev)"' <<<"$1")" | jq -r .storePath) | |
| 27 | + echo "$store$path" | |
| 28 | +} | |
| 29 | + | |
| 30 | +# The kernel cachyos.nix uses, linuxPackages-cachyos-latest-lto-zen4, is | |
| 31 | +# linux-cachyos's version. | |
| 32 | +version() { jq -r '."linux-cachyos".version' "$1/kernel-cachyos/version.json"; } | |
| 33 | + | |
| 34 | +old=$(locked) | |
| 35 | +nix flake update "$input" | |
| 36 | +new=$(locked) | |
| 37 | +old_rev=$(jq -r .rev <<<"$old") | |
| 38 | +new_rev=$(jq -r .rev <<<"$new") | |
| 39 | + | |
| 40 | +if [ "$old_rev" = "$new_rev" ]; then | |
| 41 | + echo "No new commit on $input." | tee /run/gt/skip | |
| 42 | + exit 0 | |
| 43 | +fi | |
| 44 | + | |
| 45 | +old_src=$(source_of "$old") | |
| 46 | +new_src=$(source_of "$new") | |
| 47 | +if [ "$(nix hash path "$old_src/kernel-cachyos")" = "$(nix hash path "$new_src/kernel-cachyos")" ]; then | |
| 48 | + echo "$input ${new_rev:0:7}: the kernel is the same, so it stays at ${old_rev:0:7}." | tee /run/gt/skip | |
| 49 | + exit 0 | |
| 50 | +fi | |
| 51 | + | |
| 52 | +old_version=$(version "$old_src") | |
| 53 | +new_version=$(version "$new_src") | |
| 54 | +if [ "$old_version" = "$new_version" ]; then | |
| 55 | + subject="CachyOS kernel $new_version, rebuilt" | |
| 56 | +else | |
| 57 | + subject="CachyOS kernel $new_version" | |
| 58 | +fi | |
| 59 | + | |
| 60 | +git add flake.lock | |
| 61 | +git -c user.name=git.granstrm.com -c user.email=gt@git.granstrm.com commit -q -F - <<EOF | |
| 62 | +$subject | |
| 63 | + | |
| 64 | +$input ${old_rev:0:7} -> ${new_rev:0:7}, kernel $old_version -> $new_version. | |
| 65 | +EOF | |
| 66 | +git --no-pager log -1 --format='%s%n%n%b' |