forked from nix-community/disko
-
Notifications
You must be signed in to change notification settings - Fork 0
/
disko-install
executable file
·246 lines (220 loc) · 6.55 KB
/
disko-install
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#!/usr/bin/env bash
set -euo pipefail
showUsage() {
cat <<EOF
Usage: $0 [OPTIONS]
--mode MODE Specify the mode of operation. Valid modes are: format, mount.
Format will format the disk before installing.
Mount will mount the disk before installing.
Mount is useful for updating an existing system without losing data.
-f, --flake FLAKE_URI#ATTR Use the specified flake to install the NixOS configuration.
--disk NAME DEVICE Map the specified disk name to the specified device path.
--dry-run Print the commands that would be run, but do not run them.
--show-trace Show the stack trace on error.
-h, --help Show this help message.
--extra-files SOURCE DEST Copy the specified file or directory from the host into the NixOS configuration.
--option NAME VALUE Pass the specified option to Nix.
--write-efi-boot-entries Write EFI boot entries to the NVRAM of the system for the installed system.
Specify this option if you plan to boot from this disk on the current machine,
but not if you plan to move the disk to another machine.
--system-config JSON Merges the specified JSON object into the NixOS configuration.
EOF
}
serialiaseArrayToNix() {
local -n array=$1
nixExpr="{ "
# Iterate over the associative array to populate the Nix attrset string
for key in "${!array[@]}"; do
value=${array[$key]}
nixExpr+="\"${key//\"/\\\"}\" = \"${value//\"/\\\"}\"; "
done
nixExpr+="}"
echo "$nixExpr"
}
readonly libexec_dir="${0%/*}"
nix_args=(
--extra-experimental-features 'nix-command flakes'
"--option" "no-write-lock-file" "true"
)
dry_run=
extraSystemConfig="{}"
diskoAttr=diskoScript
writeEfiBootEntries=false
declare -A diskMappings
declare -A extraFiles
parseArgs() {
[[ $# -eq 0 ]] && {
showUsage
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
-d | --debug)
set -x
;;
-f | --flake)
flake=$2
shift
;;
-h | --help)
showUsage
exit 0
;;
--dry-run)
dry_run=y
;;
--show-trace)
nix_args+=("$1")
;;
--write-efi-boot-entries)
writeEfiBootEntries=true
;;
--mode)
if [[ $# -lt 2 ]]; then
echo "Option $1 requires an argument" >&2
exit 1
fi
case $2 in
format)
diskoAttr=diskoScript
;;
mount)
diskoAttr=mountScript
;;
*)
echo "Invalid mode: $2" >&2
echo "Valid modes are: format, mount" >&2
exit 1
;;
esac
shift
;;
--system-config)
if [[ $# -lt 2 ]]; then
echo "Option $1 requires one JSON argument." >&2
exit 1
fi
# shellcheck disable=SC2034
extraSystemConfig="$2"
shift
;;
--extra-files)
if [[ $# -lt 3 ]]; then
echo "Option $1 requires two arguments: source, destination" >&2
exit 1
fi
extraFiles[$2]=$3
shift
shift
;;
--option)
if [[ $# -lt 3 ]]; then
echo "Option $1 requires two arguments: key, value" >&2
exit 1
fi
nix_args+=(--option "$2" "$3")
shift
shift
;;
--disk)
if [[ $# -lt 3 ]]; then
echo "Option $1 requires two arguments: disk_name, device_path" >&2
exit 1
fi
# shellcheck disable=SC2034
diskMappings[$2]=$3
shift
shift
;;
*)
echo "Unknown option: $1" >&2
showUsage
exit 1
;;
esac
shift
done
}
cleanupMountPoint() {
mountPoint=$1
if mountpoint -q "${mountPoint}"; then
umount -R "${mountPoint}"
fi
rmdir "${mountPoint}"
}
nixBuild() {
if command -v nom-build > /dev/null; then
nom-build "$@"
else
nix-build "$@"
fi
}
main() {
parseArgs "$@"
if [[ -z ${flake-} ]]; then
echo "Please specify the flake-uri with --flake to use for installation." >&2
exit 1
fi
# check if we are root
if [[ "$EUID" -ne 0 ]]; then
echo "This script must be run as root" >&2
exit 1
fi
if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
flake="${BASH_REMATCH[1]}"
flakeAttr="${BASH_REMATCH[2]}"
fi
if [[ -e "$flake" ]]; then
flake=$(realpath "$flake")
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." >&2
echo 'For example, to use the output nixosConfigurations.foo from the flake.nix, append "#foo" to the flake-uri.' >&2
exit 1
fi
mountPoint=$(mktemp -d)
chmod 755 "${mountPoint}" # bchachefs wants 755
escapeMountPoint=$(printf '%q' "$mountPoint")
# shellcheck disable=SC2064
trap "cleanupMountPoint ${escapeMountPoint}" EXIT
outputs=$(nixBuild "${libexec_dir}"/install-cli.nix \
"${nix_args[@]}" \
--no-out-link \
--impure \
--argstr flake "$flake" \
--argstr flakeAttr "$flakeAttr" \
--argstr rootMountPoint "$mountPoint" \
--arg writeEfiBootEntries "$writeEfiBootEntries" \
--arg diskMappings "$(serialiaseArrayToNix diskMappings)" \
--argstr extraSystemConfig "$extraSystemConfig" \
-A installToplevel \
-A closureInfo \
-A "$diskoAttr")
IFS=$'\n' mapfile -t artifacts <<<"$outputs"
nixos_system=${artifacts[0]}
closure_info=${artifacts[1]}
disko_script=${artifacts[2]}
if [[ -n ${dry_run-} ]]; then
echo "Would run: $disko_script"
echo "Would run: nixos-install --system '$nixos_system' --root '$mountPoint'"
exit 0
fi
"$disko_script"
for source in "${!extraFiles[@]}"; do
destination=${extraFiles[$source]}
mkdir -p "$mountPoint/$(dirname "$destination")"
cp -ar "$source" "$mountPoint/$destination"
done
# nix copy uses up a lot of memory and we work around issues with incorrect checksums in our store
# that can be caused by using closureInfo in combination with multiple builders and non-deterministic builds.
# Therefore if we have a blank store, we copy the store paths and registration from the closureInfo.
if [[ ! -d "${mountPoint}/nix/store" ]]; then
echo "Copying store paths" >&2
mkdir -p "${mountPoint}/nix/store"
xargs cp --recursive --target "${mountPoint}/nix/store" < "${closure_info}/store-paths"
echo "Loading nix database" >&2
NIX_STATE_DIR=${mountPoint}/nix/var/nix nix-store --load-db < "${closure_info}/registration"
fi
nixos-install --no-channel-copy --no-root-password --system "$nixos_system" --root "$mountPoint"
}
main "$@"