Skip to content

Commit af5999e

Browse files
authored
Merge pull request #461 from a-kenji/feat/can-build-locally
feat: Add `--build-on` flag with settings: `auto`, `local`, `remote`
2 parents 90a51e8 + b5cc26d commit af5999e

File tree

4 files changed

+91
-12
lines changed

4 files changed

+91
-12
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ data has been migrated.
6868
- Source Machine:
6969

7070
- Can be any machine with Nix installed, e.g. a NixOS machine.
71-
- Should be able to build nix derivations for the target platform. Otherwise
72-
`--build-on-remote` can be used.
7371

7472
- Target Machine:
7573

docs/cli.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,9 @@ Options:
5353
build the closure on the remote machine instead of locally and copy-closuring it
5454
* --vm-test
5555
build the system and test the disk configuration inside a VM without installing it to the target.
56+
* --build-on auto|remote|local
57+
sets the build on settings to auto, remote or local. Default is auto.
58+
auto: tries to figure out, if the build is possible on the local host, if not falls back gracefully to remote build
59+
local: will build on the local host
60+
remote: will build on the remote host
5661
```

docs/requirements.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
- NixOS
1616
- Windows systems using WSL2.
1717

18-
_Note_: Should be able to build nix derivations for the target platform.
19-
Otherwise `--build-on-remote` can be used.
20-
2118
2. **Nix Installation:** If Nix is not yet installed on your system, refer to
2219
the [nix installation page](https://nixos.org/download#download-nix).
2320

src/nixos-anywhere.sh

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fi
3636
sshConnection=
3737
postKexecSshPort=22
3838
buildOnRemote=n
39+
buildOn=auto
3940
envPassword=n
4041

4142
# Facts set by get-facts.sh
@@ -129,8 +130,11 @@ Options:
129130
* --disko-mode disko|mount|format
130131
set the disko mode to format, mount or destroy. Default is disko.
131132
disko: first unmount and destroy all filesystems on the disks we want to format, then run the create and mount mode
132-
mount: mount the partition at the specified root-mountpoint
133-
format: create partition tables, zpools, lvms, raids and filesystems (Experimental: Can be run increntally, but use with caution and good backups)
133+
* --build-on auto|remote|local
134+
sets the build on settings to auto, remote or local. Default is auto.
135+
auto: tries to figure out, if the build is possible on the local host, if not falls back gracefully to remote build
136+
local: will build on the local host
137+
remote: will build on the remote host
134138
USAGE
135139
}
136140

@@ -146,6 +150,7 @@ step() {
146150
parseArgs() {
147151
local substituteOnDestination=y
148152
local printBuildLogs=n
153+
local buildOnRemote=n
149154
while [[ $# -gt 0 ]]; do
150155
case "$1" in
151156
-f | --flake)
@@ -233,6 +238,18 @@ parseArgs() {
233238
;;
234239
esac
235240

241+
shift
242+
;;
243+
--build-on)
244+
case "$2" in
245+
auto | local | remote)
246+
buildOn=$2
247+
;;
248+
*)
249+
abort "Supported values for --build-on are auto, local and remote. Unknown mode : $2"
250+
;;
251+
esac
252+
236253
shift
237254
;;
238255
--extra-files)
@@ -287,7 +304,9 @@ parseArgs() {
287304
substituteOnDestination=n
288305
;;
289306
--build-on-remote)
307+
echo "WARNING: --build-on-remote is deprecated, use --build-on remote instead" 2>&1
290308
buildOnRemote=y
309+
buildOn="remote"
291310
;;
292311
--env-password)
293312
envPassword=y
@@ -319,6 +338,10 @@ parseArgs() {
319338
abort "ssh-host must be set"
320339
fi
321340

341+
if [[ $buildOn == "local" ]] && [[ $buildOnRemote == "y" ]]; then
342+
abort "Conflicting flags: --build-on local and --build-on-remote used."
343+
fi
344+
322345
if [[ -n ${flake} ]]; then
323346
if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
324347
flake="${BASH_REMATCH[1]}"
@@ -371,7 +394,7 @@ runVmTest() {
371394
exit 1
372395
fi
373396

374-
if [[ ${buildOnRemote} == "y" ]]; then
397+
if [[ ${buildOn} == "remote" ]]; then
375398
echo "--vm-test is not supported with --build-on-remote" >&2
376399
exit 1
377400
fi
@@ -458,6 +481,47 @@ importFacts() {
458481
done
459482
}
460483

484+
checkBuildLocally() {
485+
local system extraPlatforms machineSystem
486+
system="$(nix --extra-experimental-features 'nix-command flakes' config show system)"
487+
extraPlatforms="$(nix --extra-experimental-features 'nix-command flakes' config show extra-platforms)"
488+
489+
if [[ $# -gt 0 ]]; then
490+
machineSystem=$1
491+
elif [[ -n ${nixosSystem} ]]; then
492+
machineSystem="$(cat "${nixosSystem}"/system)"
493+
else
494+
machineSystem="$(nix --extra-experimental-features 'nix-command flakes' eval --raw "${flake}"#"${flakeAttr}".pkgs.system 2>/dev/null || echo "unknown")"
495+
if [[ ${machineSystem} == "unknown" ]]; then
496+
buildOn=auto
497+
return
498+
fi
499+
fi
500+
501+
if [[ ${system} == "${machineSystem}" ]]; then
502+
buildOn=local
503+
return
504+
fi
505+
506+
if [[ ${extraPlatforms} == "*${machineSystem}*" ]]; then
507+
buildOn=local
508+
return
509+
fi
510+
511+
local entropy
512+
entropy="$(date +'%Y%m%d%H%M%S')"
513+
if nix build \
514+
-L \
515+
"${nixOptions[@]}" \
516+
--expr \
517+
"derivation { system = \"$system\"; name = \"env-$entropy\"; builder = \"/bin/sh\"; args = [ \"-c\" \"echo > \$out\" ]; }"; then
518+
# The local build failed
519+
buildOn=local
520+
fi
521+
522+
buildOn=remote
523+
}
524+
461525
generateHardwareConfig() {
462526
local maybeSudo="$maybeSudo"
463527
mkdir -p "$(dirname "$hardwareConfigPath")"
@@ -565,7 +629,7 @@ runDisko() {
565629
done
566630
if [[ -n ${diskoScript} ]]; then
567631
nixCopy --to "ssh://$sshConnection" "$diskoScript"
568-
elif [[ ${buildOnRemote} == "y" ]]; then
632+
elif [[ ${buildOn} == "remote" ]]; then
569633
step Building disko script
570634
# We need to do a nix copy first because nix build doesn't have --no-check-sigs
571635
# Use ssh:// here to avoid https://github.com/NixOS/nix/issues/7359
@@ -587,7 +651,7 @@ nixosInstall() {
587651
if [[ -n ${nixosSystem} ]]; then
588652
step Uploading the system closure
589653
nixCopy --to "ssh://$sshConnection?remote-store=local?root=/mnt" "$nixosSystem"
590-
elif [[ ${buildOnRemote} == "y" ]]; then
654+
elif [[ ${buildOn} == "remote" ]]; then
591655
step Building the system closure
592656
# We need to do a nix copy first because nix build doesn't have --no-check-sigs
593657
# Use ssh:// here to avoid https://github.com/NixOS/nix/issues/7359
@@ -652,9 +716,13 @@ main() {
652716
exit 0
653717
fi
654718
719+
if [[ ${buildOn} == "auto" ]]; then
720+
checkBuildLocally
721+
fi
722+
655723
# parse flake nixos-install style syntax, get the system attr
656724
if [[ -n ${flake} ]]; then
657-
if [[ ${buildOnRemote} == "n" ]] && [[ ${hardwareConfigBackend} == "none" ]]; then
725+
if [[ ${buildOn} == "local" ]] && [[ ${hardwareConfigBackend} == "none" ]]; then
658726
if [[ ${phases[disko]} == 1 ]]; then
659727
diskoScript=$(nixBuild "${flake}#${flakeAttr}.system.build.${diskoMode}Script")
660728
fi
@@ -716,7 +784,18 @@ main() {
716784
generateHardwareConfig
717785
fi
718786
719-
if [[ ${buildOnRemote} == "n" ]] && [[ -n ${flake} ]] && [[ ${hardwareConfigBackend} != "none" ]]; then
787+
# Before we do not have a valid hardware configuration we don't know the machine system
788+
if [[ ${buildOn} == "auto" ]]; then
789+
local remoteSystem
790+
remoteSystem=$(runSshNoTty -o ConnectTimeout=10 nix --extra-experimental-features nix-command config show system)
791+
checkBuildLocally "${remoteSystem}"
792+
# if we cannot figure it out at this point, we will build on the remote host
793+
if [[ ${buildOn} == "auto" ]]; then
794+
buildOn=remote
795+
fi
796+
fi
797+
798+
if [[ ${buildOn} != "remote" ]] && [[ -n ${flake} ]] && [[ -z ${diskoScript} ]]; then
720799
if [[ ${phases[disko]} == 1 ]]; then
721800
diskoScript=$(nixBuild "${flake}#${flakeAttr}.system.build.${diskoMode}Script")
722801
fi

0 commit comments

Comments
 (0)