-
-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathnixos-deploy.sh
executable file
·133 lines (109 loc) · 3.38 KB
/
nixos-deploy.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/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"