arch/pkg/de-p1st-installer/de-p1st-installer.sh

328 lines
8.4 KiB
Bash
Executable File

#!/bin/bash
# load config
source installer.cfg || { exit 1; }
# load functions
source lib/util.sh || { exit 1; }
source lib/user-input.sh || { exit 1; }
source lib/block-device.sh || { exit 1; }
function check_network() {
echo "Sending ping to wikipedia.de ..."
ping -c 1 wikipedia.de || {
echo "Pleas set up network access."
return 1
}
}
function increase_cow_space() {
# May be useful when running 'pacman -Syu' on the live medium.
# Usually not necessary!
# make sure that we are on a live medium:
findmnt /run/archiso/cowspace || {
echo "Not on live medium, did not increase cowspace!"
return 1
}
echo "Increasing cowspace partition of live medium ..."
mount -o remount,size=2G /run/archiso/cowspace || return $?
}
function get_user_input() {
# @post
# BIOS_TYPE (uefi or bios)
# KERNEL (linux or linux-lts)
# FS (BTRFS, EXT4, F2FS)
# HOSTNAME
# USERNAME, USER_PWD
# LUKS_PWD
get_block_devices_with_size || return $?
get_single_choice TARGET_BLOCK_DEVICE "Select target device for installation" BLOCK_DEVICE_SIZES || return $?
TMP1=('uefi' 'Newer mainboards' 'bios' 'Legacy BIOS on older mainboards')
get_single_choice BIOS_TYPE "Select your bios type" TMP1 || return $?
TMP1=('linux-lts' 'Long-Time-Stable Linux kernel' 'linux' 'Latest Linux kernel')
get_single_choice KERNEL "Select kernel version" TMP1 || return $?
TMP1=('BTRFS' 'Allows snapshots and dynamic extension of the FS' 'EXT4' 'Default FS of many distributions' 'F2FS' 'Flash-Friendly-FS for SSD or NVMe')
get_single_choice FS "Select filesystem to use" TMP1 || return $?
get_text_input HOSTNAME "Enter hostname:" || return $?
get_text_input USERNAME "Enter username:" || return $?
if [ -z "${USER_PWD}" ]; then
get_text_input USER_PWD "Enter a user password:" || return $?
get_text_input USER_PWD2 "Please enter the password again:" || return $?
[[ "${USER_PWD}" == "${USER_PWD2}" ]] || {
echo "Passwords did not match";
exit 1;
}
fi
if [ -z "${LUKS_PWD}" ]; then
get_text_input LUKS_PWD "Enter a disk encryption password:" || return $?
get_text_input LUKS_PWD2 "Please enter the password again:" || return $?
[[ "${LUKS_PWD}" == "${LUKS_PWD2}" ]] || {
echo "Passwords did not match";
exit 1;
}
fi
}
function get_cpu_vendor() {
# @post
# CPU_VENDOR ("amd", "intel", "none")
if [ -z "${CPU_VENDOR}" ]; then
# if CPU_VENDOR has no value yet, ask user for input!
local vendor_id
vendor_id=$(cat /proc/cpuinfo | grep vendor_id | head -1 | sed 's|vendor_id\s*:\s*||')
if [ "$vendor_id" = "AuthenticAMD" ]; then
CPU_VENDOR="amd"
elif [ "$vendor_id" = "GenuineIntel" ]; then
CPU_VENDOR="intel"
else
echo "Unknown CPU vendor: $vendor_id"
return 1
fi
fi
}
function get_default_mount_options() {
# @pre
# FS
# @post
# FS_DEFAULT_MOUNT_OPTIONS (array)
FS_DEFAULT_MOUNT_OPTIONS=()
case "${FS}" in
BTRFS)
# compress=lzo: archwiki -> Btrfs#Compression
# "Enable compression (better performance, longer flash lifespan)"
FS_DEFAULT_MOUNT_OPTIONS+=('compress=lzo')
;;
EXT4)
# https://wiki.archlinux.org/index.php/Ext4#Enabling_metadata_checksums
# If the CPU supports SSE 4.2, make sure the crc32c_intel kernel module is loaded (TODO)
FS_DEFAULT_MOUNT_OPTIONS+=('metadata_csum')
;;
F2FS)
# When mounting the filesystem, specify compress_algorithm=(lzo|lz4|zstd|lzo-rle).
# Using compress_extension=txt will cause all txt files to be compressed by default.
FS_DEFAULT_MOUNT_OPTIONS+=('compress_algorithm=lz4')
;;
*)
echo "Filesystem $FS not yet supported!"
return 1
;;
esac
}
function choose_mount_options() {
# @pre
# FS
# @post
# FS_CHOSEN_MOUNT_OPTIONS (array)
case "${FS}" in
BTRFS)
# noatime, nodiratime:
# - The atime options do impact drive performance;
# - noatime implies nodiratime, one does not need to specify both;
# - The noatime option fully disables writing file access times to the drive every time you read a file.
# This works well for almost all applications, except for those that need to know if a file has been
# read since the last time it was modified.
TMP1=('noatime' "Don't write file/folder access times" 'on' 'ssd' 'Enable if using SSD/NVMe' 'off')
;;
EXT4)
TMP1=('noatime'" Don't write file/folder access times" 'on')
;;
F2FS)
TMP1=('noatime' "Don't write file/folder access times" 'on')
;;
*)
echo "Filesystem $FS not yet supported!"
return 1
;;
esac
get_multi_choice FS_CHOSEN_MOUNT_OPTIONS "Select mount options" TMP1 || return $?
}
function run_pacstrap() {
# @pre
# BIOS_TYPE
# KERNEL
# CPU_VENDOR
PKGS=()
case "${KERNEL}" in
linux)
PKGS+=("${KERNEL}" "${KERNEL}-headers")
;;
linux-lts)
PKGS+=("${KERNEL}" "${KERNEL}-headers")
;;
*)
echo "Not yet implemented!"
return 1
;;
esac
case "${CPU_VENDOR}" in
amd)
PKGS+=("${CPU_VENDOR}-ucode")
;;
intel)
PKGS+=("${CPU_VENDOR}-ucode")
;;
none)
true
;;
*)
echo "Not yet implemented!"
return 1
;;
esac
case "${BIOS_TYPE}" in
uefi)
PKGS+=('de-p1st-base-efi')
;;
bios)
echo "Not yet implemented"
return 1
;;
*)
echo "Not yet implemented!"
return 1
;;
esac
pacstrap /mnt "${PKGS[@]}" || return $?
}
function run_genfstab() {
# @pre
# FS
local fstab
fstab="$(genfstab -U /mnt)"
case "${FS}" in
BTRFS)
# Remove "subvolid=..." mount option but leave "subvol=..." mount option
fstab=$(printf "%s" "${fstab}" | sed 's/,subvolid=[^,\s]\+//') || return $?
# Check if fstab does still contain subvolid mount option
if printf "%s" "${fstab}" | grep -q 'subvolid='; then
echo "This should not happen!"
return 1
fi
;;
EXT4)
true
;;
F2FS)
true
;;
*)
echo "Filesystem $FS not yet supported!"
return 1
;;
esac
printf "%s" "${fstab}" > /mnt/etc/fstab || return $?
}
function config_hostname_and_hosts() {
# @pre
# HOSTNAME
# FQDN (optional, e.g. sub.domain.de)
# STATIC_IP (optional, e.g. 93.133.433.133)
# IPV6_CAPABLE (optional, e.g. 1)
echo "${HOSTNAME}" >/mnt/etc/hostname || return $?
# If the system has a permanent IP address, it should be used instead of 127.0.1.1.
# * https://wiki.archlinux.org/index.php/Installation_guide#Network_configuration
# Desirable entries IPv4/IPv6:
# * https://man.archlinux.org/man/hosts.5#EXAMPLES
# If FQDN not given, use $HOSTNAME.localdomain instead
FQDN="${FQDN:="${HOSTNAME}.localdomain"}"
# If STATIC_IP not given, use 127.0.1.1 instead
STATIC_IP="${STATIC_IP:='127.0.1.1'}"
echo "# The following lines are desirable for IPv4 capable hosts
127.0.0.1 localhost
# 127.0.1.1 is often used for the FQDN of the machine
${STATIC_IP} ${FQDN} ${HOSTNAME}" > /mnt/etc/hosts || return $?
if [ "${IPV6_CAPABLE}" = "1" ]; then
echo "
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters" >> /mnt/etc/hosts || return $?
fi
}
function main() {
# @pre
# bash libraries imported
# @post
# installation finished
check_network || return $?
# out: BIOS_TYPE, KERNEL, FS, HOSTNAME, USERNAME, USER_PWD, LUKS_PWD
get_user_input || return $?
# out: CPU_VENDOR
get_cpu_vendor || return $?
# in: FS
# out: FS_DEFAULT_MOUNT_OPTIONS
get_default_mount_options || return $?
# in: FS
# out: FS_CHOSEN_MOUNT_OPTIONS
choose_mount_options || return $?
# in: TARGET_BLOCK_DEVICE, BIOS_TYPE
# out: BOOT_PART, LUKS_PART
partition || return $?
# in: BIOS_TYPE, BOOT_PART, LUKS_PART, LUKS_PWD, FS
# out: DATA_PART
format || return $?
# Combine default and chosen mount options
TMP1=("${FS_DEFAULT_MOUNT_OPTIONS[@]}" "${FS_CHOSEN_MOUNT_OPTIONS[@]}") || return $?
# Join array elements by ","
join_by "," TMP1 FS_MOUNT_OPTIONS || return $?
echo "Mounting data partition with options: ${FS_MOUNT_OPTIONS}"
mount -o "${FS_MOUNT_OPTIONS}" "$DATA_PART" /mnt || return $?
echo "Mounting boot partition ..."
mkdir /mnt/boot || return $?
mount "$BOOT_PART" /mnt/boot || return $?
# in: BIOS_TYPE, KERNEL, CPU_VENDOR
run_pacstrap || return $?
# in: FS
run_genfstab || return $?
# in: HOSTNAME, FQDN (optional), STATIC_IP (optional), IPV6_CAPABLE (optional)
config_hostname_and_hosts || return $?
}
main "$@"