forked from extern/nixos-installer
small fixes, esp. for cross-building
This commit is contained in:
parent
9edfe9c9d8
commit
c001ad7f51
@ -77,13 +77,14 @@ in rec {
|
|||||||
entryPath ? null, config ? null, preface ? null,
|
entryPath ? null, config ? null, preface ? null,
|
||||||
inputs ? { }, overlays ? (getOverlaysFromInputs inputs), modules ? (getModulesFromInputs inputs),
|
inputs ? { }, overlays ? (getOverlaysFromInputs inputs), modules ? (getModulesFromInputs inputs),
|
||||||
peers ? { }, nixosSystem ? inputs.nixpkgs.lib.nixosSystem, localSystem ? null,
|
peers ? { }, nixosSystem ? inputs.nixpkgs.lib.nixosSystem, localSystem ? null,
|
||||||
|
renameOutputs ? (name: null), # If not supplied (explicitly or as »false« by »mkSystemsFlake«), assume the system is not exported.
|
||||||
... }: let
|
... }: let
|
||||||
preface = args.preface or (getSystemPreface inputs entryPath (specialArgs // { inherit name; }));
|
preface = args.preface or (getSystemPreface inputs entryPath (specialArgs // { inherit name; }));
|
||||||
targetSystem = "${preface.hardware}-linux"; buildSystem = if localSystem != null then localSystem else targetSystem;
|
targetSystem = "${preface.hardware}-linux"; buildSystem = if localSystem != null then localSystem else targetSystem;
|
||||||
specialArgs = (args.specialArgs or { }) // {
|
specialArgs = (args.specialArgs or { }) // {
|
||||||
nodes = peers; # NixOPS
|
nodes = peers; # NixOPS
|
||||||
};
|
};
|
||||||
outputName = if args?renameOutputs then args.renameOutputs name else name;
|
outputName = if renameOutputs != false then renameOutputs name else name;
|
||||||
in let system = { inherit preface; } // (nixosSystem {
|
in let system = { inherit preface; } // (nixosSystem {
|
||||||
system = buildSystem; # (this actually does nothing more than setting »config.nixpkgs.system« and can be null here)
|
system = buildSystem; # (this actually does nothing more than setting »config.nixpkgs.system« and can be null here)
|
||||||
|
|
||||||
@ -190,9 +191,9 @@ in rec {
|
|||||||
# If provided, then cross compilation is enabled for all hosts whose target architecture is different from this. Since cross compilation currently fails for (some stuff in) NixOS, better don't set »localSystem«. Without it, building for other platforms works fine (just slowly) if »boot.binfmt.emulatedSystems« on the building system is configured for the respective target(s).
|
# If provided, then cross compilation is enabled for all hosts whose target architecture is different from this. Since cross compilation currently fails for (some stuff in) NixOS, better don't set »localSystem«. Without it, building for other platforms works fine (just slowly) if »boot.binfmt.emulatedSystems« on the building system is configured for the respective target(s).
|
||||||
localSystem ? null,
|
localSystem ? null,
|
||||||
## If provided, then change the name of each output attribute by passing it through this function. Allows exporting of multiple variants of a repo's hosts from a single flake:
|
## If provided, then change the name of each output attribute by passing it through this function. Allows exporting of multiple variants of a repo's hosts from a single flake:
|
||||||
renameOutputs ? null,
|
renameOutputs ? false,
|
||||||
... }: let
|
... }: let
|
||||||
otherArgs = args // { inherit inputs overlays modules specialArgs nixosSystem localSystem; };
|
otherArgs = args // { inherit inputs overlays modules specialArgs nixosSystem localSystem renameOutputs; };
|
||||||
nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems);
|
nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems);
|
||||||
in let outputs = {
|
in let outputs = {
|
||||||
inherit nixosConfigurations;
|
inherit nixosConfigurations;
|
||||||
@ -207,11 +208,11 @@ in rec {
|
|||||||
packages.all-systems = pkgs.runCommandLocal "all-systems" { } ''
|
packages.all-systems = pkgs.runCommandLocal "all-systems" { } ''
|
||||||
${''
|
${''
|
||||||
mkdir -p $out/systems
|
mkdir -p $out/systems
|
||||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${system.config.system.build.toplevel} $out/systems/${name}") nixosConfigurations)}
|
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${system.config.system.build.toplevel} $out/systems/${if renameOutputs == false then name else renameOutputs name}") nixosConfigurations)}
|
||||||
''}
|
''}
|
||||||
${''
|
${''
|
||||||
mkdir -p $out/scripts
|
mkdir -p $out/scripts
|
||||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${outputs.apps.${localSystem}.${name}.program} $out/scripts/${name}") nixosConfigurations)}
|
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${outputs.apps.${localSystem}.${name}.program} $out/scripts/${if renameOutputs == false then name else renameOutputs name}") nixosConfigurations)}
|
||||||
''}
|
''}
|
||||||
${lib.optionalString (inputs != { }) ''
|
${lib.optionalString (inputs != { }) ''
|
||||||
mkdir -p $out/inputs
|
mkdir -p $out/inputs
|
||||||
@ -220,7 +221,7 @@ in rec {
|
|||||||
'';
|
'';
|
||||||
checks.all-systems = packages.all-systems;
|
checks.all-systems = packages.all-systems;
|
||||||
|
|
||||||
})); in if renameOutputs == null then outputs else {
|
})); in if renameOutputs == false then outputs else {
|
||||||
nixosConfigurations = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.nixosConfigurations;
|
nixosConfigurations = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.nixosConfigurations;
|
||||||
} // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: {
|
} // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: {
|
||||||
apps = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.apps.${localSystem};
|
apps = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.apps.${localSystem};
|
||||||
|
@ -98,7 +98,7 @@ in rec {
|
|||||||
wrap-script = args@{ pkgs, src, deps, ... }: let
|
wrap-script = args@{ pkgs, src, deps, ... }: let
|
||||||
name = args.name or (builtins.baseNameOf (builtins.unsafeDiscardStringContext "${src}"));
|
name = args.name or (builtins.baseNameOf (builtins.unsafeDiscardStringContext "${src}"));
|
||||||
in pkgs.runCommandLocal name {
|
in pkgs.runCommandLocal name {
|
||||||
script = src; nativeBuildInputs = [ pkgs.makeWrapper ];
|
script = src; nativeBuildInputs = [ pkgs.buildPackages.makeWrapper ];
|
||||||
} ''makeWrapper $script $out/bin/${name} --prefix PATH : ${lib.makeBinPath deps}'';
|
} ''makeWrapper $script $out/bin/${name} --prefix PATH : ${lib.makeBinPath deps}'';
|
||||||
|
|
||||||
# Simplifies a path (or any other string) such that it can be used as a systemd unit name.
|
# Simplifies a path (or any other string) such that it can be used as a systemd unit name.
|
||||||
|
@ -16,12 +16,13 @@ function prepare-installer { # (void)
|
|||||||
|
|
||||||
: ${argv[0]:?"Required: Target disk or image paths."}
|
: ${argv[0]:?"Required: Target disk or image paths."}
|
||||||
|
|
||||||
|
umask g-w,o-w # Ensure that files created without explicit permissions are not writable for group and other (0022).
|
||||||
|
|
||||||
if [[ "$(id -u)" != '0' ]] ; then
|
if [[ "$(id -u)" != '0' ]] ; then
|
||||||
if [[ ! ${args[no-vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi
|
if [[ ! ${args[no-vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi
|
||||||
echo 'Script must be run as root or in qemu (without »--no-vm«).' 1>&2 ; \return 1
|
echo 'Script must be run as root or in qemu (without »--no-vm«).' 1>&2 ; \return 1
|
||||||
fi
|
fi
|
||||||
if [[ ${args[vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi
|
if [[ ${args[vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi
|
||||||
umask 0022 # Ensure consistent umask (default permissions for new files).
|
|
||||||
|
|
||||||
if [[ -e "/run/keystore-@{config.networking.hostName!hashString.sha256:0:8}" ]] ; then echo "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 [[ -e "/run/keystore-@{config.networking.hostName!hashString.sha256:0:8}" ]] ; then echo "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
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ function prepare-installer { # (void)
|
|||||||
if @{native.zfs}/bin/zfs get -o value -H name "$poolName" &>/dev/null ; then echo "ZFS pool »$poolName« is already imported. Export the pool before running the installer." 1>&2 ; \return 1 ; fi
|
if @{native.zfs}/bin/zfs get -o value -H name "$poolName" &>/dev/null ; then echo "ZFS pool »$poolName« is already imported. Export the pool before running the installer." 1>&2 ; \return 1 ; fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ ${SUDO_USER:-} ]] ; then # use Nix as the user who called this script, as Nix may not be set up for root
|
if [[ ${SUDO_USER:-} && $( PATH=$hostPath which su 2>/dev/null ) ]] ; then # use Nix as the user who called this script, as Nix may not be set up for root
|
||||||
function nix {( set +x ; declare -a args=("$@") ; PATH=$hostPath su - "$SUDO_USER" -c "$(declare -p args)"' ; nix "${args[@]}"' )}
|
function nix {( set +x ; declare -a args=("$@") ; PATH=$hostPath su - "$SUDO_USER" -c "$(declare -p args)"' ; nix "${args[@]}"' )}
|
||||||
else # use Nix by absolute path, as it won't be on »$PATH«
|
else # use Nix by absolute path, as it won't be on »$PATH«
|
||||||
PATH=$PATH:@{native.nix}/bin
|
PATH=$PATH:@{native.nix}/bin
|
||||||
@ -50,6 +51,8 @@ function prepare-installer { # (void)
|
|||||||
## Re-executes the current system's installation in a qemu VM.
|
## Re-executes the current system's installation in a qemu VM.
|
||||||
function reexec-in-qemu {
|
function reexec-in-qemu {
|
||||||
|
|
||||||
|
if [[ @{pkgs.buildPackages.system} != "@{native.system}" ]] ; then echo "VM installation (implicit when not running as root) of a system built on a different ISA than the current host's is not supported (yet)." 1>&2 ; \return 1 ; fi
|
||||||
|
|
||||||
# (not sure whether this works for block devices)
|
# (not sure whether this works for block devices)
|
||||||
ensure-disks "${argv[0]}" 1 || return
|
ensure-disks "${argv[0]}" 1 || return
|
||||||
qemu=( -m 2048 ) ; declare -A qemuDevs=( )
|
qemu=( -m 2048 ) ; declare -A qemuDevs=( )
|
||||||
@ -65,16 +68,19 @@ function reexec-in-qemu {
|
|||||||
let index+=1
|
let index+=1
|
||||||
done
|
done
|
||||||
|
|
||||||
args[vm]=''
|
args[vm]='' ; args[no-vm]=1
|
||||||
newArgs=( ) ; for arg in "${!args[@]}" ; do newArgs+=( --"$arg"="${args[$arg]}" ) ; done
|
newArgs=( ) ; for arg in "${!args[@]}" ; do newArgs+=( --"$arg"="${args[$arg]}" ) ; done
|
||||||
devSpec= ; for name in "${!qemuDevs[@]}" ; do devSpec+="$name"="${qemuDevs[$name]}": ; done
|
devSpec= ; for name in "${!qemuDevs[@]}" ; do devSpec+="$name"="${qemuDevs[$name]}": ; done
|
||||||
newArgs+=( ${devSpec%:} ) ; (( ${#argv[@]} > 1 )) && args+=( "${argv[@]:1}" )
|
newArgs+=( ${devSpec%:} ) ; (( ${#argv[@]} > 1 )) && args+=( "${argv[@]:1}" )
|
||||||
|
|
||||||
#local output=@{inputs.self}'#'nixosConfigurations.@{outputName:?}.config.system.build.vmExec
|
#local output=@{inputs.self}'#'nixosConfigurations.@{outputName:?}.config.system.build.vmExec
|
||||||
local output=@{config.system.build.vmExec.drvPath} # this is more accurate, but also means another system needs to get evaluated every time
|
local output=@{config.system.build.vmExec.drvPath!unsafeDiscardStringContext} # this is more accurate, but also means another system needs to get evaluated every time
|
||||||
local command="$0 install-system $( printf '%q ' "${newArgs[@]}" ) || exit"
|
local scripts=$0 ; if [[ @{pkgs.system} != "@{native.system}" ]] ; then
|
||||||
|
scripts=$( build-lazy @{inputs.self}'#'apps.@{pkgs.system}.@{outputName:?}.derivation )
|
||||||
|
fi
|
||||||
|
local command="$scripts install-system $( printf '%q ' "${newArgs[@]}" ) || exit"
|
||||||
|
|
||||||
local runInVm ; runInVm=$( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json ${args[quiet]:+--quiet} $output | @{native.jq}/bin/jq -r .[0].outputs.out )/bin/run-@{config.system.name}-vm-exec || return
|
local runInVm ; runInVm=$( build-lazy $output )/bin/run-@{config.system.name}-vm-exec || return
|
||||||
|
|
||||||
$runInVm ${args[vm-shared]:+--shared="${args[vm-shared]}"} ${args[debug]:+--initrd-console} ${args[trace]:+--initrd-console} ${args[quiet]:+--quiet} -- "$command" "${qemu[@]}" || return # --initrd-console
|
$runInVm ${args[vm-shared]:+--shared="${args[vm-shared]}"} ${args[debug]:+--initrd-console} ${args[trace]:+--initrd-console} ${args[quiet]:+--quiet} -- "$command" "${qemu[@]}" || return # --initrd-console
|
||||||
}
|
}
|
||||||
@ -118,8 +124,8 @@ function install-system-to {( set -u # 1: mnt
|
|||||||
|
|
||||||
# Support cross architecture installation (not sure if this is actually required)
|
# Support cross architecture installation (not sure if this is actually required)
|
||||||
if [[ $(cat /run/current-system/system 2>/dev/null || echo "x86_64-linux") != "@{config.wip.preface.hardware}"-linux ]] ; then
|
if [[ $(cat /run/current-system/system 2>/dev/null || echo "x86_64-linux") != "@{config.wip.preface.hardware}"-linux ]] ; then
|
||||||
mkdir -p $mnt/run/binfmt || exit ; [[ ! -e /run/binfmt/"@{config.wip.preface.hardware}"-linux ]] || cp -a {,$mnt}/run/binfmt/"@{config.wip.preface.hardware}"-linux || exit
|
mkdir -p $mnt/run/binfmt || exit ; [[ ! -e /run/binfmt/"@{config.wip.preface.hardware}"-linux ]] || cp -a {,$mnt}/run/binfmt/"@{config.wip.preface.hardware}"-linux || exit # On NixOS, this is a symlink or wrapper script, pointing to the store.
|
||||||
# Ubuntu (by default) expects the "interpreter" at »/usr/bin/qemu-@{config.wip.preface.hardware}-static«.
|
# Ubuntu (20.04, by default) uses a statically linked, already loaded qemu binary (F-flag), which therefore does not need to be reference-able from within the chroot.
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy system closure to new nix store:
|
# Copy system closure to new nix store:
|
||||||
|
@ -54,7 +54,7 @@ function run-qemu { # 1: diskImages, ...: qemuArgs
|
|||||||
local qemu=( )
|
local qemu=( )
|
||||||
|
|
||||||
if [[ @{pkgs.system} == "@{native.system}" ]] ; then
|
if [[ @{pkgs.system} == "@{native.system}" ]] ; then
|
||||||
qemu=( $( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json @{native.qemu_kvm.drvPath} | @{native.jq}/bin/jq -r .[0].outputs.out )/bin/qemu-kvm ) || return
|
qemu=( $( build-lazy @{native.qemu_kvm.drvPath!unsafeDiscardStringContext} )/bin/qemu-kvm ) || return
|
||||||
if [[ ! ${args[no-kvm]:-} && -r /dev/kvm && -w /dev/kvm ]] ; then
|
if [[ ! ${args[no-kvm]:-} && -r /dev/kvm && -w /dev/kvm ]] ; then
|
||||||
# For KVM to work, vBox must not be running anything at the same time (and vBox hangs on start if qemu runs). Pass »--no-kvm« and accept ~10x slowdown, or stop vBox.
|
# For KVM to work, vBox must not be running anything at the same time (and vBox hangs on start if qemu runs). Pass »--no-kvm« and accept ~10x slowdown, or stop vBox.
|
||||||
qemu+=( -enable-kvm -cpu host )
|
qemu+=( -enable-kvm -cpu host )
|
||||||
@ -64,32 +64,25 @@ function run-qemu { # 1: diskImages, ...: qemuArgs
|
|||||||
echo "KVM is not available (for the current user). Running without hardware acceleration." 1>&2
|
echo "KVM is not available (for the current user). Running without hardware acceleration." 1>&2
|
||||||
fi
|
fi
|
||||||
qemu+=( -machine accel=tcg ) # this may suppress warnings that qemu is using tcg (slow) instead of kvm
|
qemu+=( -machine accel=tcg ) # this may suppress warnings that qemu is using tcg (slow) instead of kvm
|
||||||
if [[ @{pkgs.system} == aarch64-* ]] ; then qemu+=( -cpu max ) ; fi
|
|
||||||
fi
|
|
||||||
if [[ @{pkgs.system} == aarch64-* ]] ; then
|
|
||||||
qemu+=( -machine type=virt -cpu max ) # aarch64 has no default, but this seems good
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
qemu=( $( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json @{native.qemu_full.drvPath} | @{native.jq}/bin/jq -r .[0].outputs.out )/bin/qemu-system-@{config.wip.preface.hardware} ) || return
|
qemu=( $( build-lazy @{native.qemu_full.drvPath!unsafeDiscardStringContext} )/bin/qemu-system-@{config.wip.preface.hardware} ) || return
|
||||||
if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then # assume it's a raspberry PI (or compatible)
|
|
||||||
# TODO: this does not work yet:
|
|
||||||
qemu+=( -machine type=raspi3b -m 1024 ) ; args[no-nat]=1
|
|
||||||
# ... and neither does this:
|
|
||||||
#qemu+=( -machine type=virt -m 1024 -smp 4 -cpu cortex-a53 ) ; args[no-nat]=1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
if [[ @{pkgs.system} == aarch64-* ]] ; then
|
||||||
|
qemu+=( -machine type=virt ) # aarch64 has no default, but this seems good
|
||||||
|
fi ; qemu+=( -cpu max )
|
||||||
|
|
||||||
qemu+=( -m ${args[mem]:-2048} )
|
qemu+=( -m ${args[mem]:-2048} )
|
||||||
if [[ ${args[smp]:-} ]] ; then qemu+=( -smp ${args[smp]} ) ; fi
|
if [[ ${args[smp]:-} ]] ; then qemu+=( -smp ${args[smp]} ) ; fi
|
||||||
|
|
||||||
if [[ @{config.boot.loader.systemd-boot.enable} || ${args[efi]:-} ]] ; then # UEFI. Otherwise it boots SeaBIOS.
|
if [[ @{config.boot.loader.systemd-boot.enable} || ${args[efi]:-} ]] ; then # UEFI. Otherwise it boots SeaBIOS.
|
||||||
local ovmf ; ovmf=$( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json @{native.OVMF.drvPath} | @{native.jq}/bin/jq -r .[0].outputs.fd ) || return
|
local ovmf ; ovmf=$( build-lazy @{pkgs.OVMF.drvPath!unsafeDiscardStringContext} fd ) || return
|
||||||
#qemu+=( -bios ${ovmf}/FV/OVMF.fd ) # This works, but is a legacy fallback that stores the EFI vars in /NvVars on the EFI partition (which is really bad).
|
#qemu+=( -bios ${ovmf}/FV/OVMF.fd ) # This works, but is a legacy fallback that stores the EFI vars in /NvVars on the EFI partition (which is really bad).
|
||||||
local fwName=OVMF ; if [[ @{pkgs.system} == aarch64-* ]] ; then fwName=AAVMF ; fi # fwName=QEMU
|
local fwName=OVMF ; if [[ @{pkgs.system} == aarch64-* ]] ; then fwName=AAVMF ; fi # fwName=QEMU
|
||||||
qemu+=( -drive file=${ovmf}/FV/${fwName}_CODE.fd,if=pflash,format=raw,unit=0,readonly=on )
|
qemu+=( -drive file=${ovmf}/FV/${fwName}_CODE.fd,if=pflash,format=raw,unit=0,readonly=on )
|
||||||
local efiVars=${args[efi-vars]:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/qemu-@{outputName:-@{config.system.name}}-VARS.fd}
|
local efiVars=${args[efi-vars]:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/qemu-@{outputName:-@{config.system.name}}-VARS.fd}
|
||||||
qemu+=( -drive file="$efiVars",if=pflash,format=raw,unit=1 )
|
qemu+=( -drive file="$efiVars",if=pflash,format=raw,unit=1 )
|
||||||
if [[ ! -e "$efiVars" ]] ; then cat ${ovmf}/FV/${fwName}_VARS.fd >"$efiVars" || return ; fi
|
if [[ ! -e "$efiVars" ]] ; then mkdir -pm700 "$( dirname "$efiVars" )" ; cat ${ovmf}/FV/${fwName}_VARS.fd >"$efiVars" || return ; fi
|
||||||
# https://lists.gnu.org/archive/html/qemu-discuss/2018-04/msg00045.html
|
# https://lists.gnu.org/archive/html/qemu-discuss/2018-04/msg00045.html
|
||||||
fi
|
fi
|
||||||
# if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then
|
# if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then
|
||||||
@ -99,14 +92,18 @@ function run-qemu { # 1: diskImages, ...: qemuArgs
|
|||||||
if [[ $diskImages == */ ]] ; then
|
if [[ $diskImages == */ ]] ; then
|
||||||
disks=( ${diskImages}primary.img ) ; for name in "@{!config.wip.fs.disks.devices[@]}" ; do if [[ $name != primary ]] ; then disks+=( ${diskImages}${name}.img ) ; fi ; done
|
disks=( ${diskImages}primary.img ) ; for name in "@{!config.wip.fs.disks.devices[@]}" ; do if [[ $name != primary ]] ; then disks+=( ${diskImages}${name}.img ) ; fi ; done
|
||||||
else disks=( ${diskImages//:/ } ) ; fi
|
else disks=( ${diskImages//:/ } ) ; fi
|
||||||
|
|
||||||
|
[[ ' '"@{boot.initrd.availableKernelModules[@]}"' ' != *' 'virtio_blk' '* ]] || args[virtio-blk]=1
|
||||||
local index ; for index in ${!disks[@]} ; do
|
local index ; for index in ${!disks[@]} ; do
|
||||||
# qemu+=( -drive format=raw,if=ide,file="${disks[$index]/*=/}" ) # »if=ide« is the default, which these days isn't great for driver support inside the VM
|
# qemu+=( -drive format=raw,if=ide,file="${disks[$index]/*=/}" ) # »if=ide« is the default, which these days isn't great for driver support inside the VM
|
||||||
qemu+=( # not sure how correct the interpretations of the command are
|
qemu+=( -drive format=raw,file="${disks[$index]/*=/}",media=disk,if=none,index=${index},id=drive${index} ) # create the disk drive, without attaching it, name it driveX
|
||||||
-drive format=raw,file="${disks[$index]/*=/}",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«
|
if [[ ! ${args[virtio-blk]:-} ]] ; then
|
||||||
#-device ide-hd,drive=drive${index},bus=ahci${index}.${index} # attach IDE?! disk driveX as device X on bus »ahciX«
|
qemu+=( -device ahci,acpi-index=${index},id=ahci${index} ) # create an (ich9-)AHCI bus named »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)
|
qemu+=( -device ide-hd,drive=drive${index},bus=ahci${index}.${index} ) # attach IDE?! disk driveX as device X on bus »ahciX«
|
||||||
)
|
else
|
||||||
|
qemu+=( -device virtio-blk-pci,drive=drive${index},disable-modern=on,disable-legacy=off ) # this should be faster, but seems to require guest drivers
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ ${args[share]:-} ]] ; then # e.g. --share='foo:/home/user/foo,readonly=on bar:/tmp/bar'
|
if [[ ${args[share]:-} ]] ; then # e.g. --share='foo:/home/user/foo,readonly=on bar:/tmp/bar'
|
||||||
@ -144,8 +141,8 @@ function run-qemu { # 1: diskImages, ...: qemuArgs
|
|||||||
if [[ ! -e $disk ]] ; then args[install]=always ; fi
|
if [[ ! -e $disk ]] ; then args[install]=always ; fi
|
||||||
done ; fi
|
done ; fi
|
||||||
if [[ ${args[install]:-} == always ]] ; then
|
if [[ ${args[install]:-} == always ]] ; then
|
||||||
local verbosity=--quiet ; if [[ ${args[debug]:-} ]] ; then verbosity=--debug ; fi
|
local verbosity=--quiet ; if [[ ${args[trace]:-} ]] ; then verbosity=--trace ; fi ; if [[ ${args[debug]:-} ]] ; then verbosity=--debug ; fi
|
||||||
${args[dry-run]:+echo} $0 install-system "$diskImages" $verbosity --no-inspect || return
|
hostPath=${hostPath:-} ${args[dry-run]:+echo} $0 install-system "$diskImages" $verbosity --no-inspect || return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
qemu+=( "${argv[@]}" )
|
qemu+=( "${argv[@]}" )
|
||||||
|
@ -102,3 +102,9 @@ function run-hook-script {( set -eu # 1: title, 2: scriptPath
|
|||||||
fi
|
fi
|
||||||
source "$2"
|
source "$2"
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
## Lazily builds a nix derivation at run time, instead of when building the script.
|
||||||
|
# When maybe-using packages that take long to build, instead of »at{some.package.out}«, use: »$( build-lazy at{some.package.drvPath!unsafeDiscardStringContext} out )«
|
||||||
|
function build-lazy { # 1: drvPath, 2?: output
|
||||||
|
PATH=$PATH:@{native.openssh}/bin @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json ${args[quiet]:+--quiet} $1 | @{native.jq}/bin/jq -r .[0].outputs.${2:-out}
|
||||||
|
}
|
||||||
|
@ -23,10 +23,9 @@ in {
|
|||||||
bashInit = lib.mkEnableOption "pretty defaults for interactive bash shells" // { default = true; example = false; };
|
bashInit = lib.mkEnableOption "pretty defaults for interactive bash shells" // { default = true; example = false; };
|
||||||
}; };
|
}; };
|
||||||
|
|
||||||
# Bugfix:
|
imports = lib.optional ((builtins.substring 0 5 inputs.nixpkgs.lib.version) <= "22.05") (lib.wip.overrideNixpkgsModule "misc/extra-arguments.nix" { } (old: { config._module.args.utils = old._module.args.utils // {
|
||||||
imports = [ (lib.wip.overrideNixpkgsModule "misc/extra-arguments.nix" { } (old: { config._module.args.utils = old._module.args.utils // {
|
escapeSystemdPath = s: let n = builtins.replaceStrings [ "/" "-" " " ] [ "-" "\\x2d" "\\x20" ] (lib.removePrefix "/" s); in if lib.hasPrefix "." n then "\\x2e" (lib.substring 1 (lib.stringLength (n - 1)) n) else n; # (a better implementation has been merged in 22.11)
|
||||||
escapeSystemdPath = s: builtins.replaceStrings [ "/" "-" " " "." ] [ "-" "\\x2d" "\\x20" "\\x2e" ] (lib.removePrefix "/" s); # BUG(PR): The original function does not escape ».«, resulting in mismatching names with units generated from paths with ».« in them (e.g. overwrites for implicit mount units).
|
}; }));
|
||||||
}; })) ];
|
|
||||||
|
|
||||||
config = let
|
config = let
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ in {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if ! ${pkgs.gnugrep}/bin/grep -qP '^UI ' ${esc cfg.targetDir}/extlinux/extlinux.conf ; then # `extlinux-conf-builder` above would have recreated this, so the check should always be true
|
if ! ${pkgs.gnugrep}/bin/grep -qP '^UI ' ${esc cfg.targetDir}/extlinux/extlinux.conf ; then # `extlinux-conf-builder` above would have recreated this, so the check should always be true
|
||||||
${pkgs.perl}/bin/perl -i -pe 's/TIMEOUT/UI menu.c32\nTIMEOUT/' ${esc cfg.targetDir}/extlinux/extlinux.conf
|
${pkgs.gnused}/bin/sed -i 's/^TIMEOUT /UI menu.c32\nTIMEOUT /' ${esc cfg.targetDir}/extlinux/extlinux.conf
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
: # delete library files?
|
: # delete library files?
|
||||||
|
@ -71,18 +71,18 @@ in {
|
|||||||
|
|
||||||
fs.disks.partitioning = let
|
fs.disks.partitioning = let
|
||||||
partition-disk = { name = "partition-disk"; text = lib.wip.extractBashFunction (builtins.readFile lib.wip.setup-scripts.disk) "partition-disk"; };
|
partition-disk = { name = "partition-disk"; text = lib.wip.extractBashFunction (builtins.readFile lib.wip.setup-scripts.disk) "partition-disk"; };
|
||||||
esc = lib.escapeShellArg;
|
esc = lib.escapeShellArg; native = pkgs.buildPackages;
|
||||||
in pkgs.runCommand "partitioning-${config.networking.hostName}" { } ''
|
in pkgs.runCommand "partitioning-${config.networking.hostName}" { } ''
|
||||||
${lib.wip.substituteImplicit { inherit pkgs; scripts = [ partition-disk ]; context = { inherit config; native = pkgs; }; }} # inherit (builtins) trace;
|
${lib.wip.substituteImplicit { inherit pkgs; scripts = [ partition-disk ]; context = { inherit config native; }; }} # inherit (builtins) trace;
|
||||||
set -u ; mkdir -p $out ; declare -A args=([debug]=1)
|
set -u ; mkdir -p $out ; declare -A args=([debug]=1)
|
||||||
${lib.concatStrings (lib.mapAttrsToList (name: disk: ''
|
${lib.concatStrings (lib.mapAttrsToList (name: disk: ''
|
||||||
name=${esc name} ; img=$name.img
|
name=${esc name} ; img=$name.img
|
||||||
${pkgs.coreutils}/bin/truncate -s ${esc disk.size} "$img"
|
${native.coreutils}/bin/truncate -s ${esc disk.size} "$img"
|
||||||
partition-disk "$name" "$img" ${toString (lib.wip.parseSizeSuffix disk.size)}
|
partition-disk "$name" "$img" ${toString (lib.wip.parseSizeSuffix disk.size)}
|
||||||
${pkgs.gptfdisk}/bin/sgdisk --backup=$out/"$name".backup "$img"
|
${native.gptfdisk}/bin/sgdisk --backup=$out/"$name".backup "$img"
|
||||||
${pkgs.gptfdisk}/bin/sgdisk --print "$img" >$out/"$name".gpt
|
${native.gptfdisk}/bin/sgdisk --print "$img" >$out/"$name".gpt
|
||||||
${if disk.mbrParts != null then ''
|
${if disk.mbrParts != null then ''
|
||||||
${pkgs.util-linux}/bin/fdisk --type mbr --list "$img" >$out/"$name".mbr
|
${native.util-linux}/bin/fdisk --type mbr --list "$img" >$out/"$name".mbr
|
||||||
'' else ""}
|
'' else ""}
|
||||||
'') cfg.devices)}
|
'') cfg.devices)}
|
||||||
'';
|
'';
|
||||||
|
@ -29,23 +29,23 @@ nix run .../nixos-config'#'nixosConfigurations.${hostName}.config.system.build.v
|
|||||||
|
|
||||||
```nix
|
```nix
|
||||||
#*/# end of MarkDown, beginning of NixOS module:
|
#*/# end of MarkDown, beginning of NixOS module:
|
||||||
dirname: inputs: { config, pkgs, lib, modulesPath, extendModules, ... }: let inherit (inputs.self) lib; in let
|
dirname: inputs: { config, options, pkgs, lib, modulesPath, extendModules, ... }: let inherit (inputs.self) lib; in let
|
||||||
prefix = inputs.config.prefix;
|
prefix = inputs.config.prefix;
|
||||||
cfg = config.virtualisation.vmVariantExec;
|
cfg = config.virtualisation.vmVariantExec;
|
||||||
in {
|
in let hostModule = {
|
||||||
|
|
||||||
options = { virtualisation.vmVariantExec = lib.mkOption {
|
options = { virtualisation.vmVariantExec = lib.mkOption {
|
||||||
description = lib.mdDoc ''Machine configuration to be added to the system's qemu exec VM.'';
|
description = lib.mdDoc ''Machine configuration to be added to the system's qemu exec VM.'';
|
||||||
inherit (extendModules { modules = [ "${modulesPath}/virtualisation/qemu-vm.nix" ]; }) type;
|
inherit (extendModules { modules = [ "${modulesPath}/virtualisation/qemu-vm.nix" vmModule ]; }) type;
|
||||||
default = { }; visible = "shallow";
|
default = { }; visible = "shallow";
|
||||||
}; };
|
}; };
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
|
||||||
system.build.vmExec = (let vmPkgs = pkgs; in let
|
system.build.vmExec = (let hostPkgs = pkgs; in let
|
||||||
name = "run-${config.system.name}-vm-exec";
|
name = "run-${config.system.name}-vm-exec";
|
||||||
launch = "${cfg.system.build.vm}/bin/${cfg.system.build.vm.meta.mainProgram}";
|
launch = "${cfg.system.build.vm}/bin/${cfg.system.build.vm.meta.mainProgram}";
|
||||||
pkgs = if cfg.virtualisation?host.pkgs then cfg.virtualisation.host.pkgs else vmPkgs;
|
pkgs = if cfg.virtualisation?host.pkgs then cfg.virtualisation.host.pkgs else hostPkgs;
|
||||||
in pkgs.runCommand "nixos-vm" {
|
in pkgs.runCommand "nixos-vm" {
|
||||||
preferLocalBuild = true; meta.mainProgram = name;
|
preferLocalBuild = true; meta.mainProgram = name;
|
||||||
} ''
|
} ''
|
||||||
@ -79,8 +79,11 @@ in {
|
|||||||
''} $out/bin/${name}
|
''} $out/bin/${name}
|
||||||
'');
|
'');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // { virtualisation.vmVariantExec = lib.mkMerge [ ({
|
}; vmModule = { config, ... }: {
|
||||||
|
_file = "${dirname}/vm-exec.nix.md#vmModule";
|
||||||
|
imports = [ ({
|
||||||
|
|
||||||
# Instead of tearing down the initrd environment, adjust some mounts and run the »command« in the initrd:
|
# Instead of tearing down the initrd environment, adjust some mounts and run the »command« in the initrd:
|
||||||
boot.initrd.postMountCommands = ''
|
boot.initrd.postMountCommands = ''
|
||||||
@ -150,9 +153,21 @@ in {
|
|||||||
}; };
|
}; };
|
||||||
virtualisation.diskSize = 4; #MB, not needed at all
|
virtualisation.diskSize = 4; #MB, not needed at all
|
||||||
|
|
||||||
|
}) ({
|
||||||
|
|
||||||
|
virtualisation = if (lib.fileContents "${pkgs.path}/.version") > "22.05" then { host.pkgs = pkgs.buildPackages; } else { };
|
||||||
|
}) ({
|
||||||
|
virtualisation.qemu.package = lib.mkIf (pkgs.buildPackages.system != pkgs.system) cfg.virtualisation.host.pkgs.qemu_full;
|
||||||
|
|
||||||
|
}) ({
|
||||||
|
|
||||||
|
specialisation = lib.mkForce { };
|
||||||
|
services.qemuGuest.enable = lib.mkForce false;
|
||||||
|
|
||||||
# tag this to make clearer what's what
|
# tag this to make clearer what's what
|
||||||
system.nixos.tags = [ "vmExec" ];
|
system.nixos.tags = [ "vmExec" ];
|
||||||
system.build.isVmExec = true;
|
system.build.isVmExec = true;
|
||||||
|
|
||||||
}) ]; };
|
}) ];
|
||||||
}
|
|
||||||
|
}; in hostModule
|
||||||
|
@ -31,8 +31,8 @@ in {
|
|||||||
owner = "sbabic"; repo = pname; rev = "ba7564f5006d09bec51058cf4f5ac90d4dc18b3c"; # 2018-11-18
|
owner = "sbabic"; repo = pname; rev = "ba7564f5006d09bec51058cf4f5ac90d4dc18b3c"; # 2018-11-18
|
||||||
hash = "sha256-6cHkr3s7/2BVXBTn9bUfPFbYAfv9VYh6C9GAbWILNjs=";
|
hash = "sha256-6cHkr3s7/2BVXBTn9bUfPFbYAfv9VYh6C9GAbWILNjs=";
|
||||||
};
|
};
|
||||||
nativeBuildInputs = [ pkgs.cmake ];
|
nativeBuildInputs = [ pkgs.buildPackages.cmake ];
|
||||||
buildInputs = [ pkgs.cmake pkgs.zlib ];
|
buildInputs = [ pkgs.zlib ];
|
||||||
outputs = [ "out" "lib" ];
|
outputs = [ "out" "lib" ];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
@ -35,7 +35,7 @@ in {
|
|||||||
# Creates a (user) env blob for this u-boot by merging »env« over its »defaultEnv«. The resulting file can be flashed to »CONFIG_ENV_OFFSET« to replace the default env.
|
# Creates a (user) env blob for this u-boot by merging »env« over its »defaultEnv«. The resulting file can be flashed to »CONFIG_ENV_OFFSET« to replace the default env.
|
||||||
mkEnv = env: pkgs.runCommandLocal "uboot-env.img" {
|
mkEnv = env: pkgs.runCommandLocal "uboot-env.img" {
|
||||||
env = envTxt (defaultEnv' // env);
|
env = envTxt (defaultEnv' // env);
|
||||||
} "${pkgs.ubootTools}/bin/mkenvimage -p 0x00 -s ${toString envSize} -o $out $env";
|
} "${pkgs.buildPackages.ubootTools}/bin/mkenvimage -p 0x00 -s ${toString envSize} -o $out $env";
|
||||||
|
|
||||||
};
|
};
|
||||||
extraConfig = (old.extraConfig or "") + "${lib.concatStringsSep "\n" ([
|
extraConfig = (old.extraConfig or "") + "${lib.concatStringsSep "\n" ([
|
||||||
|
Loading…
Reference in New Issue
Block a user