3535sshConnection=
3636postKexecSshPort=22
3737buildOnRemote=n
38+ buildOn=auto
3839envPassword=n
3940
4041# Facts set by get-facts.sh
@@ -126,8 +127,11 @@ Options:
126127* --disko-mode disko|mount|format
127128 set the disko mode to format, mount or destroy. Default is disko.
128129 disko: first unmount and destroy all filesystems on the disks we want to format, then run the create and mount mode
129- mount: mount the partition at the specified root-mountpoint
130- format: create partition tables, zpools, lvms, raids and filesystems (Experimental: Can be run increntally, but use with caution and good backups)
130+ * --build-on auto|remote|local
131+ sets the build on settings to auto, remote or local. Default is auto.
132+ auto: tries to figure out, if the build is possible on the local host, if not falls back gracefully to remote build
133+ local: will build on the local host
134+ remote: will build on the remote host
131135USAGE
132136}
133137
@@ -143,6 +147,7 @@ step() {
143147parseArgs () {
144148 local substituteOnDestination=y
145149 local printBuildLogs=n
150+ local buildOnRemote=n
146151 while [[ $# -gt 0 ]]; do
147152 case " $1 " in
148153 -f | --flake)
@@ -227,6 +232,18 @@ parseArgs() {
227232 ;;
228233 esac
229234
235+ shift
236+ ;;
237+ --build-on)
238+ case " $2 " in
239+ auto | local | remote)
240+ buildOn=$2
241+ ;;
242+ * )
243+ abort " Supported values for --build-on are auto, local and remote. Unknown mode : $2 "
244+ ;;
245+ esac
246+
230247 shift
231248 ;;
232249 --extra-files)
@@ -281,7 +298,9 @@ parseArgs() {
281298 substituteOnDestination=n
282299 ;;
283300 --build-on-remote)
301+ echo " WARNING: --build-on-remote is deprecated, use --build-on remote instead" 2>&1
284302 buildOnRemote=y
303+ buildOn=" remote"
285304 ;;
286305 --env-password)
287306 envPassword=y
@@ -313,6 +332,10 @@ parseArgs() {
313332 abort " ssh-host must be set"
314333 fi
315334
335+ if [[ $buildOn == " local" ]] && [[ $buildOnRemote == " y" ]]; then
336+ abort " Conflicting flags: --build-on local and --build-on-remote used."
337+ fi
338+
316339 if [[ -n ${flake} ]]; then
317340 if [[ $flake =~ ^(.* )\# ([^\#\" ]* )$ ]]; then
318341 flake=" ${BASH_REMATCH[1]} "
@@ -364,7 +387,7 @@ runVmTest() {
364387 exit 1
365388 fi
366389
367- if [[ ${buildOnRemote } == " y " ]]; then
390+ if [[ ${buildOn } == " remote " ]]; then
368391 echo " --vm-test is not supported with --build-on-remote" >&2
369392 exit 1
370393 fi
@@ -450,6 +473,36 @@ importFacts() {
450473 done
451474}
452475
476+ canBuildLocally () {
477+ local system extraPlatforms machineSystem
478+ system=" $( nix --extra-experimental-features ' nix-command flakes' config show system) "
479+ extraPlatforms=" $( nix --extra-experimental-features ' nix-command flakes' config show extra-platforms) "
480+ machineSystem=" $( nix --extra-experimental-features ' nix-command flakes' eval --raw " ${flake} " # "${flakeAttr}".nixpkgs.hostPlatform)"
481+
482+ if [[ ${system} == " ${machineSystem} " ]]; then
483+ return
484+ fi
485+
486+ if [[ ${extraPlatforms} == " *${machineSystem} *" ]]; then
487+ return
488+ fi
489+
490+ local entropy nonSubstitutableDrv
491+ entropy=" $( date +' %Y%m%d%H%M%S' ) "
492+ nonSubstitutableDrv=$( nix eval \
493+ --impure \
494+ --raw \
495+ -L \
496+ " ${nixOptions[@]} " \
497+ --expr \
498+ " ((builtins.getFlake \" $flake \" ).inputs.nixpkgs.legacyPackages.$system .runCommandNoCC \" nixos-anywhere-can-build-$entropy \" { } \" echo > \$ out\" ).drvPath" )
499+
500+ if ! nix build " ${nixOptions[@]} " " ${nonSubstitutableDrv} ^*" ; then
501+ # The local build failed
502+ export buildOn=remote
503+ fi
504+ }
505+
453506generateHardwareConfig () {
454507 local maybeSudo=" $maybeSudo "
455508 mkdir -p " $( dirname " $hardwareConfigPath " ) "
@@ -557,7 +610,7 @@ runDisko() {
557610 done
558611 if [[ -n ${diskoScript} ]]; then
559612 nixCopy --to " ssh://$sshConnection " " $diskoScript "
560- elif [[ ${buildOnRemote } == " y " ]]; then
613+ elif [[ ${buildOn } == " remote " ]]; then
561614 step Building disko script
562615 # We need to do a nix copy first because nix build doesn't have --no-check-sigs
563616 # Use ssh:// here to avoid https://github.com/NixOS/nix/issues/7359
@@ -579,7 +632,7 @@ nixosInstall() {
579632 if [[ -n ${nixosSystem} ]]; then
580633 step Uploading the system closure
581634 nixCopy --to " ssh://$sshConnection ?remote-store=local?root=/mnt" " $nixosSystem "
582- elif [[ ${buildOnRemote } == " y " ]]; then
635+ elif [[ ${buildOn } == " remote " ]]; then
583636 step Building the system closure
584637 # We need to do a nix copy first because nix build doesn't have --no-check-sigs
585638 # Use ssh:// here to avoid https://github.com/NixOS/nix/issues/7359
@@ -644,9 +697,13 @@ main() {
644697 exit 0
645698 fi
646699
700+ if [[ ${buildOn} == " auto" ]]; then
701+ canBuildLocally
702+ fi
703+
647704 # parse flake nixos-install style syntax, get the system attr
648705 if [[ -n ${flake} ]]; then
649- if [[ ${buildOnRemote } == " n " ]] && [[ ${hardwareConfigBackend} == " none" ]]; then
706+ if [[ ${buildOn } == " remote " ]] && [[ ${hardwareConfigBackend} == " none" ]]; then
650707 if [[ ${phases[disko]} == 1 ]]; then
651708 diskoScript=$( nixBuild " ${flake} #${flakeAttr} .system.build.${diskoMode} Script" )
652709 fi
@@ -708,7 +765,7 @@ main() {
708765 generateHardwareConfig
709766 fi
710767
711- if [[ ${buildOnRemote} == " n " ]] && [[ -n ${flake} ]] && [[ ${hardwareConfigBackend} != " none" ]]; then
768+ if [[ ${buildOn} != " remote " ]] && [[ -n ${flake} ]] && [[ ${hardwareConfigBackend} != " none" ]]; then
712769 if [[ ${phases[disko]} == 1 ]]; then
713770 diskoScript=$( nixBuild " ${flake} #${flakeAttr} .system.build.${diskoMode} Script" )
714771 fi
0 commit comments