#!/usr/bin/env zsh # shellcheck shell=bash # Copyright (c) 2016-2021 Ivan J. # This file is part of libdevuansdk # # This source code is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this source code. If not, see . build_metal_dist() { fn build_metal_dist req=(arch) req+=(workdir strapdir disk_name) ckreq || return 1 notice "installing complete dist" act "add release symlink to debootstrap scripts." if [[ ! -f /usr/share/debootstrap/scripts/${release} ]]; then ln -sf /usr/share/debootstrap/scripts/ceres \ /usr/share/debootstrap/scripts/${release} fi image_partition_disk_zfs || { zerr; wrapup } image_format_partitions_zfs || { zerr; wrapup } bootstrap_complete_base || { zerr; wrapup } blend_preinst || { zerr; wrapup } blend_postinst || { zerr; wrapup } } # Overide the post 'debootstrap stage 2' placeholder function of zlib/debootstrap bootstrap_complete_base. # The default is just to return 0 blend_bootstrap_setup() { fn blend_bootstrap_setup "noop" return 0 } ## Override the helper function: # takes the 'apt-get -f' out of the loop so that dependency provided by other debs can be resolved. # inside the loop it just uninstalls the deb because of unfullfilled deps. install-custdebs() { fn install-custdebs "(override)" req=(R strapdir custom_deb_packages) ckreq || return 1 sudo mkdir -p ${strapdir}/debs sudo cp $R/extra/custom-packages/*.deb ${strapdir}/debs/ cat <<-EOF | sudo tee ${strapdir}/install-debs >/dev/null #!/bin/sh cd /debs for deb in ${custom_deb_packages}; do dpkg -i \$deb done apt-get --yes --force-yes -f install cd / apt-get --yes --force-yes autoremove #rm -rf /debs EOF chroot-script -d install-debs } ## Added function: # In the style of install-custdebs above but for a collection of arbitrary scripts placed in a # directory alongside the blend custom debs called automate. # The scripts are copied from the blends scripts directory to extra/custom-scripts in blend_preinst() above. # Called after install-customdebs because some need checkinstall which disappears from archives. install-custscripts() { fn install-custscripts req=(R strapdir custom_scripts) ckreq || return 1 sudo mkdir -p ${strapdir}/var/tmp/automate sudo cp $R/extra/custom-scripts/*.sh ${strapdir}/var/tmp/automate/ cat <<-EOF | sudo tee ${strapdir}/install-scripts >/dev/null #!/bin/sh cd /var/tmp/automate for script in ${custom_scripts}; do touch \${script}.log bash \$script done apt-get --yes --force-yes -f install cd / apt-get --yes --force-yes autoremove #rm -rf /var/tmp/automate EOF chroot-script -d install-scripts } ## Override the helper function: # Allow an alternative skel directory add-user() { fn add-user $* local user="$1" local pass="$2" local skel="${3:-/etc/skel}" req=(strapdir user pass skel) ckreq || return 1 notice "adding user $user:$pass using $skel" cat <<-EOF | sudo tee ${strapdir}/adduser >/dev/null #!/bin/sh set -x if [ $(id -u ${user} 2>&1 >/dev/null) ]; then echo "user not present, creating account." useradd -m ${user} -k ${userskel:-/etc/skel} echo "${user}:${pass}" | chpasswd fi EOF chroot-script adduser || { zerr; return 0; } } ## apt related functions # point apt at a local apt-proxy like apt-cacher-ng enable_apt-proxy() { fn enable_apt-proxy req=(strapdir apt_proxy) ckreq || return 1 cat <<-EOF | sudo tee ${strapdir}/add_apt-proxy #!/bin/sh cat > '/etc/apt/apt.conf.d/02proxy' << 'FOE' Acquire::http { Proxy "${apt_proxy}"; }; FOE EOF chroot-script add_apt-proxy || zerr } disable_apt-proxy() { fn disable_apt-proxy req=(strapdir) ckreq || return 1 cat <<-EOF | sudo tee ${strapdir}/del_apt-proxy #!/bin/sh rm -f /etc/apt/apt.conf.d/02proxy EOF chroot-script del_apt-proxy || zerr } # When the release changes its suite (ie. from stable to oldstable) by default apt asks for explicite acceptance, which you might not want in your image, turn this on and off. enable_apt-allow-releaseinfo-change() { fn enable_apt-allow-releaseinfo-change req=(strapdir) ckreq || return 1 cat <<-EOF | sudo tee ${strapdir}/add_apt-releaseinfo-change #!/bin/sh cat > '/etc/apt/apt.conf.d/10no-check-valid-until' << 'FOE' Acquire::AllowReleaseInfoChange::Suite "true"; FOE EOF chroot-script add_apt-releaseinfo-change || zerr } disable_apt-allow-releaseinfo-change() { fn disable_apt-allow-releaseinfo-change req=(strapdir) ckreq || return 1 cat <<-EOF | sudo tee ${strapdir}/del_apt-allow-releaseinfo-change #!/bin/sh # rm -f /etc/apt/apt.conf.d/10no-check-valid-until EOF chroot-script del_apt-allow-releaseinfo-change || zerr } # apt checks the valid-util and refuses to install from repositories that are too old, which you might not want if building an old release, turn this on or off. disable_apt-valid-until() { fn disable_apt-valid-until req=(strapdir) ckreq || return 1 cat <<-EOF | sudo tee ${strapdir}/add_apt-check-valid #!/bin/sh cat > '/etc/apt/apt.conf.d/10no-check-valid-until' << 'FOE' Acquire::Check-Valid-Until "false"; FOE EOF chroot-script add_apt-check-valid || zerr } enable_apt-valid-until() { fn enable_apt-valid-until req=(strapdir) ckreq || return 1 cat <<-EOF | sudo tee ${strapdir}/del_apt-check-valid #!/bin/sh rm -f /etc/apt/apt.conf.d/10no-check-valid-until EOF chroot-script del_apt-check-valid || zerr } # Overide the sdk version of this function to prevent deletion # prior to unpacking the cpio as we have mountpoints in place # when installing to hardrive. bootstrap_cpio_unpack() { fn bootstrap_cpio_unpack "$*" req=(_bootstrap_cpio strapdir) local _bootstrap_cpio="$1" ckreq || return 1 notice "Unpacking bootstrap cpio archive: $_bootstrap_cpio" #sudo rm -rf "${strapdir}"/* pushd "$strapdir" || { zerr; return 1; } zcat "$_bootstrap_cpio" | sudo cpio -idmn --format=newc || { zerr; return 1; } popd sudo mkdir -p "$strapdir"/{boot,dev,proc,sys} } image_partition_disk_zfs() { fn image_partition_disk_zfs req=(strapdir disk_name efi_start efi_part_size swap_part_size boot_part_size available_disks) ckreq || return 1 notice "partitioning disks" # See: https://didrocks.fr/2020/06/11/zfs-focus-on-ubuntu-20.04-lts-zsys-partition-layout/ for disk in "${available_disks[@]}"; do TARGET="/dev/disk/by-id/${disk}" act "partitioning ${TARGET}" /sbin/sgdisk --zap-all ${TARGET} act "Partition 1 - Create partition using start and end values for partitioning the 'Bios boot' partition." FIRST_USABLE_SECTOR=34 ((ENDSECTOR = ${efi_start} - 1)) /sbin/sgdisk --print --set-alignment=1 --new=1:${FIRST_USABLE_SECTOR}:${ENDSECTOR} ${TARGET} /sbin/sgdisk --print --change-name=1:"BIOS_Boot_Partition" --typecode=1:EF02 ${TARGET} act "Partition 2 - Create partition using start and end values for partitioning the 'EFI' partition." STARTSECTOR=${efi_start} /sbin/sgdisk --print --set-alignment=${STARTSECTOR} --mbrtogpt --new=2:${STARTSECTOR}:+${efi_part_size} ${TARGET} /sbin/sgdisk --print --change-name=2:"EFI_System_Partition" --typecode=2:EF00 ${TARGET} act "Partition 3 - Create partition using start and end values for partitioning the 'swap' partition." STARTSECTOR=`/sbin/sgdisk --first-in-largest ${TARGET}|sed -sn 2p` /sbin/sgdisk --print --new=3:${STARTSECTOR}:+${swap_part_size} ${TARGET} /sbin/sgdisk --print --change-name=3:"Linux_swap" --typecode=3:8200 ${TARGET} act "Partition 4 - upto 2GB partition for boot." STARTSECTOR=`/sbin/sgdisk --first-in-largest ${TARGET}|sed -sn 2p` /sbin/sgdisk --print --new=4:${STARTSECTOR}:+${boot_part_size} ${TARGET} /sbin/sgdisk --print --change-name=4:boot --typecode=4:BE00 ${TARGET} act "Partition 5 - the main partition for root." /sbin/sgdisk --print --largest-new=5 ${TARGET} /sbin/sgdisk --print --change-name=5:root --typecode=5:BF00 ${TARGET} act "Reread the current partition tables with partprobe." # the second drive fails to update the kernel until reboot so added 2> #partprobe ${TARGET} 2>/dev/null || true hdparm -z ${TARGET} done } image_format_partitions_zfs() { fn image_format_partitions_zfs req=(disk_name available_disks efi_partitions swap_partitions root_part_number boot_part_number rpool_name bpool_name zpool_cache_dir strapdir) ckreq || return 1 act "format available efi partitions to vfat." for efi_partition in "${efi_partitions[@]}"; do act "format the efi partition to vfat." mkfs.fat -F32 ${efi_partition} done act "mkswap on available swap partitions." for swap_partition in "${swap_partitions[@]}"; do notice "making swap on ${swap_partition}" mkswap ${swap_partition} done notice "formatting zfs partitions..." for disk in "${available_disks[@]}"; do gdisk -l /dev/disk/by-id/${disk} done act "udev is slow recognize new partition so trigger sleep for 10 seconds" sleep 10 # create a separate boot pool for /boot with the features limited to only those that GRUB supports # allowing the root pool to use any/all features. if [[ ${raid} == "mirror" ]]; then mirror_disk=${available_disks[2]}; fi act "create the zfs boot pool" #zpool create -f -m none \ zpool create -f \ -o cachefile=${zpool_cache_dir}/zpool.cache \ -o ashift=${ashift} -d \ -o feature@async_destroy=enabled \ -o feature@bookmarks=enabled \ -o feature@embedded_data=enabled \ -o feature@empty_bpobj=enabled \ -o feature@enabled_txg=enabled \ -o feature@extensible_dataset=enabled \ -o feature@filesystem_limits=enabled \ -o feature@hole_birth=enabled \ -o feature@large_blocks=enabled \ -o feature@lz4_compress=enabled \ -o feature@spacemap_histogram=enabled \ -o feature@zpool_checkpoint=enabled \ -O acltype=posixacl \ -O canmount=off \ -O compression=lz4 \ -O devices=off \ -O normalization=formD \ -O relatime=on \ -O xattr=sa \ -O mountpoint=/boot -o altroot=${strapdir} \ ${bpool_name} ${raid} /dev/disk/by-id/${disk_name}-part${boot_part_number} ${mirror_disk} act "create the zfs root pool" zpool create -f \ -o cachefile=${zpool_cache_dir}/zpool.cache \ -o ashift=${ashift} \ -O acltype=posixacl \ -O canmount=off \ -O compression=lz4 \ -O dnodesize=auto \ -O normalization=formD \ -O relatime=on \ -O xattr=sa \ -O mountpoint=/ -o altroot=${strapdir} \ ${rpool_name} ${raid} /dev/disk/by-id/${disk_name}-part${root_part_number} ${mirror_disk} ## Physical swap used instead. #act "create the zfs zvol for swap" #zfs create -V ${swap_part_size} -b $(getconf PAGESIZE) \ # -o compression=zle \ # -o logbias=throughput \ # -o sync=always \ # -o primarycache=metadata \ # -o secondarycache=none \ # -o com.sun:auto-snapshot=false \ # ${rpool_name}/swap #mkswap -f -L "Linux swap" /dev/zvol/${rpool_name}/swap notice "zfs system installation" act "create filesystem datasets to act as containers" zfs create -o canmount=off -o mountpoint=none ${rpool_name}/ROOT zfs create -o canmount=off -o mountpoint=none ${bpool_name}/BOOT act "create filesystem datasets for the root and boot filesystems" # Create the initial boot environment and mount ${rpool_name} at /${rpool_name} zfs create -o canmount=noauto -o mountpoint=/ ${rpool_name}/ROOT/${root_name} zfs mount ${rpool_name}/ROOT/${root_name} #zfs create -o canmount=noauto -o mountpoint=/boot ${bpool_name}/BOOT/${root_name} zfs create -o mountpoint=/boot ${bpool_name}/BOOT/${root_name} # At this point rpool directory is created in the workdir #zfs set mountpoint=/${rpool_name} ${rpool_name} TMP_EXEC_STATE=on VAR_TMP_EXEC_STATE=on notice "create datasets" act "create zfs datasets for $rpool_name" zfs create -o mountpoint=/home ${rpool_name}/home zfs create -o mountpoint=/root ${rpool_name}/home/root zfs create -o mountpoint=/space ${rpool_name}/space zfs create -o mountpoint=/opt ${rpool_name}/opt zfs create -o mountpoint=/srv ${rpool_name}/srv zfs create -o mountpoint=/usr \ -o canmount=off \ ${rpool_name}/usr zfs create -o mountpoint=/usr/share ${rpool_name}/usr/share zfs create -o mountpoint=/usr/local ${rpool_name}/usr/local zfs create -o mountpoint=/tmp \ -o setuid=off \ -o exec=${TMP_EXEC_STATE} \ -o com.sun:autosnapshot=false \ ${rpool_name}/tmp zfs create -o mountpoint=/var \ -o canmount=off \ ${rpool_name}/var zfs create -o mountpoint=/var/lib ${rpool_name}/var/lib zfs create -o mountpoint=/var/lib/virt ${rpool_name}/var/lib/virt zfs create -o mountpoint=/var/tmp \ -o setuid=off \ -o com.sun:auto-snapshot=false \ -o exec=${VAR_TMP_EXEC_STATE} \ ${rpool_name}/var/tmp zfs create -o mountpoint=/var/cache \ -o com.sun:auto-snapshot=false \ ${rpool_name}/var/cache zfs create \ -o mountpoint=/var/lib/docker \ -o com.sun:autosnapshot=false \ ${rpool_name}/docker zfs create -o mountpoint=/var/log ${rpool_name}/var/log zfs create -o mountpoint=/var/snap ${rpool_name}/var/snap zfs create -o mountpoint=/var/spool ${rpool_name}/var/spool zfs create -o mountpoint=/var/www ${rpool_name}/var/www zfs list -t all -o name,type,mountpoint,compress,exec,setuid,atime,relatime chmod 700 ${strapdir}/root chmod 1777 ${strapdir}/tmp #chmod 1777 ${strapdir}/var/tmp act "mount the efi partition on ${grub_mount} before debootstrap." mount /dev/disk/by-id/${disk_name}-part${efi_part_number} -t vfat ${strapdir}${grub_mount} act "create zpool cache file" mkdir -p ${strapdir}/etc/zfs cp ${zpool_cache_dir}/zpool.cache ${strapdir}/etc/zfs/ } use_swap_partition() { fn use_swap_partition req=(swap_partitions) ckreq || return 1 for swap_partition in "${swap_partitions[@]}"; do act "Using swapon on ${swap_partition}" swapon ${swap_partition} done } image_zfs_mount() { fn image_zfs_mount req=(strapdir disk_name rpool_name bpool_name grub_mount) ckreq || return 1 notice "image_zfs_mount" act "importing zfs pools without mounting the filesystem" zpool import -N -R ${strapdir} ${rpool_name} zpool import -N -R ${strapdir} ${bpool_name} if [[ -n $encrypt ]]; then act "loading encryption keys of ZFS datasets from imported pools" zfs load-key -a fi act "mounting zfs datasets" zfs mount -v ${rpool_name}/ROOT/${root_name} zfs mount -v ${bpool_name}/BOOT/${root_name} zfs mount -v -a act "mount efi partition to /boot/grub" mkdir -p ${strapdir}${grub_mount} mount /dev/disk/by-id/${disk_name}-part${efi_part_number} -t vfat ${strapdir}${grub_mount} act "mount system directories" devprocsys mount ${strapdir} } image_zfs_umount() { fn image_zfs_umount req=(workdir strapdir rpool_name bpool_name) ckreq || return 1 notice "umount system directories" devprocsys umount ${strapdir} act "reaping chroot processes" PREFIX=${strapdir} FOUND=0 reap() { for ROOT in /proc/*/root; do LINK=$(readlink $ROOT) if [[ "x${LINK}" != "x" ]]; then if [[ "x${LINK:0:${#PREFIX}}" = "x${PREFIX}" ]]; then PID=$(basename $(dirname "$ROOT")) act "this process is in the chroot... $PID" kill -9 "$PID" FOUND=1 fi fi done } reap if [[ "x$FOUND" = "x1" ]]; then reap fi act "umount efi partition" efi_path=/dev/disk/by-id/${disk_name}-part${efi_part_number} if [[ $(/bin/mountpoint -q -- ${efi_path}) ]]; then umount --lazy ${efi_path} fi act "umount zfs partitions" COUNT=0 while grep -q "$PREFIX" /proc/mounts; do COUNT=$(($COUNT+1)) if [ $COUNT -ge 20 ]; then echo "failed to umount $PREFIX" if [ -x /usr/bin/lsof ]; then /usr/bin/lsof "$PREFIX" fi exit 1 fi grep "$PREFIX" /proc/mounts | \ cut -d\ -f2 | LANG=C sort -r | xargs -r -n 1 umount || sleep 1 done act "export zfs pools." zpool export ${bpool_name} zpool export ${rpool_name} } get_selections() { fn get_selections req=(strapdir blend_release_path) ckreq || return 1 notice "generating package list files to ${blend_release_path}" pushd "${blend_release_path}" dpkg --get-selections > packages.list debconf-get-selections > debconf-settings.list update-alternatives --get-selections > /var/tmp/alternatives-settings.list /usr/bin/apt-mark showauto > pkgs_auto.lst /usr/bin/apt-mark showmanual > pkgs_manual.lst popd } set_selections() { fn set_selections req=(strapdir blend_release_path) ckreq || return 1 pushd "${blend_release_path}" notice "copying set selections related files to ${strapdir}/var/tmp" if [[ -f ./packages.list ]]; then cp ./packages.list ${strapdir}/var/tmp else act "no package.list found in ${blend_release_path} " exit 0 fi if [[ -f ./debconf-settings.list ]]; then cp ./debconf-settings.list ${strapdir}/var/tmp else act "no debconf-settings.list found in ${blend_release_path} " exit 0 fi if [[ -f ./alternatives-settings.list ]]; then cp ./alternatives-settings.list ${strapdir}/var/tmp else act "no alternatives-settings.list found in ${blend_release_path} " exit 0 fi if [[ -f ./pkgs_auto.lst ]]; then cp ./pkgs_auto.lst ${strapdir}/var/tmp else act "no pkgs_auto.lst found in ${blend_release_path}" fi if [[ -f ./pkgs_auto.lst ]]; then cp ./pkgs_manual.lst ${strapdir}/var/tmp else act "no pkgs_manual.lst found in ${blend_release_path}" fi popd notice "upgrading using dselect" cat <<-EOF | sudo tee "$strapdir/install-set-selections" >/dev/null #!/bin/sh dpkg --set-selections 2>&1 < /var/tmp/packages.list debconfig-set-selections 2>&1 < /var/tmp/debconf-settings.list update-alternatives --set-selections 2>&1 < /var/tmp/alternatives-settings.list apt-get -y -u dselect-upgrade if [[ -f /var/tmp/pkgs_auto.lst ]]; then apt-mark auto $(cat /var/tmp/pkgs_auto.lst) fi if [[ -f /var/tmp/pkgs_manual.lst ]]; then apt-mark manual $(cat /var/tmp/pkgs_manual.lst) fi EOF chroot-script -d install-set-selections || { zerr; return 1; } } enablessh() { fn enablessh req=(strapdir) ckreq || return 1 notice "enabling ssh access without password." act "Use ssh-copy-id default@192.168.1.x to login on reboot." act "adding or creating keys (place keys in /etc/ssh/ssh_host_rsa_key.pub)" cat <<-EOF | sudo tee "$strapdir/etc/rc.local" >/dev/null #!/bin/sh # rc.local for base images [ -f /etc/ssh/ssh_host_rsa_key.pub ] || ssh-keygen -A exit 0 EOF sudo chmod +x "$strapdir/etc/rc.local" cat <<-EOF | sudo tee "$strapdir/enablessh" >/dev/null #!/usr/bin/env zsh set -x ; exec 2>${PWD}/enablessh.log config_file="/tmp/sshd_config" typeset -A rules rules=( "LoginGraceTime" "1m" "PermitRootLogin" "yes" "PasswordAuthentication" "no" "AllowUsers" "${username}" ) EOF cat <<-'EOF' | sudo tee -a "$strapdir/enablessh" >/dev/null for rule in "${(@k)rules}"; do regex="s/^#\?\(${rule}\s*\).*$/\1 ${rules[${rule}]}/" sed -i "${regex}" ${config_file}; done EOF chroot-script -d enablessh || { zerr; return 1; } } install_kernel_headers() { fn install_kernel_headers req=(strapdir kernel_version arch) ckreq || return 1 # could go in blends/devuan-desktop-live/config $extra_packages and # remove headers in blends/devuan-desktop-live/chimaera/config $purge_packages notice "install kernel headers" cat <<-EOF | sudo tee "$strapdir/install-kernel-headers" >/dev/null #!/bin/sh apt-get install -y linux-image-${kernel_version}-${arch} apt-get install -y linux-headers-${kernel_version}-${arch} apt-get -y -f install EOF chroot-script -d install-kernel-headers || { zerr; return 1; } } install_zfs() { fn install_zfs req=(strapdir rpool_name bpool_name root_name grubversion) ckreq || return 1 act "install zfs to the $strapdir" act "install the zfs packages in the correct order before dselect upgrade" cat <<-EOF | sudo tee "$strapdir/install-zfs" >/dev/null #!/bin/sh apt-get remove -y live-config && apt-get -y autoremove apt-get install -y spl-dkms dh-autoreconf apt-get install -y zfs-dkms zfs-initramfs zfsnap zfsutils-linux ${grubversion} busybox console-setup apt-get -y -f install # add nouveau graphics setting before updating initramfs: add to the grub commandline with update-initramfs -u # zfs_autoimport_disable is now compiled as set to 1/true by default # At module load 0=read zpool.cache 1=do not read zpool.cache #echo '# https://openzfs.github.io/openzfs-docs/Performance and Tuning/Module Parameters.html' > /etc/modprobe.d/zfs.conf #echo 'options zfs zfs_autoimport_disable=0' >> /etc/modprobe.d/zfs.conf echo 'options zfs l2arc_write_max=50331648' >> /etc/modprobe.d/zfs.conf echo 'options zfs l2arc_write_boost=100663296' >> /etc/modprobe.d/zfs.conf # Additional datasets to /etc/default/zfs not created under ROOT sed -i "s/#ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\"/" /etc/default/zfs # sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/home\"/" /etc/default/zfs sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/space\"/" /etc/default/zfs sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/tmp\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/opt\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/usr_share\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/usr_local\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_lib\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_lib_docker\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_lib_virt\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_tmp\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/usr\"/" /etc/default/zfs #sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var\"/" /etc/default/zfs EOF chroot-script -d install-zfs || { zerr; return 1; } } install_grub(){ fn install_grub req=(strapdir disk_name efi_partitions swap_part_number rpool_name bpool_name root_name grub_mount grub_theme grub_gfxmode) ckreq || return 1 notice "installing grub." act "move the grub theme to the grub partition, stops 'update-alternatives desktop-grub-theme' from working." mkdir -p /boot/grub/grub-themes cp -a /usr/share/desktop-base/grub-themes/${grub_theme} /boot/grub/grub-themes/ act "replace the pool name detection with zdb command in /etc/grub.d/10_linux." sed -i "s|rpool=.*|rpool=\`zdb -l \${GRUB_DEVICE} \| grep -E '[[:blank:]]name' \| cut -d\\\' -f 2\`|" $strapdir/etc/grub.d/10_linux act "change the grub kernel commandline" cat <<-EOF | sudo tee "$strapdir/write-default-grub" >/dev/null #!/bin/sh set -x # GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/zvol/rpool/swap radeon:modeset=1 i915:modeset=1 cgroup_enable=memory swapaccount=1 net.ifnames=0 # set boot filesystem - duplicated by grub but misses rpool_name when grub-probe fails to read filesystem type. sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 zfs=${rpool_name}\"|" /etc/default/grub # set swap as the resume partition. sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 resume=/dev/disk/by-id/${disk_name}-part${swap_part_number}\"|" /etc/default/grub # set root - Not needed as the kernel and root are set before /etc/default/grub is added #sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 root=ZFS=${rpool_name}\/ROOT\/${root_name}\"|" /etc/default/grub # init_on_alloc=1 is a security hardening mechanism preventing a class of security issues from being exploitable. # init_on_alloc=1 causes big performance regression for zfs: ubuntu +bug/1862822 sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 init_on_alloc=0\"|" /etc/default/grub # enable udev "info" logging for block devices sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 rd.log.block=info\"|" /etc/default/grub sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 cgroup_enable=memory\"|" /etc/default/grub sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 swapaccount=1\"|" /etc/default/grub sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 net.ifnames=0\"|" /etc/default/grub sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 nouveau.modeset=1\"|" /etc/default/grub #sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 i915.modeset=1\"|" /etc/default/grub #sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 radeon.modeset=1\"|" /etc/default/grub sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 noplymouth nosplash\"|" /etc/default/grub sed -i '/^#GRUB_DISABLE_LINUX_UUID=.*/ s/.*/&\nGRUB_DISABLE_LINUX_UUID=true/' /etc/default/grub sed -i '/^#GRUB_TIMEOUT=.*/ s/.*/&\nGRUB_RECORDFAIL_TIMEOUT=5/' /etc/default/grub #sed -i "s|^#GRUB_DISABLE_LINUX_UUID=\"\(.*\)\"|GRUB_DISABLE_LINUX_UUID=\"\1 true\"|" /etc/default/grub echo "" >> /etc/default/grub echo "# Preload modules so that they are not missed." >> /etc/default/grub echo "GRUB_PRELOAD_MODULES=part_gpt" >> /etc/default/grub sed -i "s|^\(GRUB_GFXMODE=\).*|\1\"$grub_gfxmode\"|" /etc/default/grub sed -i '/^GRUB_GFXMODE=.*/ s/.*/&\nGRUB_GFXPAYLOAD_LINUX=\"keep\"/' /etc/default/grub sed -i "s|^\(GRUB_THEME=\).&|\1\"/boot/grub/grub-themes/${grub_theme}/theme.txt\"|" /etc/default/grub # debug grub sed -i "s/quiet//" /etc/default/grub #sed -i "s/#GRUB_TERMINAL/GRUB_TERMINAL/" /etc/default/grub EOF chroot-script -d write-default-grub || { zerr; return 1; } #umount -q ${strapdir}${grub_mount} if [[ -v $efi ]]; then mkdir -p ${grub_mount} act "write grub-efi to available efi partitions." for efi_partition in "${efi_partitions[@]}"; do notice "writing to efi partitions: ${efi_partitions}" act "mount the primary disks efi partition under ${grub_mount}" mount ${disk_path}/${disk_name}-part${efi_part_number} ${strapdir}${grub_mount} cat <<-EOF | sudo tee ${strapdir}/update-grub_${disk_name} > /dev/null #!/bin/sh echo "populate the ${grub_mount} with update-grub." grub-mkconfig -o ${grub_mount}/grub.cfg echo "install grub to disk name ${disk_name}, efi partition ${efi_partition}" grub-install --target=${grub_efi_target} \ --no-uefi-secure-boot \ --efi-directory=${grub_mount} \ --bootloader-id="Devuan ${release} (RAID disk ${disk_name})" --recheck \ --no-floppy EOF chroot-script -d update-grub_${disk_name} || { zerr; return 1; } umount ${strapdir}${grub_mount} done else mkdir -p ${grub_mount} for disk_name in "${available_disks[@]}"; do notice "writing grub to available disks:" act "mount the primary disks efi partition under ${grub_mount}" mount ${disk_path}/${disk_name}-part${efi_part_number} ${strapdir}${grub_mount} cat <<-EOF | sudo tee ${strapdir}/update-grub_${disk_name} > /dev/null #!/bin/sh echo "populate the ${grub_mount} with update-grub." grub-mkconfig -o ${grub_mount}/grub.cfg echo "install grub-pc to ${disk_name}" grub-install --target=i386-pc /dev/disk/by-id/${disk_name} EOF chroot-script -d update-grub_${disk_name} || { zerr; return 1; } umount ${strapdir}${grub_mount} done fi }