101 lines
3.6 KiB
Nix
101 lines
3.6 KiB
Nix
# services/prebuild.nix — nightly pre-build of the other hosts' system closures.
|
|
#
|
|
# Both laptops/desktops offload builds to this host (nix.buildMachines in
|
|
# common.nix), and the Macbook can't build at all (max-jobs = 0). Realising
|
|
# their toplevels here ahead of time turns `update` on those machines into a
|
|
# pure copy: the client's `update` alias re-runs this exact nix build over SSH
|
|
# (so eval happens here too, against a warm eval cache), finds the path already
|
|
# realised, and only copies the closure back.
|
|
#
|
|
# --out-link doubles as the gc root, so `clean` doesn't reap the closures
|
|
# before the other machines ever ask for them.
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
loupeCredential = pkgs.writeShellScript "forgejo-loupe-credential" ''
|
|
[ "''${1:-}" = get ] || exit 0
|
|
protocol= host= path=
|
|
while IFS='=' read -r key value; do
|
|
case "$key" in
|
|
protocol) protocol=$value ;;
|
|
host) host=$value ;;
|
|
path) path=$value ;;
|
|
esac
|
|
done
|
|
[ "$protocol" = https ] && [ "$host" = forg.gregersen.it ] || exit 0
|
|
case "$path" in
|
|
lazzexus/Loupe|lazzexus/Loupe.git) ;;
|
|
*) exit 0 ;;
|
|
esac
|
|
|
|
# Prefer a dedicated token. The router token can work too when it has
|
|
# read access to the private Loupe repository. Neither enters the store.
|
|
secret=/var/secrets/forgejo-loupe-token
|
|
[ -f "$secret" ] || secret=/var/secrets/forgejo-router-token
|
|
[ -f "$secret" ] || exit 0
|
|
if [ -r "$secret" ]; then
|
|
token=$(${pkgs.coreutils}/bin/cat "$secret")
|
|
else
|
|
token=$(/run/wrappers/bin/sudo -n ${pkgs.coreutils}/bin/cat "$secret") || exit 0
|
|
fi
|
|
[ -n "$token" ] || exit 0
|
|
printf 'username=rope\npassword=%s\n' "$token"
|
|
'';
|
|
|
|
mkService = host: {
|
|
description = "Pre-build the ${host} system closure";
|
|
after = [ "network-online.target" ];
|
|
wants = [ "network-online.target" ];
|
|
path = [ pkgs.git ];
|
|
environment.HOME = "/root";
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
StateDirectory = "prebuild";
|
|
};
|
|
# Gaming's kernel comes from lantian's attic (see hosts/hardware/
|
|
# FredOS-Gaming.nix). That substituter isn't configured on this host, so
|
|
# without it the cachyos kernel gets built from source here instead of
|
|
# fetched — hours, not minutes. Harmless for the Macbook.
|
|
script = ''
|
|
${config.nix.package}/bin/nix build --refresh \
|
|
--option extra-substituters https://attic.xuyh0120.win/lantian \
|
|
--option extra-trusted-public-keys lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc= \
|
|
--out-link /var/lib/prebuild/${host} \
|
|
'git+https://forg.gregersen.it/rope/nixos#nixosConfigurations.${host}.config.system.build.toplevel'
|
|
'';
|
|
};
|
|
|
|
# Staggered so the two builds don't fight over cores and bandwidth.
|
|
mkTimer = startAt: {
|
|
wantedBy = [ "timers.target" ];
|
|
timerConfig = {
|
|
OnCalendar = startAt;
|
|
Persistent = true;
|
|
RandomizedDelaySec = "20m";
|
|
};
|
|
};
|
|
in
|
|
{
|
|
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
|
|
# Nix's git+https input fetch uses Git outside the build sandbox. Both the
|
|
# root prebuild timer and fred's SSH-triggered rebuilds read credentials at
|
|
# fetch time, without putting a private token in flake.lock or /nix/store.
|
|
programs.git = {
|
|
enable = true;
|
|
config.credential = {
|
|
useHttpPath = true;
|
|
"https://forg.gregersen.it".helper = "${loupeCredential}";
|
|
};
|
|
};
|
|
|
|
systemd.services = {
|
|
prebuild-macbook = mkService "FredOS-Macbook";
|
|
prebuild-gaming = mkService "FredOS-Gaming";
|
|
};
|
|
|
|
systemd.timers = {
|
|
prebuild-macbook = mkTimer "04:00";
|
|
prebuild-gaming = mkTimer "05:00";
|
|
};
|
|
};
|
|
}
|