#!/bin/zsh # WARNING: this script will destroy data on the selected disk. # This script can be run by executing the following: # curl -sL https://git.io/vAoV8 | bash set -uo pipefail trap 's=$?; echo "$0: Error on line "$LINENO":"; exit $s' ERR password='' disk='' prompt_timezone='' efi_partition='' root_partition='' swap_partition='' locale='en_US.utf8' locale='en_US.utf8' ## timezone='Europe/Paris' timezone='America/New York' user='eric' hostname='Archbox' partition_devices=false format_devices=false help(){ printf 'install-arch - helper for installing arch\n' printf '\n ' printf 'basic arch installer.\n' printf 'I recommend you follow the directions at archlinux.org\n\n' printf 'if you have not become completely bored with the process of installing' printf 'Arch Linux manually. This script is no replacement for following the good' printf 'instructions that can be found here:\n' printf 'https://wiki.archlinux.org/index.php/Installation_guide\n' printf '\n ' printf 'The default behavior is to not do any partitioning or formtting' printf 'of the hard drives. Provide your devices to this script and it will' printf 'take it from there.\n' printf '\n ' printf 'If you decide to let it do the partitioning and formatting' printf 'The default behavior is to make an efi, swap and root on a' printf 'single device. If not provided on the commandline you will be' printf 'prompted for the everything necessary except locale which will' printf 'default to en_US. After this script is done follow the directions' printf 'here as needed.\n' printf 'https://wiki.archlinux.org/index.php/Installation_guide#Localization\n' printf '\n ' printf 'If you decide to let it do the partitions it will create' printf 'An efi partition a swap and a root partition on the drive given.' printf 'This script does not manage dual boot, ie. shared efi,' printf 'automatically. For that, do your own partitioning and formatting' printf 'of your drives and provide them on the commandline afterward' printf 'If auto partitioning is chosen, the partition names are' printf 'calculated from the device name.\n' printf 'efi, root and swap devices are only needed if auto formatting' printf 'is not used.\n' printf '\n ' printf " -d disk partition this disk, default is none.\n" printf " -s swap-dev swap device partition, default is none.\n" printf " -e efi-dev EFI device partition, default: $efi_partition\n" printf " -r root-dev root device partition, default: $root_partition\n" printf " -P partition devices. - default is no\n" printf " -F format devices. - default is no, true if partition is true.\n" printf " -l locale locale, default: $locale\n" printf " -n hostname hostname, default: $hostname\n" printf " -t timezone timezone, /usr/share/zoneinfo/. default: $timezone\n" printf " -T prompt for zoneinfo, default: $timezone\n" printf " -u user user name for new admin account, default $user\n" printf ' -h This help text.\n' printf '\n ' printf '\n ' exit } # $opt will hold the current option opt='' while getopts d:s:e:r:Fl:hl:u:n:t:TPh opt; do # loop continues till options finished # see which pattern $opt matches... case $opt in (d) disk=$OPTARG ;; (s) swap_partition=$OPTARG ;; (e) efi_partition=$OPTARG ;; (r) root_partition=$OPTARG ;; (n) hostname=$OPTARG ;; (P) partition_devices=true format_devices=true ;; (F) format_devices=true ;; (l) locale=$OPTARG ;; (t) timezone=$OPTARG ;; (T) prompt_timezone=true ;; (u) user=$OPTARG ;; (h) help ;; # matches a question mark # (and nothing else, see text) (\?) printf "Bad option:" # $* printf " " help return 1 ;; esac done (( OPTIND > 1 )) && shift $(( OPTIND - 1 )) ##printf Remaining arguments are: $* ### Get infomation from user as needed or asked.### if [ -z $hostname ];then hostname=$(dialog --stdout --inputbox "Enter hostname" 0 0) || exit 1 clear : ${hostname:?"hostname cannot be empty"} fi if [ -z $user ];then user=$(dialog --stdout --inputbox "Enter admin username" 0 0) || exit 1 clear : ${user:?"user cannot be empty"} fi # if [ -z $password ];then # password=$(dialog --stdout --passwordbox "Enter admin password" 0 0) || exit 1 # clear # : ${password:?"password cannot be empty"} # password2=$(dialog --stdout --passwordbox "Enter admin password again" 0 0) || exit 1 # clear # [[ "$password" == "$password2" ]] || ( echo "Passwords did not match"; exit 1; ) # fi typeset -a devicelist devicelist=(`lsblk -nx size -o name,size`) echo "devicelist is:" $devicelist # Not partitioning, and no drive partitions specified for installation if [[ -z $efi_partition && -z $partition_devices ]];then efi_partition=$(dialog --stdout --menu "Select efi-device" 0 0 0 "${devicelist[@]}") || exit 1 clear fi if [[ -z $root_partition && -z $partition_devices ]];then root_partition=$(dialog --stdout --menu "Select root-device" 0 0 0 "${devicelist[@]}") || exit 1 clear fi # if partitioning is on, but disk is not set. if [[ -z $disk && $partition_devices = true ]];then # if partitioning is on, but disk is not set. devicelist=(`lsblk -dplnx size -o name,size | grep -Ev "boot|rpmb|loop" | tac`) echo "devicelist is:" $devicelist device=$(dialog --menu --stdout "Select installation disk" 0 0 0 "${devicelist[@]}") || exit 1 clear else device=$disk fi # create the path to the zoneinfo timezone if we don't have one. if [[ -z $timezone || $prompt_timezone = true ]];then regions=(`ls /usr/share/zoneinfo`) echo "regions are:" $regions region=$(dialog --no-items --stdout --menu "Select Region" 0 0 0 "${regions[@]}") || exit 1 region_name=${regions[$region]} echo $regions[$region] echo $region_name cities=(`ls /usr/share/zoneinfo/$region`) echo "cities are:" $cities city=$(dialog --no-items --stdout --menu "Select City" 0 0 0 "${cities[@]}") || exit 1 timezone=${region_name}/${city} clear fi ### Set up logging ### exec 1> >(tee "stdout.log") exec 2> >(tee "stderr.log") timedatectl set-ntp true # partition the device/drive into efi, swap and root. if [[ ( -v $device && $partition_devices = true ) ]];then ### Setup the disk and partitions ### # swap_size=$(free --mebi | awk '/Mem:/ {printf $2}') # swap_end=$(( $swap_size + 129 + 1 ))MiB parted --script "${device}" -- mklabel gpt \ mkpart ESP fat32 1Mib 129MiB \ set 1 boot on \ # mkpart primary linux-swap 129MiB ${swap_end} \ # mkpart primary ext4 ${swap_end} 100% mkpart primary ext4 129MiB 100% # Simple globbing was not enough as on one device I needed to match /dev/mmcblk0p1 # but not /dev/mmcblk0boot1 while being able to match /dev/sda1 on other devices. efi_partition="$(ls ${device}* | grep -E "^${device}p?1$")" # swap_partition="$(ls ${device}* | grep -E "^${device}p?2$")" root_partition="$(ls ${device}* | grep -E "^${device}p?3$")" echo EFI boot is $efi_partition # echo swap is $swap_partition echo root is $root_partition fi # if we are supposed to partition or format. format, mkswap as needed. if [[ ($partition_devices = true || $format_devices = true) ]];then wipefs "${efi_partition}" mkfs.vfat -F32 "${efi_partition}" wipefs "${root_partition}" mkfs.ext4 "${root_partition}" if [[ ( -v $swap_partition ) ]];then wipefs "${swap_partition}" mkswap "${swap_partition}" fi fi if [[ -v $swap_partition ]];then echo Swap on $swap_partition swapon "${swap_partition}" fi echo "Mounting root at /mnt and boot at /mnt/boot" mount "${root_partition}" /mnt if [ ! -d /mnt/boot ];then mkdir /mnt/boot fi mount "${efi_partition}" /mnt/boot echo '=======================================================================' echo 'pacstrap. install the basics.' echo '=======================================================================' echo ' ' ### Install and configure the basic system ### # need network manager for easier network on reboot. # git to continue install from my pkgbuilds on github. # zsh to create my user account before reboot. # keep it simple here. just enough to have a base-system with the minimum tools # to reboot and configure. pacstrap /mnt base linux linux-firmware base-devel devtools sudo networkmanager git zsh dialog ### finish setting up the new system on /mnt so we can reboot. echo ' ' echo ' ' echo '=======================================================================' echo '=======================================================================' echo 'genfstab' genfstab -t PARTUUID /mnt >> /mnt/etc/fstab echo '' echo "${hostname}" > /mnt/etc/hostname cat >>/etc/hosts < /etc/locale.conf - locale-gen" echo " See https://wiki.archlinux.org/index.php/Installation_guide#Localization" arch-chroot /mnt echo "LANG=${locale}" > /mnt/etc/locale.conf arch-chroot /mnt locale-gen echo '=======================================================================' echo "usr/share/zoneinfo/${timezone} -> /etc/localtime" arch-chroot /mnt ln -sf /usr/share/zoneinfo/${timezone} /etc/localtime echo "hwclock --systohc" arch-chroot /mnt hwclock --systohc echo '=======================================================================' echo "setting up systemd-boot" echo "default is '"arch"' with acpi=off" arch-chroot /mnt bootctl install cat < /mnt/boot/loader/loader.conf timeout 10 default arch console-mode max EOF cat < /mnt/boot/loader/entries/arch.conf title Arch Linux linux /vmlinuz-linux initrd /initramfs-linux.img options root=PARTUUID=$(blkid -s PARTUUID -o value "$root_partition") rw acpi=off EOF arch-chroot /mnt bootctl list echo " " echo '=======================================================================' echo "create ${user} in wheel with zsh."w # create user in wheel with zsh. arch-chroot /mnt useradd -mU -s /usr/bin/zsh -G wheel,uucp,video,audio,storage,games,input ${user} arch-chroot /mnt chsh -s /usr/bin/zsh echo "Give sudo to wheel" # give sudo to wheel. cat < ./wheel %wheel ALL=(ALL) NOPASSWD: ALL EOF cp ./wheel /mnt/etc/sudoers.d/ echo '=======================================================================' echo "cloning Arch-Setup repo into ${user} for setup after reboot" # checkout my arch-setup repo so it's there and ready to go after reboot. arch-chroot -u "$user" /mnt git clone --remote-submodules --recurse-submodules https://github.com/ericgebhart/Arch-Setup.git /home/$user/Arch-Setup # I'm not sure why this doesn't work. But it doesn't even when it appears to. # Worst case it results in a core dump or kernel smashing... # echo '=======================================================================' # echo "Setting passwords for root and ${user}" # echo "${user}:${password}" | chpasswd --root /mnt # echo "root:${password}" | chpasswd --root /mnt # get ready to reboot. arch-chroot /mnt systemctl enable NetworkManager echo "#nomenu" > /mnt/home/$user/.zshrc echo "cd Arch-Setup; nmtui; ./install-packages" > /mnt/home/$user/.zlogin arch-chroot /mnt chown eric:eric /home/$user/.zshrc arch-chroot /mnt chown eric:eric /home/$user/.zlogin echo '=======================================================================' echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' echo " Set the Root password!" echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' arch-chroot /mnt passwd echo " " echo " " echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' echo " Set the password for $user!" echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' arch-chroot /mnt passwd $user echo " " echo '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' echo '=======================================================================' umount /mnt/boot umount /mnt echo " " echo '=======================================================================' echo Ready to reboot. _install-packages_ will run on login. (.zlogin). echo Look in '"Arch-Setup"' folder in /home/${user} for details. echo Croisez tes doigts. echo '=======================================================================' echo " "