#!/bin/bash run_in_chroot(){ chroot '/target/' /bin/bash -c "${1}" } prepare_install(){ echo -n "Checking network..." if ! ping -c 4 deb.debian.org &>/dev/null;then tmux popup -h 75% -w 75% -E "nmtui-connect" fi clear echo -n "Waiting on network" while ! timeout 1 ping -c 1 deb.debian.org &> /dev/null;do printf "%c" "." sleep 1 done clear } menu(){ menu_select=$(dialog --ok-label 'Menu' --nocancel --clear --stdout \ --title 'Device Type' \ --menu 'Select the desired configuration page' 0 0 4 \ root_setup 'Setup root user' \ user_setup 'Setup default user' \ device_type_setup 'Select installation type' \ hostname_setup 'Set hostname' \ partition_setup 'Partition disk' \ 3>&1 2>&3 3>&-) } root_setup(){ root_pass='' root_pass_confirm='' root_info=$(dialog --ok-label 'Submit' --nocancel --clear --stdout \ --title "Root Setup" \ --form "Please enter the following information for the root user" \ 0 0 0 \ "Password:" 1 1 "$root_pass" 1 25 40 0 \ "Password (confirm):" 2 1 "$root_pass_confirm" 2 25 40 0 \ 3>&1 2>&3 3>&-) root_info_array=(${root_info}) root_pass="${root_info_array[0]}" root_pass_confirm="${root_info_array[1]}" } user_setup(){ user_realname='' user_name='' user_pass='' user_pass_confirm='' user_realname=$(dialog --ok-label 'Submit' --nocancel --stdout --clear \ --title 'Default User Full Name' \ --inputbox 'Enter default user`s Full Name' 10 30 \ 3>&1 2>&3 3>&-) user_info=$(dialog --ok-label 'Submit' --nocancel --clear --stdout \ --title 'Default User' \ --form 'Please enter the following information for the default user' \ 0 0 3 \ 'Username:' 1 1 "$user_name" 1 25 40 0 \ 'Password:' 2 1 "$user_pass" 2 25 40 0 \ 'Password (confirm):' 3 1 "$user_pass_confirm" 3 25 40 0 \ 3>&1 2>&3 3>&-) user_info_array=(${user_info}) user_name="${user_info_array[0]}" user_pass="${user_info_array[1]}" user_pass_confirm="${user_info_array[2]}" } device_type_setup(){ device_type=$(dialog --ok-label 'Submit' --nocancel --clear --stdout \ --title 'Device Type' \ --menu 'Please select the device type to use for the installation' 0 0 4 \ user 'single-user desktop environment' \ common 'multi-user desktop environment' \ server 'headless environment intended for remote access' \ kiosk 'public desktop environment' \ 3>&1 2>&3 3>&-) } sanitize_hostname(){ printf "%s" "${1}" | tr -dc '\-[:alnum:]\n\r' | tr '[:upper:]' '[:lower:]' } hostname_setup(){ if [ "${device_type}" = "user" ];then sys_role="${user_name}" else sys_role="${device_type}" fi sys_manufacturer=`dmidecode -s system-manufacturer` sys_model=`dmidecode -s system-product-name` sys_serialno=`dmidecode -s system-serial-number` dest_hostname=`printf "%s-%s%s-%s" "${sys_role}" "${sys_manufacturer}" "${sys_model}" "${sys_serialno}"` dest_hostname=`sanitize_hostname "${dest_hostname}"` dest_hostname=$(dialog --ok-label 'Submit' --nocancel --clear --stdout \ --title 'Hostname' \ --inputbox 'Customize the hostname below' 0 0 "${dest_hostname}" \ 3>&1 2>&3 3>&-) dest_hostname=`sanitize_hostname "${dest_hostname}"` } automatic_partitioner(){ device_menu=() for blk_device in $(lsblk -no PATH --nodeps); do device_menu+=("$(lsblk -no PATH --nodeps ${blk_device})") device_menu+=("$(lsblk -no MODEL,SIZE --nodeps ${blk_device})") done dest_dev=$(dialog --ok-label "Submit" --nocancel --stdout \ --menu 'Select Install Destination' \ 20 0 20 \ "${device_menu[@]}" \ 3>&1 2>&3 3>&-) root_gb=$(dialog --ok-label 'Submit' --nocancel --clear --stdout \ --title "Root Partition Size" \ --rangebox "Please set the root partition size in GB" \ 0 0 10 2000 100 \ 3>&1 2>&3 3>&-) if [[ ${dest_dev} = *[0-9] ]];then part_sep="p" else part_sep="" fi efi_part="${dest_dev}${part_sep}1" boot_part="${dest_dev}${part_sep}2" swap_part="${dest_dev}${part_sep}3" root_part="${dest_dev}${part_sep}4" home_part="${dest_dev}${part_sep}5" luks_pass='' luks_pass_confirm='' luks_info=$(dialog --ok-label 'Submit' --nocancel --stdout \ --title "luks Setup" \ --form "Please enter the following information for luks encryption" \ 0 0 0 \ "Password:" 1 1 "$luks_pass" 1 25 40 0 \ "Password (confirm):" 2 1 "$luks_pass_confirm" 2 25 40 0 \ 3>&1 2>&3 3>&-) luks_info_array=(${luks_info}) luks_pass="${luks_info_array[0]}" luks_pass_confirm="${luks_info_array[1]}" #new gpt label parted "${dest_dev}" mklabel gpt --script --fix #efi parted "${dest_dev}" mkpart efi fat32 0MB 256MB --script --fix --align optimal #boot parted "${dest_dev}" mkpart boot btrfs 256MB 768MB --script --fix --align optimal #swap mem_mb=`grep MemTotal /proc/meminfo | awk '{print $2 "/1024"}' | bc` swap_end=`printf "768+%s\n" "${mem_mb}" | bc` parted "${dest_dev}" mkpart swap linux-swap 768MB "${swap_end}MB" --script --fix --align optimal #root root_mb=`printf "%s*1024\n" "${root_gb}" | bc` root_end=`printf "%s+%s\n" "${swap_end}" "${root_mb}" | bc` parted "${dest_dev}" mkpart root btrfs "${swap_end}MB" "${root_end}MB" --script --fix --align optimal #home parted "${dest_dev}" mkpart home btrfs "${root_end}MB" 100% --script --fix --align optimal } #manual_partitioner(){ # target_dev='' # until [ "${target_dev}" == 'done' ];do # device_menu=() # for blk_device in $(lsblk -no PATH --nodeps); do # device_menu+=("$(lsblk -no PATH --nodeps ${blk_device})") # device_menu+=("$(lsblk -no MODEL,SIZE --nodeps ${blk_device})") # done # device_menu+=("done") # device_menu+=("Proceed to selecting disks") # target_dev=`dialog --menu 'Select Install Destination' 20 0 20 "${device_menu[@]}" 2>&1 >/dev/tty` # tmux popup -h 75% -w 75% -E "cfdisk ${target_dev}" # done # for blk_parts in $(lsblk -rno PATH,TYPE | grep -v 'disk$\|crypt$' | awk '{ print $1 } '); do # device_menu+=("$(lsblk -rno PATH --nodeps ${blk_device})") # device_menu+=("$(lsblk -rno MODEL,SIZE --nodeps ${blk_device})") # done #} disk_setup(){ # partition_method=$(dialog --ok-label 'Submit' --nocancel --stdout \ # --title 'Partition Method' \ # --menu 'Please select the partition method to use for the installation' 0 0 4 \ # manual 'Manually partition installation' \ # automatic "Use recommended partitioning scheme [DESTRUCTIVE]" \ # 3>&1 2>&3 3>&-) # if [ "${partition_method}" == "manual" ];then # manual_partitioner # elif [ "${partition_method}" == "automatic" ] automatic_partitioner # fi } encrypt_partition(){ echo -n "${3}" | cryptsetup luksFormat "${1}" - echo -n "${3}" | cryptsetup luksOpen "${1}" "${2}_crypt" - } get_part_uuid(){ lsblk -drno UUID "${1}" } format_partitions(){ #efi partition mkfs.vfat "${efi_part}" #boot partition mkfs.btrfs -f "${boot_part}" -L boot #swap partition encrypt_partition "${swap_part}" swap "${luks_pass}" mkswap /dev/mapper/swap_crypt #root partition encrypt_partition "${root_part}" root "${luks_pass}" mkfs.btrfs /dev/mapper/root_crypt -L root #home partition encrypt_partition "${home_part}" home "${luks_pass}" mkfs.btrfs /dev/mapper/home_crypt -L home get_uuids } get_uuids(){ #get uuids efi_uuid=`get_part_uuid "${efi_part}"` boot_uuid=`get_part_uuid "${boot_part}"` swap_luks_uuid=`get_part_uuid "${swap_part}"` root_luks_uuid=`get_part_uuid "${root_part}"` home_luks_uuid=`get_part_uuid "${home_part}"` } create_filesystem(){ #create and mount root target_dir="/target" mkdir -p "${target_dir}" mount "/dev/mapper/root_crypt" "${target_dir}" # btrfs property set "${target_dir}/" compression zstd #create and mount boot mkdir -p "${target_dir}/home" mount "/dev/mapper/home_crypt" "${target_dir}/home" # btrfs property set "${target_dir}/home/" compression zstd #create and mount boot mkdir -p "${target_dir}/boot" mount "${boot_part}" "${target_dir}/boot" # btrfs property set "${target_dir}/boot/" compression zstd #create and mount efi mkdir -p "${target_dir}/boot/efi" mount "${efi_part}" "${target_dir}/boot/efi" #install base system debootstrap --arch "$(dpkg --print-architecture)" unstable "${target_dir}" https://deb.debian.org/debian mkdir '/target/etc/crypttab.d' for k in {home,swap};do keyfile_path="/target/etc/crypttab.d/${k}_key" openssl genrsa -out "${keyfile_path}" 4096 chmod -v 0400 "${keyfile_path}" chown root:root "${keyfile_path}" case "${k}" in swap) keyfile_device="${swap_part}" ;; home) keyfile_device="${home_part}" ;; esac echo -n "${luks_pass}" | cryptsetup luksAddKey "${keyfile_device}" "${keyfile_path}" - done #crypttab for luks-encrypted partitions cat > "${target_dir}/etc/crypttab" << EOF root_crypt UUID=${root_luks_uuid} none luks,discard swap_crypt UUID=${swap_luks_uuid} /etc/crypttab.d/swap_key luks,swap,discard home_crypt UUID=${home_luks_uuid} /etc/crypttab.d/home_key luks,discard EOF #fstab for filesystem mounts cat > "${target_dir}/etc/fstab" << EOF /dev/mapper/root_crypt / btrfs defaults,compress 0 1 /dev/mapper/home_crypt /home btrfs defaults,compress 0 1 /dev/mapper/swap_crypt none swap sw 0 0 UUID=${boot_uuid} /boot btrfs defaults,compress 0 2 UUID=${efi_uuid} /boot/efi vfat umask=0077 0 1 EOF #configure apt cat > "${target_dir}/etc/apt/sources.list" << EOF deb https://deb.debian.org/debian/ unstable main contrib non-free non-free-firmware deb-src https://deb.debian.org/debian/ unstable main contrib non-free non-free-firmware EOF curl -fsSL 'https://apt.pogmom.me/public.gpg' | gpg --dearmor -o "${target_dir}/usr/share/keyrings/pogmom.gpg" mkdir -p "${target_dir}/etc/apt/sources.list.d" echo "deb [signed-by=/usr/share/keyrings/pogmom.gpg] https://apt.pogmom.me/ unstable main" | tee "${target_dir}/etc/apt/sources.list.d/pogmom.list" } prepare_chroot(){ for b in {proc,sys,dev,run};do mount --make-rslave --rbind "/${b}" "/target/${b}" done run_in_chroot "apt-get update" echo "America/Los_Angeles" > /target/etc/timezone # run_in_chroot "DEBIAN_FRONTEND=noninteractive apt-get install -y btrfs-progs locales passwd zram-tools rsync network-manager curl linux-image-amd64 firmware-linux grub-efi grub-pc-bin cryptsetup-initramfs systemd-cryptsetup" run_in_chroot "DEBIAN_FRONTEND=noninteractive apt-get install -y pogmom-utils pogmom-desktop pogmom-apps linux-image-amd64 firmware-linux grub-efi grub-pc-bin cryptsetup-initramfs systemd-cryptsetup" #TODO: split pogmom-utils into pogmom-utils and pogmom-essential case "$(hostnamectl chassis)" in laptop) chassis_packages="tlp" ;; esac run_in_chroot "DEBIAN_FRONTEND=noninteractive apt-get install -y ${chassis_packages} isenkram --no-install-recommends" run_in_chroot "DEBIAN_FRONTEND=noninteractive isenkram-autoinstall-firmware" # drop files into the root filesystem # rsync -aSH "${SCRIPT_ROOT}"/payload/ /target/ # do stuff with the payload #zswap # echo -e 'ALGO=zstd\nPERCENT=60' | tee -a /target/etc/default/zramswap #zstd is unavailable in kernel 6.12 echo -e 'ALGO=lzo\nPERCENT=60' | tee -a /target/etc/default/zramswap #hostname echo "${dest_hostname}" > /target/etc/hostname cat > /target/etc/hosts << EOF 127.0.0.1 localhost 127.0.1.1 ${dest_hostname} EOF run_in_chroot "timedatectl set-local-rtc 0" run_in_chroot "dpkg-reconfigure tzdata locales keyboard-configuration" date > /target/root/install_date run_in_chroot "echo \"root:${root_pass}\" | chpasswd" run_in_chroot "useradd -c \"${user_realname}\" -m ${user_name}" run_in_chroot "echo \"${user_name}:${user_pass}\" | chpasswd" run_in_chroot "usermod -aG sudo ${user_name}" perl -i -pe 's/(GRUB_CMDLINE_LINUX_DEFAULT)="(.*)"/$1="$2 rd.luks.uuid='"${root_luks_uuid}"'"/' /target/etc/default/grub root_kernel_version=`run_in_chroot "uname -r"` run_in_chroot "update-initramfs -c -k all" run_in_chroot "update-grub && grub-install --root-directory / ${dest_dev}" } finalize(){ umount -R /target echo "Installation is complete, please remove installation medium and press ENTER to restart or CTRL+C to enter the console." read reboot }