Fediversity/launch/.terraform/modules/peertube.deploy/deploy_nixos/nixos-deploy.sh

133 lines
3.4 KiB
Bash
Executable file

#!/usr/bin/env bash
# nixos-deploy deploys a nixos-instantiate-generated drvPath to a target host
#
# Usage: nixos-deploy.sh <drvPath> <host> <switch-action> [<build-opts>] ignoreme
set -euo pipefail
### Defaults ###
buildArgs=(
--option extra-binary-caches https://cache.nixos.org/
)
profile=/nix/var/nix/profiles/system
# will be set later
sshOpts=(
-o "ControlMaster=auto"
-o "ControlPersist=60"
# Avoid issues with IP re-use. This disable TOFU security.
-o "StrictHostKeyChecking=no"
-o "UserKnownHostsFile=/dev/null"
-o "GlobalKnownHostsFile=/dev/null"
# interactive authentication is not possible
-o "BatchMode=yes"
# verbose output for easier debugging
-v
)
### Argument parsing ###
drvPath="$1"
outPath="$2"
targetHost="$3"
targetPort="$4"
buildOnTarget="$5"
sshPrivateKey="$6"
action="$7"
deleteOlderThan="$8"
shift 8
# remove the last argument
set -- "${@:1:$(($# - 1))}"
buildArgs+=("$@")
sshOpts+=( -p "${targetPort}" )
workDir=$(mktemp -d)
trap 'rm -rf "$workDir"' EXIT
if [[ -n "${sshPrivateKey}" && "${sshPrivateKey}" != "-" ]]; then
sshPrivateKeyFile="$workDir/ssh_key"
echo "$sshPrivateKey" > "$sshPrivateKeyFile"
chmod 0700 "$sshPrivateKeyFile"
sshOpts+=( -o "IdentityFile=${sshPrivateKeyFile}" )
fi
### Functions ###
log() {
echo "--- $*" >&2
}
copyToTarget() {
NIX_SSHOPTS="${sshOpts[*]}" nix-copy-closure --to "$targetHost" "$@"
}
# assumes that passwordless sudo is enabled on the server
targetHostCmd() {
# ${*@Q} escapes the arguments losslessly into space-separted quoted strings.
# `ssh` did not properly maintain the array nature of the command line,
# erroneously splitting arguments with internal spaces, even when using `--`.
# Tested with OpenSSH_7.9p1.
#
# shellcheck disable=SC2029
ssh "${sshOpts[@]}" "$targetHost" "./maybe-sudo.sh ${*@Q}"
}
# Setup a temporary ControlPath for this session. This speeds-up the
# operations by not re-creating SSH sessions between each command. At the end
# of the run, the session is forcefully terminated.
setupControlPath() {
sshOpts+=(
-o "ControlPath=$workDir/ssh_control"
)
cleanupControlPath() {
local ret=$?
# Avoid failing during the shutdown
set +e
# Close ssh multiplex-master process gracefully
log "closing persistent ssh-connection"
ssh "${sshOpts[@]}" -O stop "$targetHost"
rm -rf "$workDir"
exit "$ret"
}
trap cleanupControlPath EXIT
}
### Main ###
setupControlPath
if [[ "${buildOnTarget:-false}" == true ]]; then
# Upload derivation
log "uploading derivations"
copyToTarget "$drvPath" --gzip --use-substitutes
# Build remotely
log "building on target"
set -x
targetHostCmd "nix-store" "--realize" "$drvPath" "${buildArgs[@]}"
else
# Build derivation
log "building on deployer"
outPath=$(nix-store --realize "$drvPath" "${buildArgs[@]}")
# Upload build results
log "uploading build results"
copyToTarget "$outPath" --gzip --use-substitutes
fi
# Activate
log "activating configuration"
targetHostCmd nix-env --profile "$profile" --set "$outPath"
targetHostCmd "$outPath/bin/switch-to-configuration" "$action"
# Cleanup previous generations
log "collecting old nix derivations"
# Deliberately not quoting $deleteOlderThan so the user can configure something like "1 2 3"
# to keep generations with those numbers
targetHostCmd "nix-env" "--profile" "$profile" "--delete-generations" $deleteOlderThan
targetHostCmd "nix-store" "--gc"