Created
August 14, 2020 23:04
-
-
Save lovesegfault/36130da3ef78054aba146f797eb696bb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/nix/store/z4ajipns0l1s8b2lrgpy6nng4cys7h99-bash-4.4-p23/bin/bash | |
PATH=/nix/store/z4ajipns0l1s8b2lrgpy6nng4cys7h99-bash-4.4-p23/bin:/nix/store/hzvl3dvv8651iqlb5g6gq5hzjzmhjn7m-coreutils-8.31/bin:/nix/store/rphcpivxfm4blw36ki262yrmqygw9pcp-findutils-4.7.0/bin:/nix/store/9k90a16frvqdcxzkhxcjsi2qczv3i4x4-gnused-4.8/bin:/nix/store/zckg7fafpkpmdhgajyalakirlw88k1jz-jq-1.6-bin/bin:/nix/store/83f38s2vp9nlkh3akilbhw2869xy0b9l-nix-2.3.3/bin:/nix/store/ban4jcddacl71ld8axbnlnlh5gr0712q-openssh-8.2p1/bin:/nix/store/nz8baf2s4wygv1nc6pybb7dc5wn3yw8f-procps-3.3.16/bin:/nix/store/308x65jfhxxybjwp46492y6zqqw2z2b8-rsync-3.1.3/bin | |
set -euo pipefail | |
# Kill all child processes when interrupting/exiting | |
trap exit INT TERM | |
trap 'for pid in $(jobs -p) ; do kill -- -$pid ; done' EXIT | |
# Be sure to use --foreground for all timeouts, therwise a Ctrl-C won't stop them! | |
# See https://unix.stackexchange.com/a/233685/214651 | |
# Prefix all output with host name | |
# From https://unix.stackexchange.com/a/440439/214651 | |
exec > >(sed "s/^/[fourier] /") | |
exec 2> >(sed "s/^/[fourier] /" >&2) | |
HOST=10.0.0.10 | |
echo "Connecting to host..." >&2 | |
if ! OLDSYSTEM=$(timeout --foreground 30 \ | |
ssh -o ControlPath=none -o BatchMode=yes "$HOST" realpath /run/current-system\ | |
); then | |
echo "Unable to connect to host!" >&2 | |
exit 1 | |
fi | |
if [ "$OLDSYSTEM" == "/nix/store/hawq17bn59yif121cq71x115ambykpas-nixos-system-fourier-20.09pre-git" ]; then | |
echo "No deploy necessary" >&2 | |
#exit 0 | |
fi | |
# ======== PHASE: copy-closure ======== | |
echo "Copying closure to host..." >&2 | |
# TOOD: Prevent garbage collection until the end of the deploy | |
tries=3 | |
while [ "$tries" -ne 0 ] && | |
! NIX_SSH_OPTS="-o ServerAliveInterval=15" nix-copy-closure --to "$HOST" '/nix/store/hawq17bn59yif121cq71x115ambykpas-nixos-system-fourier-20.09pre-git' '/nix/store/xyrzxnwhnw3gx2hr1lqy0jgb8nja0f2r-switch'; do | |
tries=$(( $tries - 1 )) | |
echo "Failed to copy closure, $tries tries left" | |
done | |
# ======== PHASE: secrets ======== | |
echo "Copying secrets..." >&2 | |
ssh "$HOST" sudo mkdir -p -m 755 /var/lib/nixus-secrets/pending/per-{user,group} | |
# TODO: I don't think this works if rsync isn't on the remote's shell. | |
# We really just need a single binary we can execute on the remote, like the switch script | |
rsync --perms --chmod=440 --rsync-path="sudo rsync" "/nix/store/28c9aghrlqgsrk3nf2qipcqzklqgp127-required-secrets" "$HOST:/var/lib/nixus-secrets/pending/included-secrets" | |
while read -r json; do | |
name=$(echo "$json" | jq -r '.name') | |
source=$(echo "$json" | jq -r '.source') | |
user=$(echo "$json" | jq -r '.user') | |
group=$(echo "$json" | jq -r '.group') | |
echo "Copying secret $name..." >&2 | |
# If this is a per-user secret | |
if [[ "$user" != null ]]; then | |
# The -n is very important for ssh to not swallow stdin! | |
ssh -n "$HOST" sudo mkdir -p -m 500 "/var/lib/nixus-secrets/pending/per-user/$user" | |
rsync --perms --chmod=400 --rsync-path="sudo rsync" "$source" "$HOST:/var/lib/nixus-secrets/pending/per-user/$user/$name" | |
else | |
ssh -n "$HOST" sudo mkdir -p -m 050 "/var/lib/nixus-secrets/pending/per-group/$group" | |
rsync --perms --chmod=040 --rsync-path="sudo rsync" "$source" "$HOST:/var/lib/nixus-secrets/pending/per-group/$group/$name" | |
fi | |
done < "/nix/store/28c9aghrlqgsrk3nf2qipcqzklqgp127-required-secrets" | |
echo "Finished copying secrets" >&2 | |
# ======== PHASE: switch ======== | |
echo "Triggering system switcher..." >&2 | |
id=$(ssh -o BatchMode=yes "$HOST" exec "/nix/store/xyrzxnwhnw3gx2hr1lqy0jgb8nja0f2r-switch/bin/switch" start "/nix/store/hawq17bn59yif121cq71x115ambykpas-nixos-system-fourier-20.09pre-git") | |
echo "Trying to confirm success..." >&2 | |
active=1 | |
while [ "$active" != 0 ]; do | |
# TODO: Because of the imperative network-setup script, when e.g. the | |
# defaultGateway is removed, the previous entry is still persisted on | |
# a rebuild switch, even though with a reboot it wouldn't. Maybe use | |
# the more modern and declarative networkd to get around this | |
set +e | |
status=$(timeout --foreground 15 ssh -o ControlPath=none -o BatchMode=yes "$HOST" exec "/nix/store/xyrzxnwhnw3gx2hr1lqy0jgb8nja0f2r-switch/bin/switch" active "$id") | |
active=$? | |
set -e | |
sleep 1 | |
done | |
case "$status" in | |
"success") | |
echo "Successfully activated new system!" >&2 | |
;; | |
"failure") | |
echo "Failed to activate new system! Rolled back to previous one" >&2 | |
echo "Run the following command to see the logs for the switch:" >&2 | |
echo "ssh ${HOST@Q} sudo cat /var/lib/system-switcher/system-$id/log" >&2 | |
# TODO: Try to better show what failed | |
;; | |
*) | |
echo "This shouldn't occur, the status is $status!" >&2 | |
;; | |
esac | |
echo "Finished" >&2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment