{ hostRegistry, inputs, lib, microvm, self }: let getHostAddr = name: let hostConf = hostRegistry."${name}" or (throw "Host ${name} has no ip4 or ip6 address"); in hostConf.ip4 or hostConf.ip6; # all the input flakes for `nix copy` to the build machine, # to be available for --override-input inputPaths = lib.escapeShellArgs (builtins.attrValues inputs); overrideInputsArgs = lib.concatStringsSep " " (builtins.attrValues (lib.mapAttrs (name: value: "--override-input ${name} ${value}") (lib.filterAttrs (name: _value: name != "self") inputs) )); in lib.attrsets.mapAttrs (system: pkgs: let overlayPkgs = builtins.intersectAttrs (self.overlays { } { }) pkgs; in overlayPkgs // { host-registry = pkgs.runCommand "host-registry" { src = builtins.toFile "host-registry.nix" ( lib.generators.toPretty { } hostRegistry ); } '' ln -s $src $out ''; list-upgradable = pkgs.writeScriptBin "list-upgradable" '' #! ${pkgs.runtimeShell} NORMAL="\033[0m" RED="\033[0;31m" YELLOW="\033[0;33m" GREEN="\033[0;32m" ${pkgs.lib.concatMapStringsSep "\n" (name: let addr = getHostAddr name; in lib.optionalString (addr != null) '' echo -n -e "${name}: $RED" RUNNING=$(ssh -o PreferredAuthentications=publickey -o StrictHostKeyChecking=accept-new root@"${addr}" "readlink /run/current-system") if [ $? = 0 ] && [ -n "$RUNNING" ]; then CURRENT=$(nix eval --raw ".#nixosConfigurations.${name}.config.system.build.toplevel" 2>/dev/null) RUNNING_VER=$(basename $RUNNING|rev|cut -d - -f 1|rev) RUNNING_DATE=$(echo $RUNNING_VER|cut -d . -f 3) CURRENT_VER=$(basename $CURRENT|rev|cut -d - -f 1|rev) CURRENT_DATE=$(echo $CURRENT_VER|cut -d . -f 3) if [ "$RUNNING" = "$CURRENT" ]; then echo -e "$GREEN"current"$NORMAL $RUNNING_VER" elif [ $RUNNING_DATE -gt $CURRENT_DATE ]; then echo -e "$GREEN"newer"$NORMAL $RUNNING_VER > $CURRENT_VER" elif [ "$RUNNING_VER" = "$CURRENT_VER" ]; then echo -e "$YELLOW"modified"$NORMAL $RUNNING_VER" elif [ -n "$RUNNING_VER" ]; then echo -e "$RED"outdated"$NORMAL $RUNNING_VER < $CURRENT_VER" else echo -e "$RED"error"$NORMAL $RUNNING_VER" fi fi echo -n -e "$NORMAL" '') (builtins.attrNames self.nixosConfigurations)} ''; prebuild-all = pkgs.runCommand "prebuild-all" { preferLocalBuild = true; } '' mkdir $out ${pkgs.lib.concatMapStrings (name: '' ln -s ${self.nixosConfigurations."${name}".config.system.build.toplevel} name '') (builtins.attrNames self.nixosConfigurations)} ''; prebuild-all-remote = pkgs.writeScriptBin "prebuild-all" '' #!${pkgs.runtimeShell} -e nix copy --no-check-sigs --to ssh-ng://$1 ${inputPaths} ssh $1 -- nix build -L --no-link ${ pkgs.lib.concatMapStringsSep " " (name: "${self}#nixosConfigurations.${name}.config.system.build.toplevel" ) (builtins.attrNames self.nixosConfigurations) } ''; } // builtins.foldl' (result: name: let host = getHostAddr name; target = ''root@"${host}"''; rebuildArg = "--flake ${self}#${name} ${overrideInputsArgs} --accept-flake-config"; hostConfig = self.nixosConfigurations."${name}".config; # let /var/lib/microvm/*/flake point to the flake-update branch so that # `microvm -u $NAME` updates to what hydra built today. selfRef = "git+https://gitea.c3d2.de/c3d2/nix-config?ref=flake-update"; in result // { # Generate a small script for copying this flake to the # remote machine and bulding and switching there. # Can be run with `nix run c3d2#…-nixos-rebuild switch` "${name}-nixos-rebuild" = pkgs.writeScriptBin "${name}-nixos-rebuild" '' #!${pkgs.runtimeShell} -e if nix eval .#nixosConfigurations.${name}.config.c3d2.deployment.server &>/dev/null; then echo "microvms cannot be updated with nixos-rebuild. Use nix run .#microvm-update-${name}" exit 2 fi [[ $(ssh ${target} cat /etc/hostname) == ${name} ]] nix copy --no-check-sigs --to ssh-ng://${target} ${inputPaths} # use nixos-rebuild from target config nixosRebuild=$(nix build ${self}#nixosConfigurations.${name}.config.system.build.nixos-rebuild ${overrideInputsArgs} --no-link --json | ${pkgs.jq}/bin/jq -r '.[0].outputs.out') nix copy --no-check-sigs --to ssh-ng://${target} $nixosRebuild ssh ${target} $nixosRebuild/bin/nixos-rebuild ${rebuildArg} "$@" ''; "${name}-nixos-rebuild-hydra" = pkgs.writeScriptBin "${name}-nixos-rebuild" '' #!${pkgs.runtimeShell} -e echo Copying Flakes nix copy --no-check-sigs --to ssh-ng://root@hydra.serv.zentralwerk.org ${inputPaths} echo Building on Hydra ssh root@hydra.serv.zentralwerk.org -- \ nix build -L -o /tmp/nixos-system-${name} \ ${self}#nixosConfigurations.${name}.config.system.build.toplevel echo Built. Obtaining link to data TOPLEVEL=$(ssh root@hydra.serv.zentralwerk.org \ readlink /tmp/nixos-system-${name}) echo Checking target ${name} ssh ${target} -- bash -e < flake [ -e old ] && nix store diff-closures ./old ./current ln -sfT \$PWD/current /nix/var/nix/gcroots/microvm/${name} ln -sfT \$PWD/booted /nix/var/nix/gcroots/microvm/booted-${name} ln -sfT \$PWD/old /nix/var/nix/gcroots/microvm/old-${name} systemctl restart microvm@${name}.service END '' else throw "${name} is not configured to run on microvm.nix. Is it a physical host or is it deployed in Skyflake?" ); "microvm-update-${name}-local" = pkgs.writeScriptBin "microvm-update-${name}" '' #!${pkgs.runtimeShell} -e ${lib.optionalString (!builtins.elem (hostConfig.c3d2.deployment.server or null) [ "server9" "server10" ]) '' echo "MicroVM must be configured to proper server" >&2 exit 1 ''} ${hostConfig.system.build.copyToServer} ${hostConfig.microvm.declaredRunner} ${hostConfig.system.build.runOnServer} bash -e < flake [ -e old ] && nix store diff-closures ./old ./current ln -sfT \$PWD/current /nix/var/nix/gcroots/microvm/${name} ln -sfT \$PWD/booted /nix/var/nix/gcroots/microvm/booted-${name} ln -sfT \$PWD/old /nix/var/nix/gcroots/microvm/old-${name} systemctl restart microvm@${name}.service END ''; }) { } (builtins.attrNames self.nixosConfigurations) // builtins.foldl' (result: host: let inherit (self.nixosConfigurations.${host}) config; in result // { # boot any machine in a microvm "${host}-vm" = (self.nixosConfigurations.${host}.extendModules { modules = [{ microvm = { mem = lib.mkForce 2048; hypervisor = lib.mkForce "qemu"; socket = lib.mkForce null; shares = lib.mkForce [{ tag = "ro-store"; source = "/nix/store"; mountPoint = "/nix/.ro-store"; }]; interfaces = lib.mkForce [{ type = "user"; id = "eth0"; mac = "02:23:de:ad:be:ef"; }]; }; boot.isContainer = lib.mkForce false; users.users.root.password = ""; fileSystems."/".fsType = lib.mkForce "tmpfs"; services.getty.helpLine = '' Log in as "root" with an empty password. Use "reboot" to shut qemu down. ''; }] ++ lib.optionals (! config ? microvm) [ microvm.nixosModules.microvm ]; }).config.microvm.declaredRunner; "${host}-tftproot" = config.system.build.tftproot or (lib.trace "No tftproot for ${host}" null); } ) { } (builtins.attrNames self.nixosConfigurations) ) self.legacyPackages