void-linux-pbp-installer/bootstrap

413 lines
8.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -o errexit
set -o pipefail
CONFIG="$(mktemp)"
declare -rgA default_values=(
["wifi_if"]="wlan0"
["install_dev"]="/dev/mmcblk2"
["repo"]="https://alpha.de.repo.voidlinux.org/current/aarch64"
["arch"]="aarch64"
["timezone"]="Europe/Zurich"
["keymap"]="uk"
["locale"]="en_US.UTF-8 UTF-8"
)
get_value() {
local white=$'\e[97m'
local nocolour=$'\e[0m'
local var_name="$1"
local prompt="$2"
local secure=""
if [ -n "$3" ]; then
secure="s"
fi
# shellcheck source=/dev/null
. "$CONFIG"
if [ -z "${!var_name}" ]; then
local def_val="${default_values[$var_name]}"
read -${secure}rp "$white$prompt [$def_val]:$nocolour " value
echo "export $var_name=\"${value:-$def_val}\"" >> "$CONFIG"
# shellcheck source=/dev/null
. "$CONFIG"
fi
echo "${!var_name}"
}
network() {
local wifi_if
wifi_if="$(get_value "wifi_if" "wifi interface name")"
ip link set "$wifi_if" up
nmcli device wifi list
local wifi_ssid
wifi_ssid="$(get_value "wifi_ssid" "wifi ssid")"
local wifi_pw
wifi_pw="$(get_value "wifi_pw" "wifi password" 1)"
nmcli con delete "$wifi_ssid" || true
nmcli device wifi connect "$wifi_ssid" password "$wifi_pw"
}
datetime() {
local datetime
datetime="$(get_value "datetime" "date and time now (like 2020-01-01 12:00)")"
date "+%Y--%m-%d %T" --set="$datetime"
hwclock --systohc
}
partition() {
local install_dev
install_dev="$(get_value "install_dev" "installation device")"
if [ ! -e "$install_dev" ]; then
echo "device node $install_dev does not exist"
exit 1
fi
sfdisk --force "$install_dev" << EOF
label: gpt
start=16MiB size=512MiB, type=bc13c2ff-59e6-4262-a352-b275fd6f7172
type=b921b045-1df0-41c3-af44-4c6f280d3fae
EOF
mkfs.vfat -F32 "$install_dev"p1
}
create_luks() {
local install_dev
install_dev="$(get_value "install_dev" "installation device")"
cryptsetup luksFormat "$install_dev"p2
}
open_luks() {
local install_dev
install_dev="$(get_value "install_dev" "installation device")"
cryptsetup open "$install_dev"p2 void
}
create_lvm() {
pvcreate /dev/mapper/void
vgcreate void /dev/mapper/void
lvcreate -L 48G void -n swap
lvcreate -l 100%FREE void -n root
}
open_lvm() {
vgchange --activate y
}
make_filesystems() {
mkswap -L SWAP /dev/void/swap
mkfs.xfs -f -L ROOT /dev/void/root
}
ensure_mount() {
local src="$1"
local dest="$2"
local with_rbind="$3"
local rbind=""
if [ ! -z "$with_rbind" ]; then
rbind="--rbind"
fi
mount $rbind "$src" "$dest"
if [ ! -z "$with_rbind" ]; then
mount --make-rslave "$dest"
fi
}
mount_filesystems() {
local install_dev
install_dev="$(get_value "install_dev" "installation device")"
ensure_mount "/dev/void/root" "/mnt"
mkdir -p /mnt/boot
ensure_mount "$install_dev"p1 "/mnt/boot"
swapon /dev/void/swap
}
install_basesystem() {
local repo
repo="$(get_value "repo" "package repository")"
local arch
arch="$(get_value "arch" "installation architecture")"
XBPS_ARCH=$arch xbps-install -S -y -r /mnt -R "$repo" base-system pinebookpro-base dracut lvm2 cryptsetup sudo stow << 'EOF'
y
EOF
cp /etc/resolv.conf /mnt/etc/
}
mount_special_filesystems() {
ensure_mount "/sys" "/mnt/sys" 1
ensure_mount "/dev" "/mnt/dev" 1
ensure_mount "/proc" "/mnt/proc" 1
ensure_mount "/tmp" "/mnt/tmp" 1
}
set_fstab() {
local install_dev
install_dev="$(get_value "install_dev" "installation device")"
local boot_uuid
boot_uuid="$(blkid | grep "${install_dev}p1" | awk '{print $2}')"
cat >/mnt/etc/fstab <<EOF
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0
$boot_uuid /boot vfat defaults 0 0
/dev/void/root / xfs defaults 0 0
/dev/void/swap swap swap defaults 0 0
EOF
}
set_boot_scr() {
local install_dev
install_dev="$(get_value "install_dev" "installation device")"
local boot_txt="/mnt/boot/boot.txt"
local boot_scr="/mnt/boot/boot.scr"
local boot_txt_mine="/mnt/boot/boot.txt.mine"
local mac
mac="$(echo -n "06"; dd bs=1 count=5 if=/dev/random 2>/dev/null | hexdump -v -e '/1 " %02X"' | tr '[:upper:]' '[:lower:]')"
local root_uuid
root_uuid="$(blkid | grep "${install_dev}p2" | awk '{print $2}' | sed 's/"//g')"
sed -i "s/setenv macaddr.*/setenv macadr $mac/g" "$boot_txt"
sed -i "s|root=PARTUUID=|root=/dev/void/root rd.auto=1 cryptdevice=${root_uuid}:lvm|g" "$boot_txt"
cp "$boot_txt" "$boot_txt_mine"
mkimage -A arm -O linux -T script -C none -n "boot script" -d "$boot_txt" "$boot_scr"
}
set_sudoers() {
sed -i 's/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g' /mnt/etc/sudoers
}
set_user() {
local user_name
user_name="$(get_value "user_name" "username")"
local user_pw
user_pw="$(get_value "user_pw" "user password" 1)"
chroot /mnt /bin/env -i \
user_name="$user_name" \
user_pw="$user_pw" \
/bin/bash <<"EOT"
useradd --groups wheel --create-home --shell /bin/bash --user-group $user_name
echo -e "$user_pw\n$user_pw" | passwd "$user_name"
EOT
}
set_base_conf() {
local timezone
timezone="$(get_value "timezone" "timezone")"
local keymap
keymap="$(get_value "keymap" "keymap")"
local hostname
hostname="$(get_value "hostname" "hostname")"
local locale
locale="$(get_value "locale" "locale")"
echo "$locale" >> /mnt/etc/default/libc-locales
chroot /mnt /bin/env -i \
timezone="$timezone" \
/bin/bash <<"EOT"
xbps-reconfigure -f glibc-locales
ln -sf /usr/share/zoneinfo/$timezone /etc/localtime
EOT
echo "$hostname" > /mnt/etc/hostname
cat >/mnt/etc/hosts <<EOF
#
# /etc/hosts: static lookup table for host names
#
#<ip-address> <hostname.domain.org> <hostname>
127.0.0.1 localhost.localdomain localhost $hostname
::1 localhost.localdomain localhost ip6-localhost $hostname
# End of file
EOF
cat >/mnt/etc/rc.conf <<EOF
# /etc/rc.conf - system configuration for void
# Set the host name.
#
# NOTE: it's preferred to declare the hostname in /etc/hostname instead:
# - echo myhost > /etc/hostname
#
#HOSTNAME="void-live"
# Set RTC to UTC or localtime.
#HARDWARECLOCK="UTC"
# Set timezone, availables timezones at /usr/share/zoneinfo.
TIMEZONE="$timezone"
# Keymap to load, see loadkeys(8).
KEYMAP="$keymap"
# Console font to load, see setfont(8).
#FONT="lat9w-16"
# Console map to load, see setfont(8).
#FONT_MAP=
# Font unimap to load, see setfont(8).
#FONT_UNIMAP=
# Amount of ttys which should be setup.
#TTYS=
EOF
}
tidy_up() {
sync
if grep -qe "/mnt " /proc/mounts; then
umount -R /mnt
fi
swapoff /dev/void/swap > /dev/null 2>&1 || true
vgchange --activate n
cryptsetup close void > /dev/null 2>&1 || true
}
full_install() {
datetime
network
partition
create_luks
open_luks
create_lvm
open_lvm
make_filesystems
mount_filesystems
install_basesystem
mount_special_filesystems
set_fstab
set_boot_scr
set_sudoers
set_user
set_base_conf
tidy_up
}
repair() {
open_luks
open_lvm
mount_filesystems
mount_special_filesystems
chroot /mnt bash
tidy_up
}
help() {
cat << EOF
the following commands are available:
datetime
network
partition
create_luks
open_luks
create_lvm
open_lvm
make_filesystems
mount_filesystems
install_basesystem
mount_special_filesystems
set_fstab
set_boot_scr
set_sudoers
set_user
set_base_conf
full_install
repair
tidy_up
help
ensure to understand what they are doing before using them
EOF
}
commands=(
"datetime"
"network"
"partition"
"create_luks"
"open_luks"
"open_lvm"
"make_filesystems"
"mount_filesystems"
"set_fstab"
"set_boot_scr"
"set_sudoers"
"set_user"
"set_base_conf"
"full_install"
"repair"
"tidy_up"
"help"
)
cmd_loop() {
local cmd
while [[ "$cmd" != "exit" ]]; do
read -rp "${white}>$nocolour " cmd
if [[ "${commands[*]}" == *"${cmd}"* ]]; then
$cmd
else
if [ "$cmd" != "exit" ]; then
echo "no such command"
fi
fi
done
}
trap tidy_up 0 SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
if [ "$1" == "full" ]; then
full_install
else
cmd_loop
fi