## Does some argument validation, performs some sanity checks, includes a hack to make installation work when nix isn't installed for root, and runs the installation in qemu (if requested).
if[[ -e "/run/keystore-@{config.networking.hostName!hashString.sha256:0:8}"]];thenecho"Keystore »/run/keystore-@{config.networking.hostName!hashString.sha256:0:8}/« is already open. Close it and remove the mountpoint before running the installer." 1>&2;\return 1;fi
if @{native.zfs}/bin/zfs get -o value -H name "$poolName"&>/dev/null ;thenecho"ZFS pool »$poolName« is already imported. Export the pool before running the installer." 1>&2;\return 1;fi
#if [[ ${args[debug]:-} ]] ; then set +e ; set -E ; trap 'code= ; timeout .2s cat &>/dev/null || true ; @{native.bashInteractive}/bin/bash --init-file @{config.environment.etc.bashrc.source} || code=$? ; if [[ $code ]] ; then exit $code ; fi' ERR ; fi # On error, instead of exiting straight away, open a shell to allow diagnosing/fixing the issue. Only exit if that shell reports failure (e.g. CtrlC + CtrlD). Unfortunately, the exiting has to be repeated for each level of each nested sub-shells. The »timeout cat« eats anything lined up on stdin, which would otherwise be sent to bash and interpreted as commands.
exportPATH=$PATH:@{native.util-linux}/bin # Doing a system installation requires a lot of stuff from »util-linux«. This should probably be moved into the individual functions that actually use the tools ...
## Re-executes the current system's installation in a qemu VM.
function reexec-in-qemu {
# (not sure whether this works for block devices)
ensure-disks "${argv[0]}"1||return
qemu=( -m 2048);declare -A qemuDevs=()
localindex=2;local name ;for name in "${!blockDevs[@]}";do
#if [[ ${blockDevs[$name]} != /dev/* ]] ; then
qemu+=(# not sure how correct the interpretations of the command are
-drive format=raw,file="$( realpath "${blockDevs[$name]}")",media=disk,if=none,index=${index},id=drive${index}# create the disk drive, without attaching it, name it driveX
#-device ahci,acpi-index=${index},id=ahci${index} # create an (ich9-)AHCI bus named »ahciX«
#-device ide-hd,drive=drive${index},bus=ahci${index}.${index} # attach IDE?! disk driveX as device X on bus »ahciX«
-device virtio-blk-pci,drive=drive${index},disable-modern=on,disable-legacy=off # alternative to the two lines above (implies to be faster, but seems to require guest drivers)
)
qemuDevs[$name]=/dev/vd$(printf"\x$(printf %x $(( index -1+97)))")# a is used by the (unused) root disk
letindex+=1
done
args[vm]=''
newArgs=();for arg in "${!args[@]}";donewArgs+=( --"$arg"="${args[$arg]}");done
devSpec=;for name in "${!qemuDevs[@]}";dodevSpec+="$name"="${qemuDevs[$name]}": ;done
# »nixos-install« by default does some stateful things (see »--no-root-passwd« »--no-channel-copy«), builds and copies the system config, registers the system (»nix-env --profile /nix/var/nix/profiles/system --set $targetSystem«), and then calls »NIXOS_INSTALL_BOOTLOADER=1 nixos-enter -- $topLevel/bin/switch-to-configuration boot«, which is essentially the same as »NIXOS_INSTALL_BOOTLOADER=1 nixos-enter -- @{config.system.build.installBootLoader} $targetSystem«, i.e. the side effects of »nixos-enter« and then calling the bootloader-installer.
#PATH=@{config.systemd.package}/bin:@{native.nix}/bin:$PATH TMPDIR=/tmp LC_ALL=C @{native.nixos-install-tools}/bin/nixos-install --system "$2" --no-root-passwd --no-channel-copy --root "$1" || exit # We did most of this, so just install the bootloader:
exportNIXOS_INSTALL_BOOTLOADER=1# tells some bootloader installers (systemd & grub) to not skip parts of the installation
## Copies the system's dependencies to the disks mounted at »$mnt« and installs the bootloader. If »$inspect« is set, a root shell will be opened in »$mnt« afterwards.
# »$topLevel« may point to an alternative top-level dependency to install.
mount tmpfs -t tmpfs $mnt/run ||exit; prepend_trap "umount -l $mnt/run" EXIT ||exit# If there isn't anything mounted here, »activate« will mount a tmpfs (inside »nixos-enter«'s private mount namespace). That would hide the additions below.
[[ -e $mnt/etc/NIXOS ]]|| touch $mnt/etc/NIXOS ||exit# for »switch-to-configuration«
#mkdir -p /nix/var/nix/db # »nixos-containers« requires this but nothing creates it before nix is used. BUT »nixos-enter« screams: »/nix/var/nix/db exists and is not a regular file.«
mount -o bind,ro /nix/store $mnt/nix/store ||exit; prepend_trap '! mountpoint -q $mnt/nix/store || umount -l $mnt/nix/store' EXIT ||exit# all the things required to _run_ the system are copied, but (may) need some more things to initially install it and/or enter the chroot (like qemu, see above)
(set +x ;echo"Something went wrong in the last step of the installation. Inspect the output above and the mounted system in this chroot shell to decide whether it is critical. Exit the shell with 0 to proceed, or non-zero to abort." 1>&2)
(set +x ;echo"[1;32mInstallation done![0m This shell is in a chroot in the mounted system for inspection. Exiting the shell will unmount the system." 1>&2)