-
Notifications
You must be signed in to change notification settings - Fork 1
/
prepare-uefi-lvm.sh
executable file
·290 lines (246 loc) · 6.92 KB
/
prepare-uefi-lvm.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
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#!/usr/bin/env bash
set -euo pipefail
# TODO: move /boot to /dev/sdX2 and move /efi to /boot/efi
# Currently this produces an unbootable system, presumably becaue /boot is
# hidden in the encrypted root volume.
# Also, we may need to run a standard grub-install on the boot devices, but that
# without getting /boot into a readably partition I can't be sure.
# Prepare destination media prior to install.
#
# Arguments
# FAI_PREPARE_ROOT_CRYPT_PASPHRASE
# Passphrase to unlock the encrypted root volume at boot time.
#
# This script will format the destination media with a volume layout that looks
# like the following diagram:
#
# /dev/sd{a,b}
# \_ partition 1: 2MB, flag=bios_grub
# \_ partition 2: 128MB, flag=boot
# \_ raid volume /dev/md/esp: level 1, metadata 1.0
# \_ fs: type vfat, mountpoint /efi
# \_ partition 3: 100%
# \_ raid volume /dev/md/root: level 0, metadata 1.2
# \_ crypt volume /dev/mapper/cryptroot: type luks2, keyfile /root/keys/cryptroot.bin
# \_ fs: type ext4, mountpoint /
#
# Create the following files (necessary for the subsequent install phase):
# * mdadm.conf
# * fstab
# * crypttab
# * env.sh
#
# After running this, source `env.sh`, set any other required environment
# variables, and invoke `install.sh`.
install_root=/mnt/arch
keystore_directory=/tmp/keystore
efi_directory=/efi
esp_raid_name=esp
esp_raid_device="/dev/md/$esp_raid_name"
root_raid_name=root
root_raid_device="/dev/md/$root_raid_name"
root_crypt_name=cryptroot
root_crypt_device="/dev/mapper/$root_crypt_name"
root_crypt_keyfile="/root/keys/$root_crypt_name.bin"
root_crypt_passphrase="$FAI_PREPARE_ROOT_CRYPT_PASSPHRASE"
function _chmod() {
(
set -x
chmod "$@"
)
}
function _cryptsetup() {
(
set -x
cryptsetup --batch-mode "$@"
)
}
function _dd() {
(
set -x
dd status=progress "$@"
)
}
function _mdadm_create() {
(
set -x
mdadm --create --run "$@"
)
}
function _mkdir() {
(
set -x
mkdir --parents "$@"
)
}
function _mkfs() {
(
set -x
mkfs "$@"
)
}
function _mount() {
(
set -x
mount "$@"
)
}
function _parted() {
(
set -x
parted --script --align=optimal -- "$@"
)
}
function _parted_mklabel() {
local device label
device="$1"
label="$2"
readonly device label
_parted "$device" mklabel "$label"
}
function _parted_mkpart() {
local device partition_number partition_type begin end name
device="$1"
partition_number="$2"
partition_type="$3"
name="$4"
begin="$5"
end="$6"
readonly device partition_number partition_type begin end name
shift 6
flag_args=
for flag in "$@"; do
flag_args+=" set $partition_number $flag on"
done
_parted "$device" \
unit mib mkpart "$partition_type" "$begin" "$end" \
name "$partition_number" "$name" \
$flag_args
}
function _randomize_device() {
local device crypt_name crypt_device
device="$1"
crypt_name="randomize_${device//\//_}"
crypt_device="/dev/mapper/$crypt_name"
readonly device crypt_name crypt_device
_cryptsetup --key-file /dev/random open "$device" "$crypt_name" --type plain
local crypt_size_b write_count_mb write_count_b write_seek_b
crypt_size_b="$(blockdev --getsize64 "$crypt_device")"
write_count_mb="$((crypt_size_b / (1024 * 1024)))"
write_count_b="$((crypt_size_b % (1024 * 1024)))"
write_seek_b="$((write_count_mb * (1024 * 1024)))"
readonly crypt_size_b write_count_mb write_count_b write_seek_b
_dd if=/dev/zero of="$crypt_device" bs=1M count="$write_count_mb"
if [ "$write_count_b" != '0' ]; then
_dd \
if=/dev/zero \
of="$crypt_device" \
oflag=seek_bytes \
bs="$write_count_b" \
count=1 \
seek="$write_seek_b"
fi
_cryptsetup close "$crypt_name"
}
function _create_keyfile() {
local keyfile size
keyfile="$1"
size="$2"
readonly keyfile size
_mkdir "$(dirname "$keyfile")"
_dd if=/dev/random of="$keyfile" iflag=fullblock bs="$size" count=1
_chmod 0000 "$keyfile"
}
function partition_device() {
local device
device="$1"
readonly device
_parted_mklabel "$device" gpt
_parted_mkpart "$device" 1 primary grub 1 3 bios_grub
_parted_mkpart "$device" 2 primary esp 3 131 boot
_parted_mkpart "$device" 3 primary root 131 -1
}
function create_raid_device() {
local level metadata device
level="$1"
metadata="$2"
device="$3"
readonly level metadata device
shift 3
_mdadm_create \
--level="$level" \
--metadata="$metadata" \
--raid-devices="$#" \
"$device" \
"$@"
}
function create_crypt_device() {
local crypt type name keyfile passphrase
crypt="$1"
type="$2"
name="$3"
keyfile="$4"
passphrase="${5:-}"
readonly crypt type name keyfile passphrase
_randomize_device "$crypt"
_create_keyfile "$keyfile" 2048
_cryptsetup --key-file "$keyfile" luksFormat --type "$type" "$crypt"
if [ ! -z "$passphrase" ]; then
echo $passphrase | _cryptsetup --key-file "$keyfile" luksAddKey "$crypt"
fi
_cryptsetup --key-file "$keyfile" open "$crypt" "$name"
}
function mount_filesystem() {
local device mountpoint type
device="$1"
mountpoint="$2"
type="$3"
readonly device mountpoint type
shift 3
_mkfs --type="$type" "$@" "$device"
_mkdir "$mountpoint"
_mount "$device" "$mountpoint"
}
partition_device /dev/sda
partition_device /dev/sdb
create_raid_device 1 1.0 "$esp_raid_device" /dev/sda2 /dev/sdb2
create_raid_device 0 1.2 "$root_raid_device" /dev/sda3 /dev/sdb3
create_crypt_device \
"$root_raid_device" \
luks1 \
"$root_crypt_name" \
"$keystore_directory/$root_crypt_name.bin" \
"$root_crypt_passphrase"
mount_filesystem "$root_crypt_device" "$install_root/" ext4 -F
mount_filesystem "$esp_raid_device" "$install_root$efi_directory" vfat -F 32
(
mdadm --detail --scan >./mdadm.conf
cat >./crypttab <<EOF
$root_crypt_name $root_raid_device $root_crypt_keyfile
EOF
genfstab -U "$install_root" >./fstab
configuration_files=
configuration_files+="$keystore_directory/$root_crypt_name.bin"
configuration_files+=":$install_root$root_crypt_keyfile"
configuration_files+=",./mdadm.conf:$install_root/etc/mdadm.conf"
configuration_files+=",./crypttab:$install_root/etc/crypttab"
configuration_files+=",./fstab:$install_root/etc/fstab"
mkinitcpio_hooks=
mkinitcpio_hooks+='base udev autodetect'
mkinitcpio_hooks+=' keyboard keymap'
mkinitcpio_hooks+=' consolefont modconf block'
mkinitcpio_hooks+=' lvm2 mdadm_udev encrypt'
mkinitcpio_hooks+=' filesystems fsck'
cmdline_linux=
cmdline_linux+="cryptdevice=$root_raid_device:$root_crypt_name"
cmdline_linux+=" cryptkey=$root_crypt_name:ext4:$root_crypt_keyfile"
cat >./env.sh <<EOF
export FAI_INSTALL_ROOT='$install_root'
export FAI_INSTALL_CONFIGURATION_FILES='$configuration_files'
export FAI_BOOTLDR_MKINITCPIO_HOOKS='$mkinitcpio_hooks'
export FAI_BOOTLDR_EFI_DIRECTORY='$efi_directory'
export FAI_BOOTLDR_CMDLINE_LINUX='$cmdline_linux'
export FAI_BOOTLDR_PRELOAD_MODULES='part_gpt'
export FAI_BOOTLDR_ENABLE_CRYPTODISK='yes'
EOF
)