dot

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

133 lines4416 bytesexecutable
1#!/usr/bin/env bash
2# Updates the server (granstrm, from the srv repo) the way nixos-update updates this
3# desktop, from a throwaway worktree so the checkout you edit in is left alone.
4# Started from the "Server" half of the control centre's update tile in a kitty
5# window (installed as `server-update`, modules/home/packages.nix).
6#
7# 1. a temporary worktree of main
8# 2. nix flake update, committed there
9# 3. builds the server's system and the repo's VM tests (router, web, media), then
10# nvd's list of what changed against the system the server runs
11# 4. asks before going on; then pushes the commit, switches the server to it over
12# SSH (nixos-rebuild switch --target-host) and brings your checkout's main up
13# to date
14# 5. if the kernel changed, asks whether to reboot the server now. It is the
15# house router, so the internet drops while it reboots.
16#
17# If anything fails, the window stays open until you press Enter, and nothing on the
18# server is changed.
19set -E
20
21repo=${SRV_REPO:-$HOME/git/srv}
22host=${SRV_HOST:-granstrm}
23tmp=""
24
25step() { printf '\n\e[1;34m==> %s\e[0m\n' "$*"; }
26note() { printf '\e[1;33m%s\e[0m\n' "$*"; }
27wait_close() { read -rp "Press Enter to close. " _ || true; }
28
29die() {
30 trap - ERR
31 printf '\n\e[1;31m%s\e[0m\n' "$*"
32 wait_close
33 exit 1
34}
35
36cleanup() {
37 if [ -n "$tmp" ]; then
38 git -C "$repo" worktree remove --force "$tmp" 2>/dev/null || true
39 rm -rf "$tmp"
40 tmp=""
41 fi
42}
43
44trap 'die "The update failed (see above). The server was not changed."' ERR
45trap cleanup EXIT
46
47step "Fetching $repo"
48git -C "$repo" worktree prune
49git -C "$repo" fetch origin main
50git -C "$repo" merge-base --is-ancestor origin/main main ||
51 die "main in $repo is behind origin/main (or has diverged); pull first."
52base=$(git -C "$repo" rev-parse main)
53ahead=$(git -C "$repo" rev-list --count origin/main..main)
54dirty=$(git -C "$repo" status --porcelain)
55
56tmp=$(mktemp -d -t srv-update.XXXXXX)
57step "Creating a worktree of main in $tmp"
58git -C "$repo" worktree add --detach "$tmp" main
59cd "$tmp" || die "Could not enter $tmp."
60
61step "Updating flake inputs"
62nix flake update --commit-lock-file
63if [ "$(git rev-parse HEAD)" = "$base" ]; then
64 printf '\nEverything is already up to date.\n'
65 wait_close
66 exit 0
67fi
68
69step "Building the server's system"
70nixos-rebuild build --flake "$tmp#$host"
71
72checks=$(nix eval --raw .#checks.x86_64-linux --apply 'c: builtins.concatStringsSep " " (builtins.attrNames c)')
73step "Running the VM tests ($checks)"
74for c in $checks; do
75 nix build --no-link ".#checks.x86_64-linux.$c"
76done
77
78step "What changes"
79git --no-pager log -1 --format=%b
80running=$(ssh "$host" readlink -f /run/current-system)
81# Usually still here from the last deploy; fetched from the server if not.
82nix path-info "$running" >/dev/null 2>&1 || nix copy --from "ssh-ng://$host" "$running"
83nvd diff "$running" "$tmp/result"
84
85echo
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 git.granstrm.com yet; they are pushed and deployed too."
88read -rp "Commit, push and switch the server? [y/N] " answer || answer=""
89case $answer in
90 [yY]*) ;;
91 *)
92 echo "Nothing was changed."
93 sleep 1
94 exit 0
95 ;;
96esac
97
98step "Pushing"
99git push origin HEAD:main
100
101step "Switching the server"
102nixos-rebuild switch --flake "$tmp#$host" --target-host "$host"
103
104step "Updating main in $repo"
105commit=$(git rev-parse HEAD)
106if [ "$(git -C "$repo" symbolic-ref --quiet --short HEAD)" = main ]; then
107 git -C "$repo" merge --ff-only "$commit"
108else
109 git -C "$repo" update-ref refs/heads/main "$commit" "$base"
110fi
111cd "$repo"
112cleanup
113
114# The same test NixOS's own auto-upgrade uses: a new kernel or initrd only takes
115# effect after a reboot.
116# shellcheck disable=SC2016 # expanded on the server
117if ssh "$host" '[ "$(readlink /run/booted-system/{initrd,kernel,kernel-modules})" = "$(readlink /run/current-system/{initrd,kernel,kernel-modules})" ]'; then
118 printf '\nDone. No reboot needed.\n'
119 wait_close
120 exit 0
121fi
122
123echo
124note "The kernel changed; it is used after the server's next reboot."
125read -rp "Reboot the server now? The internet drops for a few minutes. [y/N] " answer || answer=""
126case $answer in
127 [yY]*)
128 step "Rebooting the server"
129 ssh "$host" systemctl reboot || true
130 ;;
131 *) echo "Not rebooted. The new kernel is used after the next reboot." ;;
132esac
133wait_close