summaryrefslogtreecommitdiff
path: root/zfssetup/stage1.sh
blob: c059478bfed267b4453927cb501f78ed937ecb93 (plain)
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
#!/usr/bin/env bash
# install arch linux on zfs root, stage one
# Craig Jennings <c@cjennings.net>
#
# https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS.html
#

set -e # halt on any error

#  -------------------------- Prerequisites --------------------------

sed -i "s/^#ParallelDownloads = 5$/ParallelDownloads = 15/" /etc/pacman.conf
# These are now done in stage 0
# pacman-key --init
# pacman-key --refresh-keys
# pacman --noconfirm -Sy archlinux-keyring
loadkeys us
timedatectl set-ntp true

###  --------------------------- Choose Disk ---------------------------

all_disk_ids=( $(ls /dev/disk/by-id/) )
echo ""; echo "Select the disk id to use. All data will be erased."
select disk_id in "${all_disk_ids[@]}"; do
    # ensure valid selection
    if [[ -n $disk_id ]]; then
        selection=$disk_id
        break
    else
        echo "Invalid. Try again."
    fi
done

# Confirm the selected disk
read -p "Confirm: '$selection' [y/n]? " choice
if [[ "$choice" != "y" ]]; then
    echo "Exiting..."
    exit 1
fi

DISK="/dev/disk/by-id/$selection"
MNT=/mnt   # Set a mount point
SWAPSIZE=4 # Set swap size in GB
RESERVE=1  # Set how much space to leave at the end of disk, minimum 1GB

###  --------------------------- Erase Disk -------------------------
echo ""; echo "### Erasing Disk"
blkdiscard -f "${DISK}" || true    # discard all sectors on flash-based storage
sgdisk --zap-all "${DISK}"         # clear the disk

###  ------------------------- Partition Disk ------------------------
echo ""; echo "### Partitioning Disk"
parted --script --align=optimal  "${DISK}" -- \
 mklabel gpt \
 mkpart EFI 2MiB 1GiB \
 mkpart bpool 1GiB 5GiB \
 mkpart rpool 5GiB -$((SWAPSIZE + RESERVE))GiB \
 mkpart swap  -$((SWAPSIZE + RESERVE))GiB -"${RESERVE}"GiB \
 mkpart BIOS 1MiB 2MiB \
 set 1 esp on \
 set 5 bios_grub on \
 set 5 legacy_boot on

###  ---------------------- Setup Encrypted Swap ---------------------
echo ""; echo "### Encrypted Swap"
for i in ${DISK}; do
   cryptsetup open --type plain --key-file /dev/random "${i}"-part4 "${i##*/}"-part4
   mkswap /dev/mapper/"${i##*/}"-part4
   swapon /dev/mapper/"${i##*/}"-part4
done

#  ------------------- Create Boot And Root Pools ------------------

# This step creates a separate boot pool for /boot with the features limited to
# only those that GRUB supports, allowing the root pool to use any/all features.

echo ""; echo "### Checking ZFS Module"
modprobe zfs # ensure zfs module is loaded

echo ""; echo "### Creating Boot Pool"
# shellcheck disable=SC2046
zpool create -d \
    -o feature@async_destroy=enabled \
    -o feature@bookmarks=enabled \
    -o feature@embedded_data=enabled \
    -o feature@empty_bpobj=enabled \
    -o feature@enabled_txg=enabled \
    -o feature@extensible_dataset=enabled \
    -o feature@filesystem_limits=enabled \
    -o feature@hole_birth=enabled \
    -o feature@large_blocks=enabled \
    -o feature@lz4_compress=enabled \
    -o feature@spacemap_histogram=enabled \
    -o ashift=12 \
    -o autotrim=on \
    -O acltype=posixacl \
    -O canmount=off \
    -O compression=lz4 \
    -O devices=off \
    -O normalization=formD \
    -O relatime=on \
    -O xattr=sa \
    -O mountpoint=/boot \
    -R "${MNT}" \
    bpool \
    $(for i in ${DISK}; do
       printf '%s ' "${i}-part2";
      done)

echo ""; echo "### Creating Root Pool"
# shellcheck disable=SC2046
zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -R "${MNT}" \
    -O acltype=posixacl \
    -O canmount=off \
    -O compression=zstd \
    -O dnodesize=auto \
    -O normalization=formD \
    -O relatime=on \
    -O xattr=sa \
    -O mountpoint=/ \
    rpool \
   $(for i in ${DISK}; do
      printf '%s ' "${i}-part3";
     done)

echo ""; echo "### Creating Unencrypted Root System Container"
# create UNENCRYPTED root system container
zfs create \
 -o canmount=off \
 -o mountpoint=none \
rpool/archlinux

#  --------------------- Create System Datasets --------------------
echo ""; echo "### Creating System Datasets"
zfs create -o canmount=noauto -o mountpoint=/  rpool/archlinux/root
zfs mount rpool/archlinux/root
zfs create -o mountpoint=legacy rpool/archlinux/home
mkdir "${MNT}"/home
mount -t zfs rpool/archlinux/home "${MNT}"/home
zfs create -o mountpoint=legacy  rpool/archlinux/var
zfs create -o mountpoint=legacy rpool/archlinux/var/lib
zfs create -o mountpoint=legacy rpool/archlinux/var/log
zfs create -o mountpoint=none bpool/archlinux
zfs create -o mountpoint=legacy bpool/archlinux/root
mkdir "${MNT}"/boot
mount -t zfs bpool/archlinux/root "${MNT}"/boot
mkdir -p "${MNT}"/var/log
mkdir -p "${MNT}"/var/lib
mount -t zfs rpool/archlinux/var/lib "${MNT}"/var/lib
mount -t zfs rpool/archlinux/var/log "${MNT}"/var/log

#  ---------------------- Format And Mount ESP ---------------------
echo ""; echo "### Format And Mount ESP"
for i in ${DISK}; do
 mkfs.vfat -n EFI "${i}"-part1
 mkdir -p "${MNT}"/boot/efis/"${i##*/}"-part1
 mount -t vfat -o iocharset=iso8859-1 "${i}"-part1 "${MNT}"/boot/efis/"${i##*/}"-part1
done

mkdir -p "${MNT}"/boot/efi
mount -t vfat -o iocharset=iso8859-1 "$(echo "${DISK}" | sed "s|^ *||"  | cut -f1 -d' '|| true)"-part1 "${MNT}"/boot/efi

###  -------------------------- Install Base -------------------------
echo ""; echo "### Installing Base"
# install packages with pacstrap
pacstrap "${MNT}" \
         base \
         base-devel \
         dkms \
         efibootmgr \
         git \
         grub \
         intel-ucode \
         linux-firmware \
         linux-lts \
         linux-lts-headers \
         man-db \
         man-pages \
         vi

# create fstab and remove all zroot entries
genfstab -U -p "${MNT}" >> "${MNT}"/etc/fstab
sed -i '/^# zroot/d' "${MNT}"/etc/fstab
sed -i '/^zroot/d' "${MNT}"/etc/fstab
sed -i '/^$/d' "${MNT}"/etc/fstab
echo "" >> "${MNT}"/etc/fstab # one blank line at the end

# copy over dns settings to the new system
cp -v /etc/resolv.conf "${MNT}"/etc

# copy stage2 script to the new system
cp ./stage2.sh "${MNT}"/root

#  ----------------------------- Chroot ----------------------------

echo ""; echo "### Done with Stage One"
chroot "${MNT}" /usr/bin/env DISK="${DISK}" /root/stage2.sh

#  -------------------------- After Chroot -------------------------

umount -Rl "${MNT}"
zfs snapshot -r rpool@initial-installation
zfs snapshot -r bpool@initial-installation

zpool export -a

echo ""; echo "### Done with Stage Two"