mirror of
https://github.com/NiklasGollenstede/nixos-installer.git
synced 2025-08-19 05:05:56 +02:00
upgrade to 22.11, add extlinux & hetzner-vps:
- disable wip.fs.disks.devices.*.gptOffset (patch broken with 22.11), - add wip.bootloader.extlinux, - add wip.hardware.hetzner-vps profile, - fix wip.services.dropbear.socketActivation,
This commit is contained in:
@@ -73,9 +73,9 @@ function gen-key-home-yubikey {( set -eu # 1: usage, 2: serialAndSlotAndUser(as
|
||||
## Generates a reproducible secret by prompting for a pin/password and then challenging slot »$slot« of YubiKey »$serial«.
|
||||
function gen-key-yubikey-pin {( set -eu # 1: usage, 2: serialAndSlot(as »serial:slot«)
|
||||
usage=$1 ; serialAndSlot=$2
|
||||
password=$(prompt-new-password "/ pin as challenge to YubiKey »$serialAndSlot« as key for »@{config.networking.hostName}:$usage«")
|
||||
if [[ ! $password ]] ; then exit 1 ; fi
|
||||
gen-key-yubikey-challenge "$usage" "$serialAndSlot:$password" true "password / pin as key for »@{config.networking.hostName}:$usage«"
|
||||
pin=$( prompt-new-password "/ pin as challenge to YubiKey »$serialAndSlot« as key for »@{config.networking.hostName}:$usage«" )
|
||||
if [[ ! $pin ]] ; then exit 1 ; fi
|
||||
gen-key-yubikey-challenge "$usage" "$serialAndSlot:$pin" true "password / pin as key for »@{config.networking.hostName}:$usage«"
|
||||
)}
|
||||
|
||||
## Generates a reproducible secret for a certain »$use«case and optionally »$salt« on a »$host« by challenging slot »$slot« of YubiKey »$serial«.
|
||||
|
@@ -97,6 +97,7 @@ function partition-disk { # 1: name, 2: blockDev, 3?: devSize
|
||||
|
||||
local -a sgdisk=( --zap-all ) # delete existing part tables
|
||||
if [[ ${disk[gptOffset]} != 0 ]] ; then
|
||||
echo 'Setting »gptOffset != 0« is currently not supported, as sgdisk with the patch applied somehow fails to read files' 1>&2 ; return 1
|
||||
sgdisk+=( --move-main-table=$(( 2 + ${disk[gptOffset]} )) ) # this is incorrectly documented as --adjust-main-table in the man pages (at least versions 1.05 to 1.09 incl)
|
||||
sgdisk+=( --move-backup-table=$(( devSize/${disk[sectorSize]} - 1 - 32 - ${disk[gptOffset]} )) )
|
||||
fi
|
||||
@@ -201,40 +202,37 @@ function fix-grub-install {
|
||||
|
||||
|
||||
## Mounts all file systems as it would happen during boot, but at path prefix »$mnt« (instead of »/«).
|
||||
function mount-system {( set -eu # 1: mnt, 2?: fstabPath
|
||||
# TODO: »config.system.build.fileSystems« is a dependency-sorted list. Could use that ...
|
||||
# mount --all --fstab @{config.system.build.toplevel}/etc/fstab --target-prefix "$1" -o X-mount.mkdir # (»--target-prefix« is not supported on Ubuntu 20.04)
|
||||
mnt=$1 ; fstabPath=${2:-"@{config.system.build.toplevel}/etc/fstab"}
|
||||
function mount-system {( set -eu # 1: mnt, 2?: fstabPath, 3?: allowFail
|
||||
# While not generally required for fstab, nixos uses the dependency-sorted »config.system.build.fileSystems« list (instead of plain »builtins.attrValues config.fileSystems«) to generate »/etc/fstab« (provided »config.fileSystems.*.depends« is set correctly, e.g. for overlay mounts).
|
||||
# This function depends on the file at »fstabPath« to be sorted like that.
|
||||
|
||||
# The following is roughly equivalent to: mount --all --fstab @{config.system.build.toplevel}/etc/fstab --target-prefix "$1" -o X-mount.mkdir # (but »--target-prefix« is not supported with older versions on »mount«, e.g. on Ubuntu 20.04 (but can't we use mount from nixpkgs?))
|
||||
mnt=$1 ; fstabPath=${2:-"@{config.system.build.toplevel}/etc/fstab"} ; allowFail=${3:-}
|
||||
PATH=@{native.e2fsprogs}/bin:@{native.f2fs-tools}/bin:@{native.xfsprogs}/bin:@{native.dosfstools}/bin:$PATH
|
||||
<$fstabPath grep -v '^#' | LC_ALL=C sort -k2 | while read source target type options numbers ; do
|
||||
|
||||
<$fstabPath grep -v '^#' | while read source target type options numbers ; do
|
||||
if [[ ! $target || $target == none ]] ; then continue ; fi
|
||||
options=,$options, ; options=${options//,ro,/,}
|
||||
if [[ $options =~ ,r?bind, ]] || [[ $type == overlay ]] ; then continue ; fi
|
||||
|
||||
if ! mountpoint -q "$mnt"/"$target" ; then (
|
||||
mkdir -p "$mnt"/"$target" || exit
|
||||
[[ $type == tmpfs || $type == */* ]] || @{native.kmod}/bin/modprobe --quiet $type || true # (this does help sometimes)
|
||||
mount -t $type -o "${options:1:(-1)}" "$source" "$mnt"/"$target" || exit
|
||||
) || [[ $options == *,nofail,* ]] || exit ; fi # (actually, nofail already makes mount fail silently)
|
||||
done || exit
|
||||
# Since bind mounts may depend on other mounts not only for the target (which the sort takes care of) but also for the source, do all bind mounts last. This would break if there was a different bind mountpoint within a bind-mounted target.
|
||||
<$fstabPath grep -v '^#' | LC_ALL=C sort -k2 | while read source target type options numbers ; do
|
||||
if [[ ! $target || $target == none ]] ; then continue ; fi
|
||||
options=,$options, ; options=${options//,ro,/,}
|
||||
if [[ $options =~ ,r?bind, ]] || [[ $type == overlay ]] ; then : ; else continue ; fi
|
||||
if ! mountpoint -q "$mnt"/"$target" ; then (
|
||||
mkdir -p "$mnt"/"$target" || exit
|
||||
|
||||
if [[ $type == overlay ]] ; then
|
||||
options=${options//,workdir=/,workdir=$mnt\/} ; options=${options//,upperdir=/,upperdir=$mnt\/} # Work and upper dirs must be in target.
|
||||
workdir=$(<<<"$options" grep -o -P ',workdir=\K[^,]+' || true) ; if [[ $workdir ]] ; then mkdir -p "$workdir" ; fi
|
||||
upperdir=$(<<<"$options" grep -o -P ',upperdir=\K[^,]+' || true) ; if [[ $upperdir ]] ; then mkdir -p "$upperdir" ; fi
|
||||
lowerdir=$(<<<"$options" grep -o -P ',lowerdir=\K[^,]+' || true) # TODO: test the lowerdir stuff
|
||||
workdir=$( <<<"$options" grep -o -P ',workdir=\K[^,]+' || true ) ; if [[ $workdir ]] ; then mkdir -p "$workdir" ; fi
|
||||
upperdir=$( <<<"$options" grep -o -P ',upperdir=\K[^,]+' || true ) ; if [[ $upperdir ]] ; then mkdir -p "$upperdir" ; fi
|
||||
lowerdir=$( <<<"$options" grep -o -P ',lowerdir=\K[^,]+' || true )
|
||||
options=${options//,lowerdir=$lowerdir,/,lowerdir=$mnt/${lowerdir//:/:$mnt\/},} ; source=overlay
|
||||
else
|
||||
# TODO: test the lowerdir stuff
|
||||
elif [[ $options =~ ,r?bind, ]] ; then
|
||||
if [[ $source == /nix/store/* ]] ; then options=,ro$options ; fi
|
||||
source=$mnt/$source ; if [[ ! -e $source ]] ; then mkdir -p "$source" || exit ; fi
|
||||
fi
|
||||
|
||||
mount -t $type -o "${options:1:(-1)}" "$source" "$mnt"/"$target" || exit
|
||||
) || [[ $options == *,nofail,* ]] || exit ; fi
|
||||
|
||||
) || [[ $options == *,nofail,* || $allowFail ]] || exit ; fi # (actually, nofail already makes mount fail silently)
|
||||
done || exit
|
||||
)}
|
||||
|
||||
|
@@ -77,10 +77,10 @@ function install-system-to {( set -u # 1: mnt
|
||||
chmod -R u+w $mnt/@{config.environment.etc.nixos.source} || exit
|
||||
fi
|
||||
|
||||
# Set this as the initial system generation:
|
||||
# Set this as the initial system generation (just in case »nixos-install-cmd« won't):
|
||||
mkdir -p -m 755 $mnt/nix/var/nix/profiles || exit
|
||||
ln -sT $(realpath $targetSystem) $mnt/nix/var/nix/profiles/system-1-link || exit
|
||||
ln -sT system-1-link $mnt/nix/var/nix/profiles/system || exit
|
||||
[[ -e $mnt/nix/var/nix/profiles/system-1-link ]] || ln -sT $(realpath $targetSystem) $mnt/nix/var/nix/profiles/system-1-link || exit
|
||||
[[ -e $mnt/nix/var/nix/profiles/system ]] || ln -sT system-1-link $mnt/nix/var/nix/profiles/system || exit
|
||||
|
||||
# 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
|
||||
@@ -91,7 +91,7 @@ function install-system-to {( set -u # 1: mnt
|
||||
# Copy system closure to new nix store:
|
||||
if [[ ${SUDO_USER:-} ]] ; then chown -R $SUDO_USER: $mnt/nix/store $mnt/nix/var || exit ; fi
|
||||
( cmd=( nix --extra-experimental-features nix-command --offline copy --no-check-sigs --to $mnt ${topLevel:-$targetSystem} ) ; if [[ ${args[quiet]:-} ]] ; then "${cmd[@]}" --quiet &>/dev/null || exit ; else set -x ; time "${cmd[@]}" || exit ; fi ) || exit ; rm -rf $mnt/nix/var/nix/gcroots || exit
|
||||
# TODO: if the target has @{config.nix.autoOptimiseStore} and the host doesn't (there is no .links dir?), optimize now
|
||||
# TODO: if the target has @{config.nix.settings.auto-optimise-store} and the host doesn't (there is no .links dir?), optimize now
|
||||
if [[ ${SUDO_USER:-} ]] ; then chown -R root:root $mnt/nix $mnt/nix/var || exit ; chown :30000 $mnt/nix/store || exit ; fi
|
||||
|
||||
# Run the main install command (primarily for the bootloader):
|
||||
|
@@ -18,6 +18,7 @@ function register-vbox {( set -eu # 1: diskImages, 2?: bridgeTo
|
||||
diskImage=${decl/*=/}
|
||||
if [[ ! -e $diskImage.vmdk ]] ; then
|
||||
$VBoxManage internalcommands createrawvmdk -filename $diskImage.vmdk -rawdisk $diskImage # pass-through
|
||||
#VBoxManage convertfromraw --format VDI $diskImage $diskImage.vmdk && rm $diskImage # convert
|
||||
fi
|
||||
$VBoxManage storageattach "$vmName" --storagectl SATA --port $(( index++ )) --device 0 --type hdd --medium $diskImage.vmdk
|
||||
done
|
||||
@@ -133,56 +134,57 @@ function add-bootkey-to-keydev {( set -eu # 1: blockDev, 2?: hostHash
|
||||
# See »open-system«'s implementation for some example calls to this function.
|
||||
function mount-keystore-luks { # ...: cryptsetupOptions
|
||||
# (For the traps to work, this can't run in a sub shell. The function therefore can't use »( set -eu ; ... )« internally and instead has to use »&&« after every command and in place of most »;«, and the function can't be called from a pipeline.)
|
||||
keystore=keystore-@{config.networking.hostName!hashString.sha256:0:8} &&
|
||||
mkdir -p -- /run/$keystore &&
|
||||
@{native.cryptsetup}/bin/cryptsetup open "$@" /dev/disk/by-partlabel/$keystore $keystore &&
|
||||
mount -o nodev,umask=0077,fmask=0077,dmask=0077,ro /dev/mapper/$keystore /run/$keystore &&
|
||||
prepend_trap "umount /run/$keystore ; @{native.cryptsetup}/bin/cryptsetup close $keystore ; rmdir /run/$keystore" EXIT
|
||||
local keystore=keystore-@{config.networking.hostName!hashString.sha256:0:8}
|
||||
mkdir -p -- /run/$keystore && prepend_trap "[[ ! -e /run/$keystore ]] || rmdir /run/$keystore" EXIT || return
|
||||
@{native.cryptsetup}/bin/cryptsetup open "$@" /dev/disk/by-partlabel/$keystore $keystore && prepend_trap "@{native.cryptsetup}/bin/cryptsetup close $keystore" EXIT || return
|
||||
mount -o nodev,umask=0077,fmask=0077,dmask=0077,ro /dev/mapper/$keystore /run/$keystore && prepend_trap "umount /run/$keystore" EXIT || return
|
||||
}
|
||||
|
||||
## Performs any steps necessary to mount the target system at »/tmp/nixos-install-@{config.networking.hostName}« on the current host.
|
||||
# For any steps taken, it also adds the reaps to undo them on exit from the calling shell, and it always adds the exit trap to do the unmounting itself.
|
||||
# For any steps taken, it also adds the steps to undo them on exit from the calling shell, and it always adds the exit trap to do the unmounting itself.
|
||||
# »diskImages« may be passed in the same format as to the installer. If so, any image files are ensured to be loop-mounted.
|
||||
# Perfect to inspect/update/amend/repair a system's installation afterwards, e.g.:
|
||||
# $ source ${config_wip_fs_disks_initSystemCommands1writeText_initSystemCommands}
|
||||
# $ source ${config_wip_fs_disks_restoreSystemCommands1writeText_restoreSystemCommands}
|
||||
# $ install-system-to /tmp/nixos-install-${config_networking_hostName}
|
||||
# $ nixos-enter --root /tmp/nixos-install-${config_networking_hostName}
|
||||
# $ install-system-to $mnt
|
||||
# $ nixos-install --system ${config_system_build_toplevel} --no-root-passwd --no-channel-copy --root $mnt
|
||||
# $ nixos-enter --root $mnt
|
||||
function open-system { # 1?: diskImages
|
||||
# (for the traps to work, this can't run in a sub shell, so also can't »set -eu«, so use »&&« after every command and in place of most »;«)
|
||||
|
||||
local diskImages=${1:-} # If »diskImages« were specified and they point at files that aren't loop-mounted yet, then loop-mount them now:
|
||||
local images=$( losetup --list --all --raw --noheadings --output BACK-FILE )
|
||||
local decl && for decl in ${diskImages//:/ } ; do
|
||||
local image=${decl/*=/} && if [[ $image != /dev/* ]] && ! <<<$images grep -xF $image ; then
|
||||
local blockDev=$( losetup --show -f "$image" ) && prepend_trap "losetup -d '$blockDev'" EXIT &&
|
||||
@{native.parted}/bin/partprobe "$blockDev" &&
|
||||
:;fi &&
|
||||
:;done &&
|
||||
( @{native.systemd}/bin/udevadm settle -t 15 || true ) && # sometimes partitions aren't quite made available yet
|
||||
local decl ; for decl in ${diskImages//:/ } ; do
|
||||
local image=${decl/*=/} ; if [[ $image != /dev/* ]] && ! <<<$images grep -xF $image ; then
|
||||
local blockDev=$( losetup --show -f "$image" ) && prepend_trap "losetup -d '$blockDev'" EXIT || return
|
||||
@{native.parted}/bin/partprobe "$blockDev" || return
|
||||
|
||||
fi
|
||||
done
|
||||
@{native.systemd}/bin/udevadm settle -t 15 || true # sometimes partitions aren't quite made available yet
|
||||
|
||||
if [[ @{config.wip.fs.keystore.enable} && ! -e /dev/mapper/keystore-@{config.networking.hostName!hashString.sha256:0:8} ]] ; then # Try a bunch of approaches for opening the keystore:
|
||||
mount-keystore-luks --key-file=<( printf %s "@{config.networking.hostName}" ) ||
|
||||
mount-keystore-luks --key-file=/dev/disk/by-partlabel/bootkey-@{config.networking.hostName!hashString.sha256:0:8} ||
|
||||
mount-keystore-luks --key-file=<( read -s -p PIN: pin && echo ' touch!' >&2 && ykchalresp -2 "$pin" ) ||
|
||||
# TODO: try static yubikey challenge
|
||||
mount-keystore-luks
|
||||
fi &&
|
||||
mount-keystore-luks || return
|
||||
fi
|
||||
|
||||
local mnt=/tmp/nixos-install-@{config.networking.hostName} && if [[ ! -e $mnt ]] ; then mkdir -p "$mnt" && prepend_trap "rmdir '$mnt'" EXIT ; fi &&
|
||||
mnt=/tmp/nixos-install-@{config.networking.hostName} # allow this to leak into the calling scope
|
||||
if [[ ! -e $mnt ]] ; then mkdir -p "$mnt" && prepend_trap "rmdir '$mnt'" EXIT || return ; fi
|
||||
|
||||
open-luks-layers && # Load crypt layers and zfs pools:
|
||||
open-luks-layers || return # Load crypt layers and zfs pools:
|
||||
if [[ $( LC_ALL=C type -t ensure-datasets ) == 'function' ]] ; then
|
||||
local poolName && for poolName in "@{!config.wip.fs.zfs.pools[@]}" ; do
|
||||
local poolName ; for poolName in "@{!config.wip.fs.zfs.pools[@]}" ; do
|
||||
if ! zfs get -o value -H name "$poolName" &>/dev/null ; then
|
||||
zpool import -f -N -R "$mnt" "$poolName" && prepend_trap "zpool export '$poolName'" EXIT &&
|
||||
:;fi &&
|
||||
: | zfs load-key -r "$poolName" || true &&
|
||||
:;done &&
|
||||
ensure-datasets "$mnt" &&
|
||||
:;fi &&
|
||||
zpool import -f -N -R "$mnt" "$poolName" ; prepend_trap "zpool export '$poolName'" EXIT || return
|
||||
fi
|
||||
: | zfs load-key -r "$poolName" || true
|
||||
done
|
||||
ensure-datasets "$mnt" || return
|
||||
fi
|
||||
|
||||
prepend_trap "unmount-system '$mnt'" EXIT && mount-system "$mnt" &&
|
||||
|
||||
true # (success)
|
||||
prepend_trap "unmount-system '$mnt'" EXIT && mount-system "$mnt" '' 1 || return
|
||||
df -h | grep $mnt | cat
|
||||
}
|
||||
|
@@ -32,10 +32,11 @@ function create-zpool { # 1: mnt, 2: poolName
|
||||
fi
|
||||
done
|
||||
<$keySrc tr -dc 0-9a-f | head -c 64 | ( PATH=@{native.zfs}/bin ; ${_set_x:-:} ; zpool create "${args[@]}" -R "$mnt" "${pool[name]}" "${vdevs[@]}" || exit ) || exit
|
||||
@{native.zfs}/bin/zfs unload-key "$poolName" &>/dev/null || true
|
||||
if [[ $keySrc == /dev/urandom ]] ; then @{native.zfs}/bin/zfs unload-key "$poolName" &>/dev/null ; fi
|
||||
) || return
|
||||
prepend_trap "@{native.zfs}/bin/zpool export '$poolName'" EXIT || return
|
||||
ensure-datasets $mnt '^'"$poolName"'($|[/])' || return
|
||||
if [[ ${args[debug]:-} ]] ; then @{native.zfs}/bin/zfs list -o name,canmount,mounted,mountpoint,keystatus,encryptionroot -r "$poolName" ; fi
|
||||
}
|
||||
|
||||
## Ensures that the system's datasets exist and have the defined properties (but not that they don't have properties that aren't defined).
|
||||
|
Reference in New Issue
Block a user