· 5 years ago · Dec 02, 2020, 07:48 AM
1#!/usr/bin/env sh
2#
3# TODO:
4# * Suspend/resume to/from swap: https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate#Required_kernel_parameters
5# * Emojis? http://www.omgubuntu.co.uk/2016/03/enable-color-emoji-linux-svg-font
6
7
8set -e
9# set -x
10
11
12
13#-----------------------------------------------------------------------------------------------------------------------
14# Config.
15
16#--YOUR-CUSTOMIZATIONS-BELOW--------------------------------------------------------------------------------------------
17
18# General.
19DESIRED_COUNTRY='US'
20DESIRED_TIMEZONE='America/Chicago'
21DESIRED_LOCALE='en_US.UTF-8 UTF-8'
22DESIRED_LOCALE2='en_US.UTF-8'
23DESIRED_LANGUAGE='en_US'
24DESIRED_HOSTNAME='bo-laptop'
25DESIRED_USERNAME='bo'
26# Cipher Strength.
27CIPHER_STRENGTH=256
28# Key file.
29KEYFILE_NAME='multikeyfile'
30# If these devs are not found, will default to /dev/sda & /dev/sdb.
31DEV_DRIVE1='/dev/nvme0n1'
32DEV_DRIVE2='/dev/nvme1n1'
33# Partition numbers.
34PARTNUM_EFI='1'
35PARTNUM_SWAP1='2'
36PARTNUM_DATA1='3'
37PARTNUM_SWAP2='1'
38PARTNUM_DATA2='2'
39# Swap size in harddrive sectors.
40SWAP_SIZE=34603007
41
42
43#--DO-NOT-MODIFY-ANYTHING-BEYOND-THIS-LINE-UNLESS-NECESSARY-------------------------------------------------------------
44
45KERNEL_PARAMS=''
46# Key file.
47KEYFILE="/mnt/boot/${KEYFILE_NAME}"
48KEYFILE_MAPPED="/dev/mapper/${KEYFILE_NAME}"
49# /dev/mapper/* related.
50DATA1_MAPNAME='container1'
51DATA2_MAPNAME='container2'
52DATA1_MAPPED="/dev/mapper/${DATA1_MAPNAME}"
53DATA2_MAPPED="/dev/mapper/${DATA2_MAPNAME}"
54SWAP1_MAPNAME='swap1'
55SWAP2_MAPNAME='swap2'
56SWAP1_MAPPED="/dev/mapper/${SWAP1_MAPNAME}"
57SWAP2_MAPPED="/dev/mapper/${SWAP2_MAPNAME}"
58SWAP_RAID='/dev/md1'
59# Used later.
60PART_EFI=''
61PART_SWAP1=''
62PART_DATA1=''
63PART_SWAP2=''
64PART_DATA2=''
65SWAP_UUID=''
66ROOT_UUID=''
67
68INTEL_DEV_ID="$(lspci -nn | grep -Ei "(VGA|3D).+ Intel .*" | sed -E 's/.*\[([a-fA-F0-9]+:[a-fA-F0-9]+)\].*/\1/g')"
69NVIDIA_DEV_ID="$(lspci -nn | grep -Ei "(VGA|3D).+ nVidia .*" | sed -E 's/.*\[([a-fA-F0-9]+:[a-fA-F0-9]+)\].*/\1/g')"
70NVIDIA_BUS_ID="$(lspci | grep -Ei "(VGA|3D).+ nVidia .*" | cut -b1-7)"
71
72
73
74#-----------------------------------------------------------------------------------------------------------------------
75# General Methods.
76
77wait_for_user_input() {
78 printf "\nPress ENTER to continue.\n"
79 read
80}
81
82# Chopped up version of armrr.
83# https://github.com/Gen2ly/armrr
84dld_mirror_list() {
85 # "sh" shell doesn't support local variables so these will be global. :/
86 # TODO: test this install script in bash.
87 url="https://www.archlinux.org/mirrorlist/?country=${DESIRED_COUNTRY}&protocol=http&ip_version=4&use_mirror_status=on"
88 tmp_ml=$(mktemp --suffix=-mirrorlist)
89
90 if curl -s "${url}" -o "${tmp_ml}"; then
91 if ! grep "^## Arch Linux repository mirrorlist" "${tmp_ml}" > /dev/null; then
92 echo 'Warning: Downloaded mirrorlist invalid. Not using.'
93 return
94 fi
95 else
96 echo 'Warning: Download of mirrorlist failed. Not using.'
97 return
98 fi
99
100 # Enable all servers.
101 sed -i 's/^#Server/Server/g' "${tmp_ml}"
102
103 # Copy over the new mirror list.
104 install -Dm644 "${tmp_ml}" /etc/pacman.d/mirrorlist
105}
106
107# Attempts to find a device for our work. If passing a unix-style dev, like "nvme" drives, pass the full dev; e.g.
108# '/dev/nvme0n1' rather than '/dev/nvme0'.
109#
110# Takes two arguments:
111# 1. our desired dev; e.g. '/dev/nvme0'
112# 2. our allowable fallback dev; e.g. '/dev/sda'
113find_proper_drive() {
114 ourdev="$1"
115 defaultdev="$2"
116 returndev="${ourdev}"
117
118 if [ ! -e "${ourdev}" ]; then
119 returndev="${defaultdev}"
120 fi
121
122 # Is the device NVME? Does it not end in "n1"? If both are true, then append "n1" to the dev name.
123 if [ "${returndev#*nvme}" != "${returndev}" -a "${returndev%n1}" == "${returndev}" ]; then
124 returndev="${returndev}n1"
125 fi
126
127 printf "%s" "${returndev}"
128}
129
130find_proper_partition() {
131 ourdev="$1"
132 ourpart="$2"
133
134 if [ "${ourdev#*nvme}" != "${ourdev}" ]; then
135 ourdev="${ourdev}p"
136 fi
137
138 printf "%s%s" "${ourdev}" "${ourpart}"
139}
140
141
142unmount_all() {
143 set +e
144 swapoff "${SWAP_RAID}"
145 mdadm --stop --force "${SWAP_RAID}"
146 cryptsetup close "${SWAP1_MAPNAME}"
147 cryptsetup close "${SWAP2_MAPNAME}"
148 umount -R /mnt/arch/home
149 umount -R /mnt/arch
150 umount -R /mnt/btrfs-pool
151 cryptsetup close "${DATA1_MAPNAME}"
152 cryptsetup close "${DATA2_MAPNAME}"
153 umount -R "${DATA1_MAPPED}"
154 umount -R "${DATA2_MAPPED}"
155 cryptsetup close "${KEYFILE_NAME}"
156 umount -R "${KEYFILE_MAPPED}"
157 umount -R /mnt/boot
158 set -e
159}
160
161
162
163#-----------------------------------------------------------------------------------------------------------------------
164# Confirm Execution of This Script.
165
166
167clear
168
169echo '
170
171
172WARNING! WARNING! WARNING! WARNING!
173WARNING! WARNING! WARNING! WARNING!
174
175THIS SCRIPT WILL ABSOLUTELY WIPE OUT YOUR DATA ON AT LEAST THE FIRST TWO DRIVES AND WILL REPLACE YOUR BOOT LOADER!
176YOU ALONE CARRY THE RESPONSIBILITY FOR ANY DATA LOSS BY USING THIS SCRIPT.
177
178THERE WILL BE NO CONFIRMATION BEFORE DATA DESTRUCTION BEYOND THIS POINT!
179
180WARNING! WARNING! WARNING! WARNING!
181WARNING! WARNING! WARNING! WARNING!
182
183
184Do you acknowledge you alone carry the responsibility for any data loss and want to continue?
185* If so, press enter three times.
186* If not, press CTRL+C to cancel this script.
187'
188wait_for_user_input
189wait_for_user_input
190wait_for_user_input
191
192
193
194#-----------------------------------------------------------------------------------------------------------------------
195# General Prep.
196# https://wiki.archlinux.org/index.php/beginners'_guide#Update_the_system_clock
197# https://wiki.archlinux.org/index.php/beginners'_guide#Select_the_mirrors
198# https://wiki.archlinux.org/index.php/Mirrors
199
200# Ensure nothing is mounted that we intend to mount later.
201unmount_all
202
203
204printf "\n\nActivating network time to ensure the system's time is correct.\n"
205sudo tee /etc/systemd/timesyncd.conf <<-'EOF' > /dev/null
206[Time]
207#NTP=0.north-america.pool.ntp.org 1.north-america.pool.ntp.org 2.north-america.pool.ntp.org 3.north-america.pool.ntp.org
208NTP=time1.google.com time2.google.com time3.google.com time4.google.com
209FallbackNTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
210EOF
211
212timedatectl set-ntp true
213
214
215printf "\n\nRanking pacman mirrors.\n"
216dld_mirror_list
217
218
219printf "\n\nEnabling multilib.\n"
220sed -i '/[#]*\[multilib\]/ { N; d; }' /etc/pacman.conf
221sed -i '/[#]*\[archlinuxfr\]/ { N; N; d; }' /etc/pacman.conf
222tee -a /etc/pacman.conf <<'EOF' > /dev/null
223
224[multilib]
225Include = /etc/pacman.d/mirrorlist
226
227[archlinuxfr]
228SigLevel = Never
229Server = http://repo.archlinux.fr/$arch
230EOF
231
232
233printf "\n\nInstalling latest utils.\n"
234pacman -Sy --noconfirm btrfs-progs parallel
235
236
237# Figure out if we have devices to raid.
238DEV_DRIVE1="$(find_proper_drive "${DEV_DRIVE1}" "/dev/sda")"
239DEV_DRIVE2="$(find_proper_drive "${DEV_DRIVE2}" "/dev/sdb")"
240
241
242
243#-----------------------------------------------------------------------------------------------------------------------
244# Partition Drives.
245# https://wiki.archlinux.org/index.php/beginners'_guide#Prepare_the_storage_devices
246
247# Reset the drive's partition table to a fresh GPT.
248sgdisk --zap "${DEV_DRIVE1}"
249sgdisk --clear --mbrtogpt "${DEV_DRIVE1}"
250
251# Calculate sectors for drive 1's EFI boot partition.
252EFI_SECT_START=2048
253EFI_SECT_END=$((EFI_SECT_END=EFI_SECT_START+2097151))
254
255# Calculate sectors for drive 1's swap.
256SWAP_SECT_START=$((SWAP_SECT_START=EFI_SECT_END+1))
257SWAP_SECT_END=$((SWAP_SECT_END=SWAP_SECT_START+SWAP_SIZE))
258
259# Calculate sectors for drive 1's data.
260DATA_SECT_START=$((DATA_SECT_START=SWAP_SECT_END+1))
261DATA_SECT_END=$(sgdisk -E ${DEV_DRIVE1})
262
263# Create a 1024MB EFI boot partition.
264sgdisk --new ${PARTNUM_EFI}:${EFI_SECT_START}:${EFI_SECT_END} \
265 --change-name ${PARTNUM_EFI}:'EFI System Partition' \
266 --typecode ${PARTNUM_EFI}:ef00 "${DEV_DRIVE1}"
267
268# Create a SWAP partition.
269sgdisk --new ${PARTNUM_SWAP1}:${SWAP_SECT_START}:${SWAP_SECT_END} \
270 --change-name ${PARTNUM_SWAP1}:'SWAP1' \
271 --typecode ${PARTNUM_SWAP1}:8200 "${DEV_DRIVE1}"
272
273# Create the root partition.
274sgdisk --new ${PARTNUM_DATA1}:${DATA_SECT_START}:${DATA_SECT_END} \
275 --change-name ${PARTNUM_DATA1}:'DATA1' \
276 --typecode ${PARTNUM_DATA1}:8300 "${DEV_DRIVE1}"
277
278# Print out the partition table for the first drive.
279sgdisk --print "${DEV_DRIVE1}"
280
281
282# Reset the drive's partition table to a fresh GPT.
283sgdisk --zap "${DEV_DRIVE2}"
284sgdisk --clear --mbrtogpt "${DEV_DRIVE2}"
285
286# Calculate sectors for drive 2's swap.
287SWAP_SECT_START=2048
288SWAP_SECT_END=$((SWAP_SECT_END=SWAP_SECT_START+SWAP_SIZE))
289
290# Calculate sectors for drive 2's data.
291DATA_SECT_START=$((DATA_SECT_START=SWAP_SECT_END+1))
292DATA_SECT_END=$(sgdisk -E ${DEV_DRIVE2})
293
294# Create a 16.5GB SWAP partition.
295sgdisk --new ${PARTNUM_SWAP2}:${SWAP_SECT_START}:${SWAP_SECT_END} \
296 --change-name ${PARTNUM_SWAP2}:'SWAP2' \
297 --typecode ${PARTNUM_SWAP2}:8200 "${DEV_DRIVE2}"
298
299# Create the root partition.
300sgdisk --new ${PARTNUM_DATA2}:${DATA_SECT_START}:${DATA_SECT_END} \
301 --change-name ${PARTNUM_DATA2}:'DATA2' \
302 --typecode ${PARTNUM_DATA2}:8300 "${DEV_DRIVE2}"
303
304# Print out the partition table for the first drive.
305sgdisk --print "${DEV_DRIVE2}"
306
307
308
309#-----------------------------------------------------------------------------------------------------------------------
310# Discover proper partition names.
311
312PART_EFI="$(find_proper_partition "${DEV_DRIVE1}" "${PARTNUM_EFI}")"
313PART_SWAP1="$(find_proper_partition "${DEV_DRIVE1}" "${PARTNUM_SWAP1}")"
314PART_DATA1="$(find_proper_partition "${DEV_DRIVE1}" "${PARTNUM_DATA1}")"
315PART_SWAP2="$(find_proper_partition "${DEV_DRIVE2}" "${PARTNUM_SWAP2}")"
316PART_DATA2="$(find_proper_partition "${DEV_DRIVE2}" "${PARTNUM_DATA2}")"
317
318
319
320#-----------------------------------------------------------------------------------------------------------------------
321# Setup The Key.
322# https://bbs.archlinux.org/viewtopic.php?id=196840
323
324echo "
325
326Creating keyfile used to decrypt each drive in the array. This key is encrypted and will be what you unlock when
327entering the proper password on boot.
328
329When prompted, please provide a password you can remember.
330"
331# wait_for_user_input
332
333# Format the EFI+BOOT partition and mount it.
334printf "\n\nBuilding /mnt/boot (EFI).\n"
335mkfs.fat -F32 "${PART_EFI}"
336[ ! -d /mnt/boot ] && mkdir -p /mnt/boot
337mount "${PART_EFI}" /mnt/boot
338
339# Generate a blank keyfile -- apparently the LUKS header is 2MB, so we'll need 2MB + the 2MB for keys.
340dd if=/dev/zero of="${KEYFILE}" bs=4M count=1
341
342# Format our keyfile.
343cryptsetup --batch-mode --verbose --verify-passphrase \
344 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \
345 luksFormat "${KEYFILE}"
346
347# Decrypt and open the keyfile.
348printf "\n\nEnter your encrypt password when prompted below.\n"
349cryptsetup open --type luks "${KEYFILE}" "${KEYFILE_NAME}"
350
351
352set +e
353
354# Write zeros to the keyfile.
355dd if=/dev/zero of="${KEYFILE_MAPPED}"
356# Want 4 keys. (4 * 4096 / 8) = 2048 bytes".
357dd iflag=fullblock if=/dev/random of="${KEYFILE_MAPPED}" bs=2048 count=1
358
359set -e
360
361
362printf "\n\nVerify there is enough random content in the keyfile:\n"
363hexdump -C "${KEYFILE_MAPPED}"
364
365
366
367#-----------------------------------------------------------------------------------------------------------------------
368# Create Encrypted Swap.
369# https://wiki.archlinux.org/index.php/Dm-crypt/Swap_encryption
370
371printf "\n\nCreating the containers for our swap.\n"
372
373cryptsetup --batch-mode --verbose \
374 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \
375 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 0 --keyfile-size 512 \
376 luksFormat "${PART_SWAP1}"
377
378cryptsetup --batch-mode --verbose \
379 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \
380 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 512 --keyfile-size 512 \
381 luksFormat "${PART_SWAP2}"
382
383
384printf "\n\nOpening the containers for our swap.\n"
385
386cryptsetup open --type luks \
387 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 0 --keyfile-size 512 "${PART_SWAP1}" "${SWAP1_MAPNAME}" # swapDevice
388
389cryptsetup open --type luks \
390 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 512 --keyfile-size 512 "${PART_SWAP2}" "${SWAP2_MAPNAME}" # swapDevice
391
392
393# Wipe 999MB of each drive (for testing of a full disk wipe).
394# printf "%s\n%s\n" "${SWAP1_MAPPED}" "${SWAP2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M count=999 status=progress"
395# TODO: remove the above parallel command and uncomment the below.
396# Fully wipe both drives to fill them with encrypted "garbage" making it near impossible to discern where new encrypted
397# data is stored.
398# printf "%s\n%s\n" "${SWAP1_MAPPED}" "${SWAP2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M status=progress"
399
400# Create raid for swap. Why? Only because of resume. I intend to use VMs for most of my memory and am uncertain that the
401# memory used by VMs can be compressed to the default 2/5ths to fit all 32GBs of system memory into a single swap
402# partition. On top of that, I want my swap partitions to be used evenly, which can either be done via setting their
403# priority to exactly the same (kernel will then "stripe" them) or mdadm'ing them. If I let the kernel decide what swap
404# partition to prioritize for hibernation, I will not be able to reliably resume because the kernel "resume" parameter
405# does not consider multiple swap devices! Therefore we must raid them.
406mdadm --create "${SWAP_RAID}" --force --level=0 --raid-devices=2 "${SWAP1_MAPPED}" "${SWAP2_MAPPED}"
407
408# Make the swap partition.
409mkswap "${SWAP_RAID}"
410
411# Start using the swap partition.
412swapon "${SWAP_RAID}"
413
414
415
416#-----------------------------------------------------------------------------------------------------------------------
417# Create Encrypted BTRFS.
418# https://wiki.archlinux.org/index.php/beginners'_guide#Format_the_file_systems_and_enable_swap
419# http://kneit.in/2015/09/17/brtfs-raid-on-dmcrypt.html#planning-your-disk-layout
420
421printf "\n\nCreating the containers for our array.\n"
422
423cryptsetup --batch-mode --verbose \
424 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \
425 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 1024 --keyfile-size 512 \
426 luksFormat "${PART_DATA1}"
427
428cryptsetup --batch-mode --verbose \
429 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \
430 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 1536 --keyfile-size 512 \
431 luksFormat "${PART_DATA2}"
432
433
434printf "\n\nOpening the containers for our array.\n"
435
436cryptsetup open --type luks \
437 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 1024 --keyfile-size 512 "${PART_DATA1}" \
438 "${DATA1_MAPNAME}"
439
440cryptsetup open --type luks \
441 --key-file "${KEYFILE_MAPPED}" --keyfile-offset 1536 --keyfile-size 512 "${PART_DATA2}" \
442 "${DATA2_MAPNAME}"
443
444
445# Close the no longer needed cryptkey.
446cryptsetup close "${KEYFILE_NAME}"
447
448
449# Wipe 999MB of each drive (for testing of a full disk wipe).
450# printf "%s\n%s\n" "${DATA1_MAPPED}" "${DATA2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M count=999 status=progress"
451# TODO: remove the above parallel command and uncomment the below.
452# Fully wipe both drives to fill them with encrypted "garbage" making it near impossible to discern where new encrypted
453# data is stored.
454# printf "%s\n%s\n" "${DATA1_MAPPED}" "${DATA2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M status=progress"
455
456
457# Make the BTRFS RAID 0 (stripe) for data & RAID 1 (mirror) for meta data, the latter helps detect & avoid corruption.
458printf "\n\nFormatting the containers with btrfs.\n"
459mkfs.btrfs -m raid1 -d raid0 "${DATA1_MAPPED}" "${DATA2_MAPPED}"
460
461
462# Mount our BTRFS RAID--defaults for mounting on NVME are fine, just add compression cause it's good stuff.
463# WARNING: Do not add "discard" to mounting NVME SSDs! Btrfs does not do this by default, which is good.
464[ ! -d /mnt/btrfs-pool ] && mkdir /mnt/btrfs-pool
465mount -t btrfs -o defaults,compress=lzo "${DATA1_MAPPED}" /mnt/btrfs-pool
466
467
468# Change our working dir.
469pushd /mnt/btrfs-pool
470
471# Create desired subvolumes for easy snapshots.
472btrfs sub create @
473btrfs sub create @home
474btrfs sub create @snapshots
475# Paths we do not want to include in snapshots.
476btrfs sub create @var-cache-pacman-pkg
477btrfs sub create @var-abs
478btrfs sub create @var-tmp
479btrfs sub create @tmp
480btrfs sub create @srv
481
482
483# List our subvols.
484btrfs sub list .
485
486# Reset our current working folder.
487popd
488
489
490
491#-----------------------------------------------------------------------------------------------------------------------
492# Mount Our Partitions.
493# https://wiki.archlinux.org/index.php/beginners'_guide#Format_the_file_systems_and_enable_swap
494
495
496# Mount our root subvolume.
497[ ! -d /mnt/arch ] && mkdir /mnt/arch
498mount -t btrfs -o defaults,compress=lzo,subvol=@ "${DATA1_MAPPED}" /mnt/arch
499
500
501# Make some system dirs.
502[ ! -d /mnt/arch/boot ] && mkdir -p /mnt/arch/boot
503[ ! -d /mnt/arch/home ] && mkdir -p /mnt/arch/home
504[ ! -d /mnt/arch/etc ] && mkdir -p /mnt/arch/etc
505[ ! -d /mnt/arch/var/log ] && mkdir -p /mnt/arch/var/log
506# Paths we do not want to include in snapshots.
507[ ! -d /mnt/arch/var/cache/pacman/pkg ] && mkdir -p /mnt/arch/var/cache/pacman/pkg
508[ ! -d /mnt/arch/var/abs ] && mkdir -p /mnt/arch/var/abs
509[ ! -d /mnt/arch/var/tmp ] && mkdir -p /mnt/arch/var/tmp
510[ ! -d /mnt/arch/tmp ] && mkdir -p /mnt/arch/tmp
511[ ! -d /mnt/arch/srv ] && mkdir -p /mnt/arch/srv
512
513
514# Bind boot to two locations since a symlink cannot be used within /mnt/arch once we get into arch-chroot or mkinitcpio.
515mount --bind /mnt/boot /mnt/arch/boot
516
517
518# Disable copy-on-write to avoid fragmentation.
519chattr +C /mnt/arch/var/log
520
521
522# Mount our subvols.
523# We keep them as subvols not nested under root so that rolling back the subvol named "@" will be easy, again, due to
524# not having nested subvols under "@".
525mount -t btrfs -o defaults,compress=lzo,subvol=@home "${DATA1_MAPPED}" /mnt/arch/home
526mount -t btrfs -o defaults,compress=lzo,subvol=@var-cache-pacman-pkg "${DATA1_MAPPED}" /mnt/arch/var/cache/pacman/pkg
527mount -t btrfs -o defaults,compress=lzo,subvol=@var-abs "${DATA1_MAPPED}" /mnt/arch/var/abs
528mount -t btrfs -o defaults,compress=lzo,subvol=@var-tmp "${DATA1_MAPPED}" /mnt/arch/var/tmp
529mount -t btrfs -o defaults,compress=lzo,subvol=@tmp "${DATA1_MAPPED}" /mnt/arch/tmp
530mount -t btrfs -o defaults,compress=lzo,subvol=@srv "${DATA1_MAPPED}" /mnt/arch/srv
531
532
533# Mount our btrfs pool, without specifying subvolumes, to make it easier to manage subvols.
534[ ! -d /mnt/arch/mnt/btrfs-pool ] && mkdir -p /mnt/arch/mnt/btrfs-pool
535mount -t btrfs -o defaults,compress=lzo "${DATA1_MAPPED}" /mnt/arch/mnt/btrfs-pool
536
537
538
539#-----------------------------------------------------------------------------------------------------------------------
540# Install Arch Linux.
541# https://wiki.archlinux.org/index.php/beginners'_guide#Installation
542
543# Package descriptions:
544# * intel-ucode: updated microcode for intel CPUs. AMDs do not need an extra pkg for updates.
545# * mesa-libgl, lib32-mesa-libgl: adds OpenGL support to intel gpu.
546# * mesa: an open-source implementation of the OpenGL specification.
547# * vulkan-intel: adds Vulkan, replacement for OpenGL, to intel gpu.
548# * xf86-video-*: hybrid graphics cards drivers (nvidia + intel, or amd + intel);
549# see https://wiki.archlinux.org/index.php/PRIME
550# * nvidia*, lib32-nvidia-libgl: nVidia supplied linux video drivers--very performant.
551# see https://wiki.archlinux.org/index.php/NVIDIA_Optimus
552# * xorg-xrandr: required by nvidia* packages, according to the wiki.
553# * iw: CLI WIFI configuration util.
554# * netctl: installed with "base"; recommended for networking control. https://wiki.archlinux.org/index.php/Netctl
555# * ifplugd: starts & stops DHCP profiles when network cable is plugged in or unplugged.
556# * wpa_actiond: same concept as ifplugd but for wifi.
557# * wpa_supplicant: A utility providing key negotiation for WPA wireless networks.
558# * dialog: A tool to display dialog boxes from shell scripts.
559# * libva-intel-driver, libva-vdpau-driver (req. nouveau-fw), nvidia-utils: "Video Acceleration API" (VA-API) for hw
560# accel video encoding and decoding. https://wiki.archlinux.org/index.php/VA-API
561# * libvdpau-va-gl, mesa-vdpau (req. nouveau-fw), nvidia-utils: "Video Decode and Presentation API for Unix" (VDPAU) is
562# an open source library and API to offload portions of the video decoding process and video post-processing to the
563# GPU video-hardware. https://wiki.archlinux.org/index.php/VDPAU
564# * qemu, libvirt, bridge-utils: KVM & VFIO related.
565#
566# Dependencies for future packages/apps:
567# * python3: snapper gui
568# * gtk3: snapper gui
569# * python-dbus: snapper gui
570# * python-gobject: snapper gui
571# * python-setuptools: snapper gui
572# * gtksourceview3: snapper gui
573
574printf "\n\nInstalling Arch Linux.\n"
575pacstrap /mnt/arch \
576 alsa-utils \
577 alsa-oss \
578 alsa-lib \
579 base \
580 base-devel \
581 mtr \
582 bash-completion \
583 btrfs-progs \
584 dialog \
585 downgrade \
586 efibootmgr \
587 gtk3 \
588 qt4 \
589 gtksourceview3 \
590 htop \
591 intel-ucode \
592 iotop \
593 iw \
594 lib32-alsa-plugins \
595 lib32-mesa-libgl \
596 libvdpau-va-gl \
597 linux-headers \
598 libva-intel-driver \
599 mesa \
600 mesa-libgl \
601 mesa-vdpau \
602 pulseaudio \
603 pulseaudio-alsa \
604 pulseaudio-bluetooth \
605 pulseaudio-equalizer \
606 pulseaudio-gconf \
607 python \
608 python-dbus \
609 python-gobject \
610 python-setuptools \
611 python2 \
612 snapper \
613 vulkan-icd-loader \
614 vulkan-intel \
615 wget \
616 wpa_supplicant \
617 wpa_supplicant_gui \
618 xf86-input-evdev \
619 xf86-input-synaptics \
620 yaourt \
621 qemu libvirt bridge-utils \
622
623
624# ifplugd \
625# wpa_actiond \
626 # nvidia \
627 # nvidia-utils \
628 # nvidia-libgl \
629 # lib32-nvidia-libgl \
630 # xorg-xrandr \
631
632 # xf86-video-intel \ # apparently has poor performance. https://www.reddit.com/r/archlinux/comments/4cojj9/it_is_probably_time_to_ditch_xf86videointel/
633 # xf86-video-nouveau \
634 # xf86-video-vesa \
635 # xf86-video-ati \
636
637
638
639#-----------------------------------------------------------------------------------------------------------------------
640# Configure Arch.
641
642printf "\n\nGenerating fstab.\n"
643genfstab -pU /mnt/arch > /mnt/arch/etc/fstab
644cat /mnt/arch/etc/fstab
645
646
647# Set the hostname.
648echo "${DESIRED_HOSTNAME}" > /mnt/arch/etc/hostname
649
650# Copy files that do not seem to be copied by pacstrap.
651install -Dm644 /etc/pacman.d/mirrorlist /mnt/arch/etc/pacman.d/mirrorlist
652install -Dm644 /etc/pacman.conf /mnt/arch/etc/pacman.conf
653cp /etc/locale.gen /etc/locale.conf /mnt/arch/etc/
654
655
656printf "\n\nConfiguring arch.\n"
657arch-chroot /mnt/arch /bin/bash <<-EOC
658loadkeys us
659
660printf "\n\nGenerating locale config.\n"
661echo "${DESIRED_LOCALE}" > /etc/locale.gen
662locale-gen
663
664echo "LANG=${DESIRED_LOCALE2}" > /etc/locale.conf
665# echo "LANGUAGE=${DESIRED_LANGUAGE}" >> /etc/locale.conf
666# # echo 'LC_ALL=C' >> /etc/locale.conf
667export LANG="${DESIRED_LOCALE2}"
668localectl set-locale LANG="${DESIRED_LOCALE2}"
669
670
671printf "\n\nSet timezone.\n"
672ln -s "/usr/share/zoneinfo/${DESIRED_TIMEZONE}" /etc/localtime
673# Adjust time skew.
674hwclock --systohc --utc
675
676printf "\n\nActivating network time to ensure the system's time is correct.\n"
677tee /etc/systemd/timesyncd.conf <<-'EOF' > /dev/null
678[Time]
679NTP=0.north-america.pool.ntp.org 1.north-america.pool.ntp.org 2.north-america.pool.ntp.org 3.north-america.pool.ntp.org
680FallbackNTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
681EOF
682
683
684# Download latest pacman package list.
685pacman -Sy
686
687
688# Install python pip.
689wget https://bootstrap.pypa.io/get-pip.py
690python get-pip.py
691rm -f get-pip.py
692EOC
693
694
695# Enable "LLMNR" for systemd-resolved so that we may resolve hosts on the LAN without needing a DNS server.
696sed -i 's/^[#]*\s*LLMNR=.*/LLMNR=yes/g' /mnt/arch/etc/systemd/resolved.conf
697
698# Add systemd-resolved to the host lookup order to act as a local DNS middle-man or cache.
699sed -i 's/^hosts:.*/hosts: files mymachines resolve myhostname dns/g' /mnt/arch/etc/nsswitch.conf
700
701
702
703#-----------------------------------------------------------------------------------------------------------------------
704# Configure Xorg.
705
706printf "\n\nConfiguring Xorg.\n"
707
708# TODO: CODE NEEDS TO DOWNLOAD AND INSTALL THIS INTEL GUC FIRMWARE UNTIL IT MAKES IT INTO THE NEXT KERNEL OR WHATEVER:
709# https://01.org/sites/default/files/downloads/intelr-graphics-linux/sklgucver61.tar.bz2
710# probably can have it replace the v4 guc:
711# ln -sf /lib/firmware/i915/skl_guc_ver6_1.bin /lib/firmware/i915/skl_guc_ver4.bin
712# have to rebuild init:
713# mkinitcpio -p linux
714
715tee /mnt/arch/etc/X11/xorg.conf <<EOF > /dev/null
716Section "Module"
717 Load "modesetting"
718EndSection
719
720# Section "Device"
721# Identifier "nvidia"
722# Driver "nvidia"
723# BusID "${NVIDIA_DEV_ID}"
724# Option "AllowEmptyInitialConfiguration"
725# EndSection
726
727# If not use xf86-video-intel but kernel provided mesa for intel gfx, then you need this config.
728Section "Device"
729 Identifier "Intel Graphics"
730 # Driver "intel"
731 Driver "modesetting"
732 # BusID "${INTEL_DEV_ID}"
733 Option "AccelMethod" "sna"
734 Option "TearFree" "True"
735 Option "DRI" "3"
736 # Option "Tiling" "True"
737 # Option "SwapbuffersWait" "True"
738EndSection
739
740# Section "ServerLayout"
741# Identifier "layout"
742# Screen 1 "nvidia"
743# Inactive "intel"
744# EndSection
745EOF
746
747# tee /mnt/arch/etc/X11/xorg.conf.d/20-intel.conf <<EOF > /dev/null
748# EOF
749
750# tee /mnt/arch/etc/X11/xinit/xinitrc.d/nvidia-optimus.sh <<EOF > /dev/null
751# #!/bin/sh
752# xrandr --setprovideroutputsource modesetting NVIDIA-0
753# xrandr --auto
754# EOF
755
756# chmod +x /mnt/arch/etc/X11/xinit/xinitrc.d/nvidia-optimus.sh
757
758
759# Monitor Scale related.
760sudo tee /mnt/arch/etc/X11/xinit/xinitrc.d/70-xrandr-scale.sh <<'EOF' > /dev/null
761#!/usr/bin/env sh
762
763set -e
764# Set the gnome scale to something larger than what we really want so we can scale it down.
765gsettings set org.gnome.desktop.interface scaling-factor 2
766# Get the name of the first connected display's port.
767PRI_PORT="$(xrandr | grep -v disconnected | grep connected | cut -d' ' -f1)"
768# Set the scale.
769xrandr --output ${PRI_PORT} --scale 1.35x1.35
770# Reset "panning" so xrandr will tell us the virtual resolution of the screen.
771xrandr --output ${PRI_PORT} --panning 0x0
772# Get the virtual resolution of the screen.
773SCALED_RES="$(xrandr | grep ${PRI_PORT} | sed -E 's/.* ([0-9]+x[0-9]+).*/\1/')"
774# Set the panning size to the virtual resolution of the screen to force it to properly fill the screen & avoid improper mou$
775xrandr --output ${PRI_PORT} --panning ${SCALED_RES}
776EOF
777
778sudo chmod +x /mnt/arch/etc/X11/xinit/xinitrc.d/70-xrandr-scale.sh
779
780
781
782# #-----------------------------------------------------------------------------------------------------------------------
783# # KVM + VFIO + libvirt + qemu -- GPU passthrough.
784# # Older guide:
785# # http://www.se7ensins.com/forums/threads/how-to-setup-a-gaming-virtual-machine-with-gpu-passthrough-qemu-kvm-libvirt-and-vfio.1371980/
786# # Newer guide:
787# # http://chanster.net/article/2016/03/05/qemu-gpu-passthrough/
788
789# printf "\n\nConfiguring mkinitcpio to load the vfio related modules.\n"
790# sed -Ei 's/^MODULES=".*/MODULES="i915 vfio vfio_iommu_type1 vfio_pci vfio_virqfd"/' /mnt/arch/etc/mkinitcpio.conf
791
792# # DETACH GPU FROM HOST
793# if [ -e /mnt/arch/etc/modprobe.d/vfio.conf ]; then
794# cp -b --preserve /mnt/arch/etc/modprobe.d/vfio.conf{,-bak}
795# sed -Ei '/^options/d' /mnt/arch/etc/modprobe.d/vfio.conf
796# fi
797# echo "options vfio-pci ids=${NVIDIA_DEV_ID}" | tee /mnt/arch/etc/modprobe.d/vfio.conf
798
799# tee /mnt/arch/etc/modprobe.d/00-modprobe.conf <<'EOF' > /dev/null
800# blacklist radeon
801# blacklist nvidia
802# EOF
803
804# # Bind the addon GPU to VFIO.
805# # ls /sys/bus/pci/devices | grep -i '01:00.0\|01:00.1'
806# echo "DEVICES=\"0000:${NVIDIA_BUS_ID}\"" > /mnt/arch/usr/local/etc/vfio-devices
807
808# tee /mnt/arch/usr/local/bin/vfio-bind <<'EOF' > /dev/null
809# #!/bin/sh
810# # This script loads the vfio-pci module, locates the devices passed in as arguments and rebinds them to vfio-pci.
811# # http://chanster.net/article/2016/03/05/qemu-gpu-passthrough/
812# modprobe vfio-pci
813# for dev in "$@"; do
814# vendor=$(cat /sys/bus/pci/devices/${dev}/vendor)
815# device=$(cat /sys/bus/pci/devices/${dev}/device)
816# if [ -e /sys/bus/pci/devices/${dev}/driver ]; then
817# echo ${dev} > /sys/bus/pci/devices/${dev}/driver/unbind
818# fi
819# echo ${vendor} ${device} > /sys/bus/pci/drivers/vfio-pci/new_id
820# done
821# EOF
822# chmod +x /mnt/arch/usr/local/bin/vfio-bind
823
824# tee /mnt/arch/usr/lib/systemd/system/vfio-bind.service <<'EOF' > /dev/null
825# [Unit]
826# Description=Binds devices to vfio-pci
827# After=syslog.target
828
829# [Service]
830# EnvironmentFile=-/usr/local/etc/vfio-bind
831# Type=oneshot
832# RemainAfterExit=yes
833# ExecStart=-/usr/local/bin/vfio-bind $DEVICES
834
835# [Install]
836# WantedBy=multi-user.target
837# EOF
838
839
840
841#-----------------------------------------------------------------------------------------------------------------------
842# Configure Boot.
843
844printf "\n\nAdding the multidecrypt mkinitcpio hook.\n"
845tee /etc/initcpio/hooks/multidecrypt <<EOF > /dev/null
846#!/usr/bin/ash
847
848run_hook() {
849 # set -x
850
851 modprobe -a -q dm-crypt >/dev/null 2>&1
852 modprobe -a -q loop >/dev/null 2>&1
853
854 [ "\${quiet}" = "y" ] && CSQUIET=">/dev/null"
855
856 if [ -z "\${multidecrypt}" ]; then
857 err "No dm-crypt luks devices specified for multidecrypt, aborting..."
858 exit 1
859 fi
860
861 # Loop until the user provides a valid password.
862 while ! eval cryptsetup open --type luks "/${KEYFILE_NAME}" "${KEYFILE_NAME}" \${CSQUIET}; do
863 sleep 2;
864 done
865
866 if [ ! -e "${KEYFILE_MAPPED}" ]; then
867 err "${KEYFILE_NAME} decryption failed, aborting..."
868 exit 1
869 fi
870
871 luksdevnum=1
872 mapdevnum=1
873 for luksdev in \${multidecryptswap//:/ }; do
874 if resolved=\$(resolve_device "\${luksdev}" \${rootdelay}); then
875 eval cryptsetup open --type luks \
876 --key-file "${KEYFILE_MAPPED}" \
877 --keyfile-offset \$(((\$luksdevnum-1)*512)) \
878 --keyfile-size 512 \
879 \${resolved} \
880 swap\${mapdevnum} \
881 \${CSQUIET}
882 # swapDevice \
883
884 if [ ! -e "/dev/mapper/swap\${mapdevnum}" ]; then
885 err "swap\${mapdevnum} creation failed, continuing with other specified devices..."
886 fi
887 else
888 err "Could not resolve \${luksdev}, continuing with other specified devices..."
889 fi
890 let luksdevnum++
891 let mapdevnum++
892 done
893
894 mapdevnum=1
895 for luksdev in \${multidecrypt//:/ }; do
896 if resolved=\$(resolve_device "\${luksdev}" \${rootdelay}); then
897 eval cryptsetup open --type luks \
898 --key-file "${KEYFILE_MAPPED}" \
899 --keyfile-offset \$(((\$luksdevnum-1)*512)) \
900 --keyfile-size 512 \
901 \${resolved} \
902 container\${mapdevnum} \
903 \${CSQUIET}
904
905 if [ ! -e "/dev/mapper/container\${mapdevnum}" ]; then
906 err "container\${mapdevnum} creation failed, continuing with other specified devices..."
907 fi
908 else
909 err "Could not resolve \${luksdev}, continuing with other specified devices..."
910 fi
911 let luksdevnum++
912 let mapdevnum++
913 done
914
915 # Clean up.
916 cryptsetup close "${KEYFILE_NAME}"
917}
918
919# vim: set ft=sh ts=4 sw=4 et:
920EOF
921
922
923printf "\n\nAdding the multidecrypt mkinitcpio install.\n"
924tee /etc/initcpio/install/multidecrypt <<EOF > /dev/null
925#!/bin/bash
926
927build() {
928 local mod
929
930 add_module dm-crypt
931 if [[ \${CRYPTO_MODULES} ]]; then
932 for mod in \${CRYPTO_MODULES}; do
933 add_module "\$mod"
934 done
935 else
936 add_all_modules '/crypto/'
937 fi
938
939 # add loop module for mounting of keyfile
940 add_module loop
941
942 add_binary "cryptsetup"
943 add_binary "dmsetup"
944 add_file "/usr/lib/udev/rules.d/10-dm.rules"
945 add_file "/usr/lib/udev/rules.d/13-dm-disk.rules"
946 add_file "/usr/lib/udev/rules.d/95-dm-notify.rules"
947 add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules"
948
949 add_file "/boot/${KEYFILE_NAME}" "/${KEYFILE_NAME}"
950
951 add_runscript
952}
953
954help() {
955 cat <<HELPEOF
956This hook allows for startup decryption of multiple dm-crypt luks encrypted
957devices. Users should specify the devices to be unlocked using:
958
959 'multidecrypt=device[[:device]...]'
960
961on the kernel command line, where 'device' is the path to the raw device,
962specified using PARTUUID or some other means. Devices will be available as
963/dev/mapper/container[1,2,3...] etc.
964
965The hook expects a dm-crypt luks encrypted file called /boot/${KEYFILE_NAME} to
966exist. This keyfile contains a concatenation of 4096 bit keys for each
967encrypted device in the same order as specified in the multidecrypt kernel
968command line argument.
969
970If decryption of one of the devices fails, the hook will attempt to continue
971to decrypt any other specified devices. This is useful for btrfs software
972raid if a device has failed as an example.
973
974You will be prompted for the password to the ${KEYFILE_NAME} container at runtime.
975This means you must have a keyboard available to input it, and you may need the
976keymap hook as well to ensure that the keyboard is using the layout you expect.
977HELPEOF
978}
979
980# vim: set ft=sh ts=4 sw=4 et:
981EOF
982
983
984cp -Rf /etc/initcpio/{hooks,install} /mnt/arch/etc/initcpio/
985
986
987printf "\n\nConfiguring mkinitcpio to use multidecrypt hook.\n"
988sed -i 's/^HOOKS=.*/HOOKS="base udev multidecrypt mdadm_udev resume modconf block filesystems fsck btrfs keyboard autodetect"/' \
989 /mnt/arch/etc/mkinitcpio.conf
990
991
992printf "\n\nGathering partition UUIDs for both btrfs partitions used in RAID 0 (stripe)."
993# Will be mounted by multidecrypt.
994PART_DATA1_PARTUUID="$(blkid -s PARTUUID -o value "${PART_DATA1}")"
995PART_DATA2_PARTUUID="$(blkid -s PARTUUID -o value "${PART_DATA2}")"
996PART_SWAP1_PARTUUID="$(blkid -s PARTUUID -o value "${PART_SWAP1}")"
997PART_SWAP2_PARTUUID="$(blkid -s PARTUUID -o value "${PART_SWAP2}")"
998SWAP_UUID="$(blkid -s UUID -o value "${SWAP_RAID}")"
999# Will be mounted by BTRFS.
1000ROOT_UUID="$(blkid -s UUID -o value "${DATA1_MAPPED}")"
1001
1002
1003# Get rid fo the mkinitcpio error, "ERROR: file not found: 'fsck.btrfs'".
1004rm -f /bin/fsck.btrfs
1005
1006
1007printf "\n\nInstalling boot control.\n"
1008arch-chroot /mnt/arch /bin/bash <<EOF
1009# set -x
1010
1011# Make sure efivars are loaded.
1012mount -t efivarfs efivarfs /sys/firmware/efi/efivars
1013
1014# Regenerate initrd image
1015mkinitcpio -p linux
1016
1017
1018# Prune linux boot entries.
1019set +e
1020IFS='
1021'
1022for ITEM in \$(efibootmgr); do
1023 echo "scanning \${ITEM}..."
1024
1025 # If statements with []'s are not working properly here so we'll just use "test" directly.
1026 test "\${ITEM#*inux}" == "\${ITEM}" && continue
1027
1028 BOOTNUM="\$(echo "\${ITEM}" | sed -e 's/^[Bb]oot\([a-zA-Z0-9]*\).*/\1/')"
1029
1030 echo "Removing boot num \${BOOTNUM}, entry: \${ITEM}."
1031 efibootmgr --bootnum "\${BOOTNUM}" --delete-bootnum
1032 echo "Done removing boot entry: \${ITEM}."
1033done
1034set -e
1035
1036
1037# # Install EFI boot image.
1038# efibootmgr \
1039# --create \
1040# --disk ${DEV_DRIVE1} \
1041# --part ${PARTNUM_EFI} \
1042# --label "Arch Linux" \
1043# --loader /vmlinuz-linux \
1044# --timeout 2 \
1045# --unicode "multidecryptswap=PARTUUID=${PART_SWAP1_PARTUUID}:PARTUUID=${PART_SWAP2_PARTUUID} multidecrypt=PARTUUID=${PART_DATA1_PARTUUID}:PARTUUID=${PART_DATA2_PARTUUID} root=UUID=${ROOT_UUID} rw rootflags=subvol=@ resume=UUID=${SWAP_UUID} initrd=\\intel-ucode.img initrd=\\initramfs-linux.img"
1046
1047bootctl install
1048
1049exit 0
1050EOF
1051
1052
1053# systemd-boot arch linux config.
1054tee /mnt/arch/boot/loader/entries/arch.conf <<EOF > /dev/null
1055title Arch Linux
1056linux /vmlinuz-linux
1057initrd /intel-ucode.img
1058initrd /initramfs-linux.img
1059# "iommu=pt" : to avoid DMAR errors.
1060# "i915.enable_hd_vgaarb=1" : use this if you're not getting monitor sync when the VM starts, because there's probably a
1061# problem with VGA arbitration or the device ROM; this addresses the former. You may need to use linux-vfio kernel.
1062options multidecryptswap=PARTUUID=${PART_SWAP1_PARTUUID}:PARTUUID=${PART_SWAP2_PARTUUID} multidecrypt=PARTUUID=${PART_DATA1_PARTUUID}:PARTUUID=${PART_DATA2_PARTUUID} root=UUID=${ROOT_UUID} rw rootflags=subvol=@ resume=UUID=${SWAP_UUID} quiet pcie_acs_override=downstream rd.modules-load=vfio-pci iommu=pt intel_iommu=on
1063EOF
1064
1065
1066# systemd-boot loader config.
1067tee /mnt/arch/boot/loader/loader.conf <<EOF > /dev/null
1068timeout 0
1069default arch
1070EOF
1071
1072
1073
1074#-----------------------------------------------------------------------------------------------------------------------
1075# Setup snapshot system.
1076# http://ramsdenj.com/2016/04/05/Using-Btrfs-for-Easy-Backup-and-Rollback.html
1077
1078printf "\n\nSetup btrfs snapshot management.\n"
1079
1080arch-chroot /mnt/arch /bin/bash <<-EOC
1081# Remove unwanted grub hook since we do not use grub, which will avoid a safe-to-ignore error that will show up each
1082# time snap-pac is updated.
1083rm -f /usr/share/libalpm/hooks/99_grub-config.hook
1084
1085# Create the snapper configuration files for root and home.
1086snapper --no-dbus -c root create-config /
1087snapper --no-dbus -c home create-config /home
1088
1089# Snapper makes unwanted subvols.
1090btrfs sub delete /.snapshots
1091btrfs sub delete /home/.snapshots
1092
1093# Create desirable snapshot subvols for root & home.
1094btrfs sub create /mnt/btrfs-pool/@snapshots/root
1095btrfs sub create /mnt/btrfs-pool/@snapshots/home
1096
1097# Create the paths snapper will be looking for & mount the above subvols to them.
1098mkdir /home/.snapshots
1099mkdir /.snapshots
1100mount -t btrfs -o defaults,compress=lzo,subvol=@snapshots/home "${DATA1_MAPPED}" /home/.snapshots
1101mount -t btrfs -o defaults,compress=lzo,subvol=@snapshots/root "${DATA1_MAPPED}" /.snapshots
1102EOC
1103
1104# Regen fstab, pruning out efivars, gvfsd-fuse & external media.
1105printf "\n\nRegenerating fstab.\n"
1106# # Breakdown of actions:
1107# # 1. Generates the new fstab.
1108# # 2. Inverse the file.
1109# # 3. Removes all lines containing "efivars", "gvfsd-fuse" or "/run/media", as well as the line below them.
1110# # 4. Inverse the file again.
1111# # 5. Write the file to /etc/fstab.
1112# genfstab -pU /mnt/arch | tac | sed '/(efivarfs|gvfsd-fuse|\/run\/media)/I,+2 d' | tac | tee /mnt/arch/etc/fstab
1113genfstab -pU /mnt/arch > /mnt/arch/etc/fstab
1114cat /mnt/arch/etc/fstab
1115
1116
1117
1118#-----------------------------------------------------------------------------------------------------------------------
1119# Setup the users.
1120
1121printf "\n\nPlease enter below the desired root password.\n"
1122arch-chroot /mnt/arch /bin/bash -c 'passwd'
1123
1124printf "\n\nAdding user '%s'.\n" "${DESIRED_USERNAME}"
1125arch-chroot /mnt/arch /bin/bash -c "groups '${DESIRED_USERNAME}' > /dev/null 2>&1 || useradd --create-home --groups wheel,storage,power,users,audio,video,optical --shell /bin/bash ${DESIRED_USERNAME}"
1126printf "\n\nPlease enter below the desired password for ${DESIRED_USERNAME}.\n"
1127arch-chroot /mnt/arch /bin/bash -c "passwd ${DESIRED_USERNAME}"
1128
1129printf "\n\nAllowing ${DESIRED_USERNAME} to sudo without a password.\n"
1130sudo tee "/mnt/arch/etc/sudoers.d/${DESIRED_USERNAME}" <<EOF > /dev/null
1131${DESIRED_USERNAME} ALL=NOPASSWD: ALL
1132EOF
1133
1134
1135
1136#-----------------------------------------------------------------------------------------------------------------------
1137# Add a convenience script.
1138
1139# NOTE: Short URL resolves to: https://gist.github.com/redeemed2011/3387d18d5e8f0274b0e3/raw/post-install-additions.sh
1140wget https://goo.gl/HGlSC3 -O "/mnt/arch/home/${DESIRED_USERNAME}/post-install-additions.sh"
1141arch-chroot /mnt/arch /bin/bash <<EOC
1142chown '${DESIRED_USERNAME}:${DESIRED_USERNAME}' '/home/${DESIRED_USERNAME}/post-install-additions.sh'
1143chmod +x '/home/${DESIRED_USERNAME}/post-install-additions.sh'
1144EOC
1145
1146
1147
1148#-----------------------------------------------------------------------------------------------------------------------
1149# Cleanup.
1150
1151unmount_all