Skip to content

Commit f4849b2

Browse files
a-kenjiMic92
authored andcommitted
feat: Add --build-on flag with settings: auto, local, remote
Add `--build-on` flag with the following settings: `auto`(default), `local`, `remote`. - `auto`: Will check, if a local build is possible and gracefully fall back to a remote build. - `local`: Will build on the local host. - `remote`: Will build on the remote host.
1 parent 3a8ec88 commit f4849b2

File tree

4 files changed

+86
-12
lines changed

4 files changed

+86
-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: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ fi
3535
sshConnection=
3636
postKexecSshPort=22
3737
buildOnRemote=n
38+
buildOn=auto
3839
envPassword=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
131135
USAGE
132136
}
133137

@@ -143,6 +147,7 @@ step() {
143147
parseArgs() {
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,46 @@ 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+
481+
if [[ $# -gt 0 ]]; then
482+
machineSystem=$1
483+
elif [[ -n ${nixosSystem} ]]; then
484+
machineSystem="$(cat "${nixosSystem}"/system)"
485+
else
486+
machineSystem="$(nix --extra-experimental-features 'nix-command flakes' eval --raw "${flake}"#"${flakeAttr}".pkgs.system 2>/dev/null || echo "unknown")"
487+
if [[ ${machineSystem} == "unknown" ]]; then
488+
return
489+
fi
490+
fi
491+
492+
if [[ ${system} == "${machineSystem}" ]]; then
493+
return
494+
fi
495+
496+
if [[ ${extraPlatforms} == "*${machineSystem}*" ]]; then
497+
return
498+
fi
499+
500+
local entropy nonSubstitutableDrv
501+
entropy="$(date +'%Y%m%d%H%M%S')"
502+
nonSubstitutableDrv=$(nix eval \
503+
--impure \
504+
--raw \
505+
-L \
506+
"${nixOptions[@]}" \
507+
--expr \
508+
"((builtins.getFlake \"$flake\").inputs.nixpkgs.legacyPackages.$system.runCommandNoCC \"nixos-anywhere-can-build-$entropy\" { } \"echo > \$out\").drvPath")
509+
510+
if ! nix build "${nixOptions[@]}" "${nonSubstitutableDrv}^*"; then
511+
# The local build failed
512+
export buildOn=remote
513+
fi
514+
}
515+
453516
generateHardwareConfig() {
454517
local maybeSudo="$maybeSudo"
455518
mkdir -p "$(dirname "$hardwareConfigPath")"
@@ -557,7 +620,7 @@ runDisko() {
557620
done
558621
if [[ -n ${diskoScript} ]]; then
559622
nixCopy --to "ssh://$sshConnection" "$diskoScript"
560-
elif [[ ${buildOnRemote} == "y" ]]; then
623+
elif [[ ${buildOn} == "remote" ]]; then
561624
step Building disko script
562625
# We need to do a nix copy first because nix build doesn't have --no-check-sigs
563626
# Use ssh:// here to avoid https://github.com/NixOS/nix/issues/7359
@@ -579,7 +642,7 @@ nixosInstall() {
579642
if [[ -n ${nixosSystem} ]]; then
580643
step Uploading the system closure
581644
nixCopy --to "ssh://$sshConnection?remote-store=local?root=/mnt" "$nixosSystem"
582-
elif [[ ${buildOnRemote} == "y" ]]; then
645+
elif [[ ${buildOn} == "remote" ]]; then
583646
step Building the system closure
584647
# We need to do a nix copy first because nix build doesn't have --no-check-sigs
585648
# Use ssh:// here to avoid https://github.com/NixOS/nix/issues/7359
@@ -644,9 +707,13 @@ main() {
644707
exit 0
645708
fi
646709
710+
if [[ ${buildOn} == "auto" ]]; then
711+
canBuildLocally
712+
fi
713+
647714
# parse flake nixos-install style syntax, get the system attr
648715
if [[ -n ${flake} ]]; then
649-
if [[ ${buildOnRemote} == "n" ]] && [[ ${hardwareConfigBackend} == "none" ]]; then
716+
if [[ ${buildOn} == "local" ]] && [[ ${hardwareConfigBackend} == "none" ]]; then
650717
if [[ ${phases[disko]} == 1 ]]; then
651718
diskoScript=$(nixBuild "${flake}#${flakeAttr}.system.build.${diskoMode}Script")
652719
fi
@@ -708,7 +775,14 @@ main() {
708775
generateHardwareConfig
709776
fi
710777
711-
if [[ ${buildOnRemote} == "n" ]] && [[ -n ${flake} ]] && [[ ${hardwareConfigBackend} != "none" ]]; then
778+
# Before we do not have a valid hardware configuration we don't know the machine system
779+
if [[ ${buildOn} == "auto" ]]; then
780+
local remoteSystem
781+
remoteSystem=$(runSsh -o ConnectTimeout=10 nix --extra-experimental-features 'nix-command flakes' config show system)
782+
canBuildLocally "${remoteSystem}"
783+
fi
784+
785+
if [[ ${buildOn} != "remote" ]] && [[ -n ${flake} ]] && [[ ${hardwareConfigBackend} != "none" ]]; then
712786
if [[ ${phases[disko]} == 1 ]]; then
713787
diskoScript=$(nixBuild "${flake}#${flakeAttr}.system.build.${diskoMode}Script")
714788
fi

0 commit comments

Comments
 (0)