nixos-anywhere/nixos-remote

185 lines
4.5 KiB
Plaintext
Raw Normal View History

2022-11-10 16:42:06 +03:00
#!/usr/bin/env bash
set -eufo pipefail
showUsage() {
cat <<USAGE
Usage: nixos-remote [options] ssh-host
2022-11-10 16:42:06 +03:00
Options:
* -f, --flake flake
set the flake to install the system from
2022-12-07 18:06:02 +03:00
* -s, --store-paths
set the store paths to the disko-script and nixos-system directly
if this is give, flake is not needed
2022-12-07 18:06:20 +03:00
* --no-ssh-copy
skip copying ssh-keys to target system
* --kexec url
use another kexec tarball to bootstrap NixOS
* --debug
enable debug output
2022-11-10 16:42:06 +03:00
USAGE
}
abort() {
echo "aborted: $*" >&2
exit 1
}
kexec_url=https://github.com/nix-community/nixos-images/releases/download/nixos-22.05/nixos-kexec-installer-x86_64-linux.tar.gz
2022-11-10 16:42:06 +03:00
while [[ $# -gt 0 ]]; do
case "$1" in
-f | --flake)
flake=$2
shift
;;
2022-12-07 18:06:02 +03:00
-s | --store-paths)
disko_script=$2
nixos_system=$3
shift
shift
;;
2022-11-10 16:42:06 +03:00
--help)
showUsage
exit 0
;;
--kexec)
kexec_url=$2
shift
;;
--no-ssh-copy-id)
no_ssh_copy=y
;;
--debug)
set -x
;;
2022-11-10 16:42:06 +03:00
*)
if [ -z ${ssh_connection+x} ]; then
2022-12-09 14:39:20 +03:00
if [[ "$1" =~ ^ssh:// ]]; then
ssh_connection=$1
else
ssh_connection="ssh://$1"
fi
2022-11-10 16:42:06 +03:00
else
showUsage
exit 1
fi
;;
esac
shift
done
# ssh wrapper
2022-11-10 18:45:14 +03:00
timeout_ssh_() {
2022-11-10 17:31:43 +03:00
timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$ssh_connection" "$@"
2022-11-10 16:42:06 +03:00
}
2022-11-10 18:45:14 +03:00
ssh_() {
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$ssh_connection" "$@"
}
nixCopy() {
NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix copy --extra-experimental-features nix-command "$@"
}
nix_build() {
nix \
--experimental-features flakes build \
--extra-experimental-features nix-command \
--no-write-lock-file \
--print-out-paths \
"$@"
}
# parse flake nixos-install style syntax, get the system attr
if [[ ! -z "${flake+x}" ]]; then
if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
flake="${BASH_REMATCH[1]}"
flakeAttr="${BASH_REMATCH[2]}"
fi
if [[ -z "$flakeAttr" ]]; then
echo "Please specify the name of the NixOS configuration to be installed, as a URI fragment in the flake-uri."
echo "For example, to use the output nixosConfigurations.foo from the flake.nix, append \"#foo\" to the flake-uri."
exit 1
fi
disko_script=$(nix_build "${flake}#nixosConfigurations.${flakeAttr}.config.system.build.disko")
nixos_system=$(nix_build "${flake}#nixosConfigurations.${flakeAttr}.config.system.build.toplevel")
2022-12-07 18:06:02 +03:00
elif [[ ! -z "${disko_script+x}" ]] && [[ ! -z "${nixos_system+x}" ]]; then
if [[ ! -e "${disko_script}" ]] || [[ ! -e "${nixos_system}" ]]; then
echo "${disko_script} and ${nixos_system} must be existing store-paths"
exit 1
fi
:
else
abort "flake must be set"
fi
# wait for machine to become reachable (possibly forever)
if [ ${no_ssh_copy-n} != "y" ]; then
until ssh-copy-id -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$ssh_connection"; do sleep 5; done
else
until ssh_ -o ConnectTimeout=10 -- exit 0; do sleep 5; done
fi
2022-11-10 16:42:06 +03:00
# first check if the remote system is kexec booted
2022-11-12 13:47:10 +03:00
if $(ssh_ -- test -e /etc/is_kexec); then
2022-11-10 16:42:06 +03:00
is_kexec=y
fi
if [ ${is_kexec-n} != "y" ]; then
# TODO we probably need an architecture detection here
2022-11-10 17:31:43 +03:00
ssh_ << SSH
2022-11-10 16:42:06 +03:00
set -efux
2022-11-10 19:15:00 +03:00
os=\$(uname)
if [[ "\$os" != "Linux" ]]; then
echo "This script requires Linux as the operating system, but got \${os}" >&2
exit 1
fi
if ! command -v tar >/dev/null 2>&1; then
echo "no tar command found, but required to unpack kexec tarball" >&2
exit 1
fi
rm -rf /root/kexec
mkdir -p /root/kexec
SSH
if [[ -e "$kexec_url" ]]; then
cat "$kexec_url" | ssh_ 'tar -C /root/kexec -xvzf-'
else
ssh_ << SSH
2022-11-10 16:42:06 +03:00
fetch(){
if command -v curl >/dev/null 2>&1; then
curl --fail -Ss -L "\$1"
elif command -v wget >/dev/null 2>&1; then
wget "\$1" -O-
else
echo "no downloader (curl or wget) found, bailing out"
exit 1
fi
}
fetch "$kexec_url" | tar -C /root/kexec -xvzf-
SSH
2022-11-10 18:46:53 +03:00
fi
2022-11-12 13:47:17 +03:00
ssh_ << SSH
2022-11-10 16:42:06 +03:00
export TMPDIR=/root/kexec
setsid /root/kexec/kexec/run
SSH
2022-11-10 16:42:06 +03:00
# wait for machine to become unreachable
2022-11-10 18:45:14 +03:00
while timeout_ssh_ -- exit 0; do sleep 1; done
2022-11-10 16:42:06 +03:00
# watiting for machine to become available again
2022-11-10 17:31:43 +03:00
until ssh_ -o ConnectTimeout=10 -- exit 0; do sleep 5; done
2022-11-10 16:42:06 +03:00
fi
2022-12-09 14:39:20 +03:00
nixCopy --to "$ssh_connection" "$disko_script"
ssh_ $disko_script
2022-11-10 16:42:06 +03:00
2022-12-09 14:39:20 +03:00
nixCopy --to "$ssh_connection?remote-store=local?root=/mnt" "$nixos_system"
2022-11-10 17:31:43 +03:00
ssh_ << SSH
set -efu
nixos-install --no-root-passwd --no-channel-copy --system "$nixos_system"
2022-11-10 16:42:06 +03:00
reboot
SSH