123 lines
3.7 KiB
Nix
123 lines
3.7 KiB
Nix
# Binary-cache update mechanism for Jovian-NixOS desktops.
|
|
#
|
|
# Replaces the upstream holo-update/steamos-update stubs with a script that
|
|
# checks the private binary cache for a newer system closure, and provides a
|
|
# root-level systemd service to apply it. Steam's deck UI calls
|
|
# `steamos-update check` periodically; exit 7 = no update, exit 0 = update
|
|
# applied or available.
|
|
#
|
|
# The deploy endpoint is ${binary_cache_url}/deploy/${hostname} — a plain
|
|
# text file containing the /nix/store path of the latest closure, published
|
|
# by CI after a successful build.
|
|
{
|
|
pkgs,
|
|
lib,
|
|
hostname,
|
|
username,
|
|
site_config,
|
|
...
|
|
}:
|
|
let
|
|
deploy-url = "${site_config.binary_cache.url}/deploy/${hostname}";
|
|
|
|
steamos-update-script = pkgs.writeShellScript "steamos-update" ''
|
|
export PATH=${
|
|
lib.makeBinPath [
|
|
pkgs.curl
|
|
pkgs.coreutils
|
|
pkgs.systemd
|
|
]
|
|
}
|
|
|
|
STORE_PATH=$(curl -sf --max-time 30 "${deploy-url}" || true)
|
|
|
|
if [ -z "$STORE_PATH" ]; then
|
|
>&2 echo "[steamos-update] server unreachable"
|
|
exit 7
|
|
fi
|
|
|
|
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
|
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
|
>&2 echo "[steamos-update] no update available"
|
|
exit 7
|
|
fi
|
|
|
|
# check-only mode: just report that an update exists
|
|
if [ "''${1:-}" = "check" ] || [ "''${1:-}" = "--check-only" ]; then
|
|
>&2 echo "[steamos-update] update available"
|
|
exit 0
|
|
fi
|
|
|
|
# apply: trigger the root-running systemd service to install the update
|
|
>&2 echo "[steamos-update] applying update..."
|
|
if systemctl start --wait pull-update-apply.service; then
|
|
>&2 echo "[steamos-update] update installed, reboot to apply"
|
|
exit 0
|
|
else
|
|
>&2 echo "[steamos-update] apply failed; see 'journalctl -u pull-update-apply'"
|
|
exit 1
|
|
fi
|
|
'';
|
|
in
|
|
{
|
|
nixpkgs.overlays = [
|
|
(_final: prev: {
|
|
jovian-stubs = prev.jovian-stubs.overrideAttrs (old: {
|
|
buildCommand = (old.buildCommand or "") + ''
|
|
install -D -m 755 ${steamos-update-script} $out/bin/holo-update
|
|
install -D -m 755 ${steamos-update-script} $out/bin/steamos-update
|
|
'';
|
|
});
|
|
})
|
|
];
|
|
|
|
systemd.services.pull-update-apply = {
|
|
description = "Apply pending NixOS update pulled from binary cache";
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStart = pkgs.writeShellScript "pull-update-apply" ''
|
|
set -uo pipefail
|
|
export PATH=${
|
|
lib.makeBinPath [
|
|
pkgs.curl
|
|
pkgs.coreutils
|
|
pkgs.nix
|
|
]
|
|
}
|
|
|
|
STORE_PATH=$(curl -sf --max-time 30 "${deploy-url}" || true)
|
|
if [ -z "$STORE_PATH" ]; then
|
|
echo "server unreachable"
|
|
exit 1
|
|
fi
|
|
|
|
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
|
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
|
echo "already up to date: $STORE_PATH"
|
|
exit 0
|
|
fi
|
|
|
|
echo "applying $STORE_PATH (was $CURRENT)"
|
|
nix-store -r --add-root /nix/var/nix/gcroots/pull-update-apply-latest --indirect "$STORE_PATH" \
|
|
|| { echo "fetch failed"; exit 1; }
|
|
nix-env -p /nix/var/nix/profiles/system --set "$STORE_PATH" \
|
|
|| { echo "profile set failed"; exit 1; }
|
|
"$STORE_PATH/bin/switch-to-configuration" boot \
|
|
|| { echo "boot entry failed"; exit 1; }
|
|
echo "update applied; reboot required"
|
|
'';
|
|
};
|
|
};
|
|
|
|
# allow the primary user to trigger pull-update-apply without a password
|
|
security.polkit.extraConfig = ''
|
|
polkit.addRule(function(action, subject) {
|
|
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
|
action.lookup("unit") == "pull-update-apply.service" &&
|
|
subject.user == "${username}") {
|
|
return polkit.Result.YES;
|
|
}
|
|
});
|
|
'';
|
|
}
|