From 6af2a6650f81586ee98cb304f7e9e1d264d93f01 Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 14:42:06 +0100 Subject: [PATCH 1/7] init nixos-remote --- nixos-remote | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100755 nixos-remote diff --git a/nixos-remote b/nixos-remote new file mode 100755 index 0000000..58c6d9a --- /dev/null +++ b/nixos-remote @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +set -eufo pipefail +set -x + +showUsage() { + cat <&2 + exit 1 +} + +nix_args=() + +while [[ $# -gt 0 ]]; do + case "$1" in + -f | --flake) + flake=$2 + shift + ;; + --argstr | --arg) + nix_args+=("$1" "$2" "$3") + shift + shift + ;; + --help) + showUsage + exit 0 + ;; + *) + if [ -z ${ssh_connection+x} ]; then + ssh_connection=$1 + else + showUsage + exit 1 + fi + ;; + esac + shift +done + +# ssh wrapper +ssh_() { + ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$@" +} + +# first check if the remote system is kexec booted +# if $(ssh_ "$ssh_connection" -- test -e /etc/is-kexec); then +if $(ssh_ "$ssh_connection" -- test -e /etc/NIXOS); then + is_kexec=y +fi + + +echo ${is_kexec-n} +if [ ${is_kexec-n} != "y" ]; then + # TODO we probably need an architecture detection here + ssh_ "$ssh_connection" << SSH +set -efux +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 +} +rm -rf /root/kexec +mkdir -p /root/kexec +fetch https://github.com/nix-community/nixos-images/releases/download/nixos-22.05/nixos-kexec-installer-x86_64-linux.tar.gz | tar -C /root/kexec -xvzf- +export TMPDIR=/root/kexec +setsid /root/kexec/kexec/run +SSH + # wait for machine to become unreachable + while ssh_ "$ssh_connection" -- exit 0; do sleep 1; done + + # watiting for machine to become available again + until ssh_ -o ConnectTimeout=10 "$ssh_connection" -- exit 0; do sleep 5; done +fi + + +ssh_ "$ssh_connection" << SSH +set -efux +$(declare -p nix_args) +nix --extra-experimental-features nix-command --extra-experimental-features flakes \ + run github:nix-community/disko \ + --no-write-lock-file -- \ + --debug -m create "\${nix_args[@]}" --flake "$flake" + +nix --extra-experimental-features nix-command --extra-experimental-features flakes \ + run github:nix-community/disko \ + --no-write-lock-file -- \ + --debug -m mount "\${nix_args[@]}" --flake "$flake" + +nixos-install --flake "$flake" +reboot +SSH From 5029d6a0fbbbd08572d9bdaacf4f501c44acbe9c Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 15:30:50 +0100 Subject: [PATCH 2/7] add --kexec paramter to specify custom image --- nixos-remote | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nixos-remote b/nixos-remote index 58c6d9a..a14ee60 100755 --- a/nixos-remote +++ b/nixos-remote @@ -14,6 +14,8 @@ Options: pass value to nix-build. can be used to set disk-names for example * --argstr name value pass value to nix-build as string +* --kexec url + use another kexec tarball to bootstrap NixOS USAGE } @@ -23,6 +25,7 @@ abort() { } nix_args=() +kexec_url=https://github.com/nix-community/nixos-images/releases/download/nixos-22.05/nixos-kexec-installer-x86_64-linux.tar.gz while [[ $# -gt 0 ]]; do case "$1" in @@ -39,6 +42,10 @@ while [[ $# -gt 0 ]]; do showUsage exit 0 ;; + --kexec) + kexec_url=$2 + shift + ;; *) if [ -z ${ssh_connection+x} ]; then ssh_connection=$1 @@ -80,7 +87,7 @@ fetch(){ } rm -rf /root/kexec mkdir -p /root/kexec -fetch https://github.com/nix-community/nixos-images/releases/download/nixos-22.05/nixos-kexec-installer-x86_64-linux.tar.gz | tar -C /root/kexec -xvzf- +fetch "$kexec_url" | tar -C /root/kexec -xvzf- export TMPDIR=/root/kexec setsid /root/kexec/kexec/run SSH From 650b6db62c3ed5876e86fa3189e75733d8c8e027 Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 15:31:43 +0100 Subject: [PATCH 3/7] ssh timeout --- nixos-remote | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/nixos-remote b/nixos-remote index a14ee60..7ab72c1 100755 --- a/nixos-remote +++ b/nixos-remote @@ -60,12 +60,11 @@ done # ssh wrapper ssh_() { - ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$@" + timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$ssh_connection" "$@" } # first check if the remote system is kexec booted -# if $(ssh_ "$ssh_connection" -- test -e /etc/is-kexec); then -if $(ssh_ "$ssh_connection" -- test -e /etc/NIXOS); then +if $(ssh_ -- test -e /etc/is-kexec); then is_kexec=y fi @@ -73,7 +72,7 @@ fi echo ${is_kexec-n} if [ ${is_kexec-n} != "y" ]; then # TODO we probably need an architecture detection here - ssh_ "$ssh_connection" << SSH + ssh_ << SSH set -efux fetch(){ if command -v curl >/dev/null 2>&1; then @@ -92,14 +91,14 @@ export TMPDIR=/root/kexec setsid /root/kexec/kexec/run SSH # wait for machine to become unreachable - while ssh_ "$ssh_connection" -- exit 0; do sleep 1; done + while ssh_ -- exit 0; do sleep 1; done # watiting for machine to become available again - until ssh_ -o ConnectTimeout=10 "$ssh_connection" -- exit 0; do sleep 5; done + until ssh_ -o ConnectTimeout=10 -- exit 0; do sleep 5; done fi -ssh_ "$ssh_connection" << SSH +ssh_ << SSH set -efux $(declare -p nix_args) nix --extra-experimental-features nix-command --extra-experimental-features flakes \ From b7c4b74bf91bac74e4139a7419e7b608555b5b1a Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 16:45:14 +0100 Subject: [PATCH 4/7] ssh: use timout only for waiting --- nixos-remote | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nixos-remote b/nixos-remote index 7ab72c1..c0bfb9b 100755 --- a/nixos-remote +++ b/nixos-remote @@ -59,9 +59,12 @@ while [[ $# -gt 0 ]]; do done # ssh wrapper -ssh_() { +timeout_ssh_() { timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$ssh_connection" "$@" } +ssh_() { + ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$ssh_connection" "$@" +} # first check if the remote system is kexec booted if $(ssh_ -- test -e /etc/is-kexec); then @@ -91,7 +94,7 @@ export TMPDIR=/root/kexec setsid /root/kexec/kexec/run SSH # wait for machine to become unreachable - while ssh_ -- exit 0; do sleep 1; done + while timeout_ssh_ -- exit 0; do sleep 1; done # watiting for machine to become available again until ssh_ -o ConnectTimeout=10 -- exit 0; do sleep 5; done From 416390f6dd443cd411f52b9c3fc41e50c5d3e8d6 Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 16:46:53 +0100 Subject: [PATCH 5/7] check if tar exists on target system --- nixos-remote | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nixos-remote b/nixos-remote index c0bfb9b..0ce10ed 100755 --- a/nixos-remote +++ b/nixos-remote @@ -87,6 +87,10 @@ fetch(){ 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 fetch "$kexec_url" | tar -C /root/kexec -xvzf- From ab86ca7927f55f8c1108681bc824e3cbbd16fbbb Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 16:49:56 +0100 Subject: [PATCH 6/7] add minimal README --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ee19f9..636b7c2 100644 --- a/README.md +++ b/README.md @@ -1 +1,8 @@ -# nixos-remote \ No newline at end of file +# nixos-remote - install nixos everywhere via ssh + +## Usage +Needs a repo with your configurations with flakes. for a minimal example checkout https://github.com/Lassulus/flakes-testing. +afterwards you can just run: +``` + ./nixos-remote root@yourip --flake github:your-user/your-repo#your-system +``` From 28809e0ef94444320ee839aed2e81e5dec2832ad Mon Sep 17 00:00:00 2001 From: lassulus Date: Thu, 10 Nov 2022 17:15:00 +0100 Subject: [PATCH 7/7] check target OS --- nixos-remote | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nixos-remote b/nixos-remote index 0ce10ed..3e8b517 100755 --- a/nixos-remote +++ b/nixos-remote @@ -77,6 +77,11 @@ if [ ${is_kexec-n} != "y" ]; then # TODO we probably need an architecture detection here ssh_ << SSH set -efux +os=\$(uname) +if [[ "\$os" != "Linux" ]]; then + echo "This script requires Linux as the operating system, but got \${os}" >&2 + exit 1 +fi fetch(){ if command -v curl >/dev/null 2>&1; then curl --fail -Ss -L "\$1"