Advertisement
Dan42

improved /usr/share/ubiquity/zsys-setup

Dec 12th, 2023 (edited)
1,083
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 19.97 KB | Source Code | 0 0
  1. #!/bin/sh
  2.  
  3. #
  4. # This script creates ZFS pools and dataset compatible with zsys
  5. # improved to avoid using all disk space
  6. # use extra disk space for dual boot, swap, extra vdev, etc.
  7. #
  8.  
  9. # Layout:
  10. # bpool/BOOT/ubuntu_${UUID}
  11. # rpool/ROOT/ubuntu_${UUID}
  12. # rpool/ROOT/ubuntu_${UUID}/var -o canmount=off
  13. # rpool/ROOT/ubuntu_${UUID}/var/games
  14. # rpool/ROOT/ubuntu_${UUID}/var/lib
  15. # rpool/ROOT/ubuntu_${UUID}/var/lib/AccountsService
  16. # rpool/ROOT/ubuntu_${UUID}/var/lib/apt
  17. # rpool/ROOT/ubuntu_${UUID}/var/lib/dpkg
  18. # rpool/ROOT/ubuntu_${UUID}/var/log
  19. # rpool/ROOT/ubuntu_${UUID}/var/mail
  20. # rpool/ROOT/ubuntu_${UUID}/var/snap
  21. # rpool/ROOT/ubuntu_${UUID}/var/spool
  22. # rpool/ROOT/ubuntu_${UUID}/var/www
  23. # rpool/ROOT/ubuntu_${UUID}/var/lib/NetworkManager
  24. # rpool/ROOT/ubuntu_${UUID}/srv
  25. # rpool/ROOT/ubuntu_${UUID}/usr -o canmount=off
  26. # rpool/ROOT/ubuntu_${UUID}/usr/local
  27. # rpool/USERDATA/$user_$UUID2
  28. # rpool/USERDATA/root_$UUID2
  29. # rpool/keystore
  30. #
  31. # Steps:
  32. # - Verify that /target is mounted
  33. # - Retrieve fstab
  34. # - unmount /target
  35. # - delete all the partitions but the ESP on p1
  36. # - Create p2 zfs bpool 2 GB
  37. # - Create p3 zfs rbool 500 GB
  38. # - Create datasets
  39. #
  40. # After setup is done leave it mounted to let Ubiquity proceed with installation
  41.  
  42. set -eu
  43.  
  44. REQUIREDPKGS="zfsutils-linux"
  45. TARGET="/target"
  46. ESP="${TARGET}/boot/efi"
  47. ZSYSTMP="/tmp/$(basename $0)"
  48. INIT_FLAG="${ZSYSTMP}/init.done"
  49. FSTAB_PARTMAN="${ZSYSTMP}/fstab.partman"
  50. PARTITION_LAYOUT="${ZSYSTMP}/layout"
  51. KEYSTORE_ROOT="/run/keystore/rpool"
  52. KEYSTORE_SIZE="500M"
  53.  
  54. mkdir -p "${ZSYSTMP}"
  55.  
  56. usage() {
  57.     # Display script usage
  58.     cat<<EOF
  59. Usage: $(basename "$0") [COMMAND] [OPTIONS...]
  60.     Prepares a zsys compatible ZFS system.
  61.  
  62. Commands:
  63.     layout      Get layout to display before formatting to ubiquity. Give the chosen disk as argument. Output to $PARTITION_LAYOUT
  64.     init        Initialize the pools and datasets
  65.     finalize    Finalize the installation after the system has been installed
  66. Options:
  67.     -h, --help      This help
  68.     -d, --debug     Enable debug mode
  69. EOF
  70.     exit
  71. }
  72.  
  73. SHORTOPTS="hd"
  74. LONGOPTS="help,debug"
  75.  
  76. TEMP=$(getopt -o $SHORTOPTS --long $LONGOPTS -- "$@")
  77. eval set -- "$TEMP"
  78.  
  79. while true ; do
  80.     case "$1" in
  81.         -h|--help)
  82.             usage;;
  83.         -d|--debug)
  84.             set -x
  85.             shift;;
  86.         --)
  87.             shift;
  88.             break;;
  89.         *)
  90.             usage;;
  91.     esac
  92. done
  93.  
  94. COMMAND=$( echo $1 | tr '[:upper:]' '[:lower:]' )
  95. EXTRAARG=""
  96. if [ $# -gt 1 ]; then
  97.     EXTRAARG="${2}"
  98. fi
  99.  
  100. ENCRYPTION=0
  101. ZFS_KS_KEY=${ZFS_KS_KEY:-}
  102. if [ -n "${ZFS_KS_KEY}" ]; then
  103.     ENCRYPTION=1
  104. fi
  105.  
  106. check_prerequisites() {
  107.     # Check and set requirements to run this script
  108.     #
  109.     # Check and set the requirements to run this test. If any of the
  110.     # requirement is missing the programs exit with error
  111.     #
  112.     # Args:
  113.     #   $@: List of required packages
  114.     #
  115.     # Returns
  116.     #   Exit program is a requirement is not met
  117.     echo "I: Checking system requirements"
  118.  
  119.     if [ $(id -u) -ne 0 ]; then
  120.         echo "E: Script must be executed as root. Exiting!"
  121.         exit 1
  122.     fi
  123.  
  124.     for pkg in $@; do
  125.         if ! dpkg-query -W -f'${Status}' "${pkg}"|grep -q "install ok installed" 2>/dev/null; then
  126.             echo "E: $pkg is required and not installed on this system. Exiting!"
  127.             exit 1
  128.         fi
  129.     done
  130.  
  131. }
  132.  
  133. prepare_target() {
  134.     target="$1"
  135.  
  136.     if ! grep -qE "\s${target}\s" /proc/mounts; then
  137.         echo "E: $target is not mounted. Exiting!"
  138.         exit 1
  139.     fi
  140.  
  141.     # Save fstab generated by partman
  142.     if [ -f "${target}/etc/fstab" ]; then
  143.         echo "I: Saving existing fstab"
  144.         cp "${target}/etc/fstab" "${FSTAB_PARTMAN}"
  145.     else
  146.         echo "W: ${target}/etc/fstab doesn't exist"
  147.     fi
  148.  
  149.     # umount /target
  150.     # It may fail to umount because the swap is being created by partman and not finished when we reach this point.
  151.     # Give it some time and retry with a sleep between tries.
  152.     iter=0
  153.     maxiter=10
  154.  
  155.     for mountpoint in "${ESP}" "${target}"; do
  156.         if [ ! -d "${mountpoint}" ]; then
  157.             continue
  158.         fi
  159.  
  160.         echo "I: umounting ${mountpoint}"
  161.         while :; do
  162.             # Do not make it quiet. We want to know why it failed.
  163.             if ! sudo umount "${mountpoint}"; then
  164.                 iter=$(( iter + 1 ))
  165.                 echo "W: Try ${iter}. Failed to umount ${mountpoint}."
  166.                 if [ ${iter} -eq ${maxiter} ]; then
  167.                     echo "E: Failed to umount ${mountpoint}. Exiting!"
  168.                     exit 1
  169.                 fi
  170.                 sleep 3
  171.             else
  172.                 break
  173.             fi
  174.         done
  175.     done
  176.    
  177.     # Destroy existing pools before removing partitions
  178.     if zpool list|grep -w bpool; then
  179.         zpool destroy bpool
  180.     fi
  181.     if zpool list|grep -w rpool; then
  182.         zpool destroy rpool
  183.     fi
  184. }
  185.  
  186. get_layout() {
  187.     # Returns disk, base name of the partition and partition numbers to create
  188.     target="$1"
  189.     disk="$2"
  190.  
  191.     if [ -z "${disk}" ]; then
  192.         # The entire disk has been formatted with use_device
  193.         # There is either one ext4 partition or one ext4 and one ESP
  194.         part="$(grep -E "\s${target}\s" /proc/mounts | awk '{print $1}')"
  195.         partbase=""
  196.  
  197.         if [ -n "${part}" ]; then
  198.             disk="$(lsblk -lns -o TYPE,PATH ${part}| grep disk| awk '{print $2}')"
  199.             if [ -z "${disk}" ]; then
  200.                 echo "E: Couldn't identify disk for partition ${part}. Exiting!"
  201.                 exit 1
  202.             fi
  203.             # Some disks have letters in the partition number like /dev/nvme0n1p1
  204.             # In this case we want to retrieve 'p' so we deal only with partition number
  205.             # in the rest of the script and prepend the base.
  206.             partbase="$(echo ${part} | sed -e 's/[0-9]*$//' | sed -e "s#${disk}##")"
  207.         fi
  208.     else
  209.         # The only purpose of this code is to display a friendly message in ubiquity to show the user
  210.         # what partitioning will be performed. However, on first call, the disk is not yet partitioned
  211.         # and collecting the information about disk partitioning would require to query partman. But we
  212.         # don't want to add this extra complexity just to display a message. Instead we hardcode the
  213.         # extension of the partition name depending on the type of disk, basically it's 'p' for anything
  214.         # else than standard drives (eg nvme01pX)
  215.         case "${disk}" in
  216.             /dev/sd*|/dev/hd*|/dev/vd*)
  217.                 partbase=""
  218.                 ;;
  219.             *)
  220.                 partbase="p"
  221.         esac
  222.     fi
  223.  
  224.     if [ -d /sys/firmware/efi/efivars ]; then
  225.         # No extended partition on EFI + GPT
  226.         # The layout is
  227.         # 1: ESP
  228.         # 2: swap
  229.         # 3: bpool
  230.         # 4: rpool
  231.         partesp=1
  232.         partswap=4
  233.         partbpool=2
  234.         partrpool=3
  235.  
  236.     # As partman forces now gpt for any installation, we consider that not having efivar equals gpt with BiosBoot (LP: #1796260)
  237.     else
  238.         # The layout is:
  239.         # 1: BiosBoot
  240.         # 2: ESP
  241.         # 3: swap
  242.         # 4: bpool
  243.         # 5: rpool
  244.         partesp=2
  245.         partswap=3
  246.         partbpool=4
  247.         partrpool=5
  248.     fi
  249.  
  250.     echo "OK|${disk}|${partbase}|${partesp}|${partswap}|${partbpool}|${partrpool}"
  251. }
  252.  
  253. format_disk() {
  254.     disk="$1"
  255.     partbase="$2"
  256.     partesp="$3"
  257.     partswap=$4
  258.     partbpool="$5"
  259.     partrpool="$6"
  260.     ss="$7"
  261.     partprefix="${disk}${partbase}"
  262.  
  263.     sfdisktmp="${ZSYSTMP}/sfdisk.cfg"
  264.     rm -f "${sfdisktmp}"
  265.  
  266.     echo "I: Formatting disk $disk with partitions swap:${partswap} bpool:${partbpool} rpool:${partrpool}"
  267.  
  268.     # bpool size: 500M < 5% of ZFS allocated space < 2G
  269.     # srcpath is the system partition on initial layout.
  270.     srcpath=$(lsblk -ln -o PATH ${disk}|tail -1)
  271.     partsrc=${srcpath##*${partprefix}}
  272.     size_percent=$(expr \( $(blockdev --getsize64 ${disk}) / 1024 / 1024 \) \* 5 / 100)
  273.     bpool_size=500
  274.     [ ${size_percent} -gt ${bpool_size} ] && bpool_size=${size_percent}
  275.     [ ${bpool_size} -gt 2048 ] && bpool_size=2048
  276.  
  277.     # Improvement: Delete all the partitions but the ESP
  278.     # There should be only 1 or 2 partitions but it can be made generic
  279.     if ! esp_exists "${disk}"; then
  280.         start=$(sfdisk -l "${disk}"|grep "^${partprefix}${partesp}"|awk '{print $2}')
  281.         cat > "${sfdisktmp}" <<EOF
  282. ${partprefix}${partesp}   : start= ${start}, size=    512M,        type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, bootable
  283. EOF
  284.     else
  285.         while [ $partsrc -gt 1 ]; do
  286.             zpool labelclear -f ${partprefix}${partsrc} || true
  287.             sfdisk --delete "${disk}" ${partsrc}
  288.             partsrc=$((partsrc-1))
  289.         done
  290.     fi
  291.  
  292.     cat >> "${sfdisktmp}" <<EOF
  293. ${partprefix}${partbpool} :   size= ${bpool_size}M, type=6A82CB45-1DD2-11B2-99A6-080020736631
  294. ${partprefix}${partrpool} :   size=512000M,         type=6A85CF4D-1DD2-11B2-99A6-080020736631
  295. ${partprefix}${partswap}  :   size= ${ss}M,         type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
  296. EOF
  297.  
  298.     cat "${sfdisktmp}" | sfdisk --append --wipe-partitions=always --no-reread "${disk}"
  299.  
  300.     # Force a re-read of the partition table
  301.     echo "I: Re-reading partition table"
  302.     partx --add "${disk}" 2>/dev/null || true
  303.     partx --show "${disk}"
  304. }
  305.  
  306. init_keystore() {
  307.     keystore_dev="$1"
  308.     echo "I: Initializing Key Store"
  309.  
  310.     if [ ${ENCRYPTION} -eq 1 ]; then
  311.         mkdir -p "${KEYSTORE_ROOT}"
  312.         printf "%s" "${ZFS_KS_KEY}" | cryptsetup luksFormat /dev/zvol/${keystore_dev} -
  313.         printf "%s" "${ZFS_KS_KEY}" | cryptsetup luksOpen /dev/zvol/${keystore_dev} keystore-rpool -
  314.         mke2fs -t ext4 /dev/mapper/keystore-rpool -L keystore-rpool
  315.         mount /dev/mapper/keystore-rpool "${KEYSTORE_ROOT}"
  316.     fi
  317. }
  318.  
  319. init_zfs() {
  320.     target="$1"
  321.     partbpool="$2"
  322.     partrpool="$3"
  323.  
  324.     echo "I: Initializing ZFS"
  325.     # Now we can create the pools and dataset
  326.     UUID_ORIG=$(head -100 /dev/urandom | tr -dc 'a-z0-9' |head -c6)
  327.  
  328.     # Use stable uuid for partition when available as device name can change
  329.     # Let udev finish its job before proceeding with zpool creation
  330.     udevadm settle
  331.     bpooluuid=$(blkid -s PARTUUID -o value $partbpool)
  332.     [ -n "$bpooluuid" -a -e "/dev/disk/by-partuuid/$bpooluuid" ] && partbpool=/dev/disk/by-partuuid/$bpooluuid
  333.     rpooluuid=$(blkid -s PARTUUID -o value  $partrpool)
  334.     [ -n "$rpooluuid" -a -e "/dev/disk/by-partuuid/$rpooluuid" ] && partrpool=/dev/disk/by-partuuid/$rpooluuid
  335.  
  336.     # Pools
  337.     encrypt_args=""
  338.     if [ ${ENCRYPTION} -eq 1 ]; then
  339.         # Creation of the encryption key
  340.         local ks_system_key="${KEYSTORE_ROOT}/system.key"
  341.         local ks_system_key_tmp="${ZSYSTMP}/$(basename "${ks_system_key}")"
  342.         head -c 32 /dev/urandom > "${ks_system_key_tmp}"
  343.         encrypt_args="-O encryption=on -O keylocation=file://${ks_system_key_tmp} -O keyformat=raw"
  344.     fi
  345.  
  346.     # rpool
  347.     zpool create -f \
  348.         -o ashift=12 \
  349.         -o autotrim=on \
  350.         -O compression=lz4 \
  351.         -O acltype=posixacl \
  352.         -O xattr=sa \
  353.         -O relatime=on \
  354.         -O normalization=formD \
  355.         -O mountpoint=/ \
  356.         -O canmount=off \
  357.         -O dnodesize=auto \
  358.         -O sync=disabled \
  359.         ${encrypt_args} \
  360.         -O mountpoint=/ -R "${target}" rpool "${partrpool}"
  361.  
  362.     # bpool
  363.     # The version of bpool is set to the default version to prevent users from upgrading
  364.     # Then only features supported by grub are enabled.
  365.     zpool create -f \
  366.         -o ashift=12 \
  367.         -o autotrim=on \
  368.         -d \
  369.         -o feature@async_destroy=enabled \
  370.         -o feature@bookmarks=enabled \
  371.         -o feature@embedded_data=enabled \
  372.         -o feature@empty_bpobj=enabled \
  373.         -o feature@enabled_txg=enabled \
  374.         -o feature@extensible_dataset=enabled \
  375.         -o feature@filesystem_limits=enabled \
  376.         -o feature@hole_birth=enabled \
  377.         -o feature@large_blocks=enabled \
  378.         -o feature@lz4_compress=enabled \
  379.         -o feature@spacemap_histogram=enabled \
  380.         -O compression=lz4 \
  381.         -O acltype=posixacl \
  382.         -O xattr=sa \
  383.         -O relatime=on \
  384.         -O normalization=formD \
  385.         -O canmount=off \
  386.         -O devices=off \
  387.         -O mountpoint=/boot -R "${target}" bpool "${partbpool}"
  388.  
  389.     if [ ${ENCRYPTION} -eq 1 ]; then
  390.         # Creation of the encryption keystore on the pool directly
  391.         # and point to the system ZFS decryption key path
  392.         local keystore_dev="rpool/keystore"
  393.         zfs create -o encryption=off -V ${KEYSTORE_SIZE} "${keystore_dev}"
  394.         init_keystore "${keystore_dev}"
  395.         mv "${ks_system_key_tmp}" "${ks_system_key}"
  396.         chmod 600 "${ks_system_key}"
  397.         zfs set keylocation=file://"${ks_system_key}" rpool
  398.     fi
  399.  
  400.     # Root and boot dataset
  401.     zfs create rpool/ROOT -o canmount=off -o mountpoint=none
  402.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}" -o mountpoint=/
  403.     zfs create bpool/BOOT -o canmount=off -o mountpoint=none
  404.     zfs create "bpool/BOOT/ubuntu_${UUID_ORIG}" -o mountpoint=/boot
  405.  
  406.     # System dataset
  407.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var" -o canmount=off
  408.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/lib"
  409.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/lib/AccountsService"
  410.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/lib/apt"
  411.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/lib/dpkg"
  412.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/lib/NetworkManager"
  413.  
  414.     # Desktop specific system dataset
  415.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/srv"
  416.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/usr" -o canmount=off
  417.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/usr/local"
  418.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/games"
  419.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/log"
  420.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/mail"
  421.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/snap"
  422.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/spool"
  423.     zfs create "rpool/ROOT/ubuntu_${UUID_ORIG}/var/www"
  424.  
  425.     # USERDATA datasets
  426.     # Dataset associated to the user are created by the installer.
  427.     zfs create rpool/USERDATA -o canmount=off -o mountpoint=/
  428.  
  429.     # Set zsys properties
  430.     zfs set com.ubuntu.zsys:bootfs='yes' "rpool/ROOT/ubuntu_${UUID_ORIG}"
  431.     zfs set com.ubuntu.zsys:last-used=$(date +%s) "rpool/ROOT/ubuntu_${UUID_ORIG}"
  432.     zfs set com.ubuntu.zsys:bootfs='no' "rpool/ROOT/ubuntu_${UUID_ORIG}/srv"
  433.     zfs set com.ubuntu.zsys:bootfs='no' "rpool/ROOT/ubuntu_${UUID_ORIG}/usr"
  434.     zfs set com.ubuntu.zsys:bootfs='no' "rpool/ROOT/ubuntu_${UUID_ORIG}/var"
  435. }
  436.  
  437. move_user () {
  438.     target="$1"
  439.     user="$2"
  440.     userhome="$3"
  441.     uuid="$4"
  442.  
  443.     echo "I: Creating user $user with home $userhome"
  444.     mv "${target}/${userhome}" "${target}/tmp/home/${user}"
  445.     zfs create "rpool/USERDATA/${user}_${uuid}" -o canmount=on -o mountpoint=${userhome}
  446.     chown $(chroot "${target}" id -u ${user}):$(chroot ${target} id -g ${user}) "${target}/${userhome}"
  447.     rsync -a "${target}/tmp/home/${user}/" "${target}/${userhome}"
  448.     bootfsdataset=$(grep "\s${target}\s" /proc/mounts | awk '{ print $1 }')
  449.     zfs set com.ubuntu.zsys:bootfs-datasets="${bootfsdataset}" rpool/USERDATA/${user}_${UUID_ORIG}
  450. }
  451.  
  452. init_system_partitions() {
  453.     target="$1"
  454.     partefi="$2"
  455.  
  456.     # ESP
  457.     mkdir -p "${target}/boot/efi"
  458.     mount -t vfat "${partefi}" "${target}/boot/efi"
  459.     mkdir -p "${target}/boot/efi/grub"
  460.  
  461.     echo "I: Mount grub directory"
  462.     # Finalize grub directory
  463.     mkdir -p "${target}/boot/grub"
  464.     mount -o bind "${target}/boot/efi/grub" "${target}/boot/grub"
  465. }
  466.  
  467. esp_exists() {
  468.     parttype="C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
  469.     sfdisk -d "${1}" | grep -q "type=${parttype}"
  470. }
  471.  
  472. check_prerequisites ${REQUIREDPKGS}
  473.  
  474. echo "I: Running $(basename "$0") ${COMMAND}"
  475.  
  476. if [ -z "${COMMAND}" ]; then
  477.     echo "E: ${COMMAND} is mandatory. Exiting!"
  478.     exit 1
  479. elif [ "${COMMAND}" = "layout" ]; then
  480.     # Just displays de layout that will be created without any change to the disk.
  481.     # At this stage we don't know yet the size of the partition that will be created.
  482.     IFS="|" read ERR DISK PARTBASE PARTESP PARTSWAP PARTBPOOL PARTRPOOL<<EOF
  483. $(get_layout ${TARGET} "${EXTRAARG}")
  484. EOF
  485.  
  486.     if [ "${ERR}" != "OK" ]; then
  487.         echo "${ERR}"
  488.         exit 1
  489.     fi
  490.  
  491.     cat > "${PARTITION_LAYOUT}" <<EOF
  492. disk:${DISK}
  493. EOF
  494.     if ! esp_exists "${DISK}"; then
  495.         cat >> "${PARTITION_LAYOUT}" <<EOF
  496. part:vfat:ESP:${DISK}${PARTBASE}${PARTESP}
  497. EOF
  498.     fi
  499.  
  500.     cat >> "${PARTITION_LAYOUT}" <<EOF
  501. part:swap:swap:${DISK}${PARTBASE}${PARTSWAP}
  502. part:zfs:bpool:${DISK}${PARTBASE}${PARTBPOOL}
  503. part:zfs:rpool:${DISK}${PARTBASE}${PARTRPOOL}
  504. EOF
  505.  
  506. elif [ "${COMMAND}" = "init" ]; then
  507.     rm -f "${INIT_FLAG}"
  508.  
  509.     IFS="|" read ERR DISK PARTBASE PARTESP PARTSWAP PARTBPOOL PARTRPOOL<<EOF
  510. $(get_layout ${TARGET} "")
  511. EOF
  512.  
  513.     if [ "${ERR}" != "OK" ]; then
  514.         echo "${ERR}"
  515.         exit 1
  516.     fi
  517.  
  518.     echo "I: Partition table before init of ZFS"
  519.     partx --show "${DISK}"
  520.  
  521.     # Swap files are not supported on ZFS, we use a swap partition instead:
  522.     SWAPFILE="$(grep "^${TARGET}" /proc/swaps | awk '{print $1}')"
  523.     # Give us a minimum swap partition size of 4MB in case we decide on
  524.     # no swap, just to keep the partition layout stable:
  525.     SWAPSIZE=4194304
  526.  
  527.     # Disable swap and get the swap volume size:
  528.     if [ -n "${SWAPFILE}" ]; then
  529.         SWAPSIZE=$(stat -c%s "${SWAPFILE}")
  530.         echo "I: Found swapfile with size ${SWAPSIZE}. Disabling"
  531.         swapoff "${SWAPFILE}"
  532.     fi
  533.     # Convert to MiB to align the size on the size of a block
  534.     SWAPVOLSIZE=$(( SWAPSIZE / 1024 / 1024 ))
  535.  
  536.     prepare_target "${TARGET}"
  537.     format_disk "${DISK}" "${PARTBASE}" "${PARTESP}" "${PARTSWAP}" "${PARTBPOOL}" "${PARTRPOOL}" "${SWAPVOLSIZE}"
  538.     init_zfs "${TARGET}" "${DISK}${PARTBASE}${PARTBPOOL}" "${DISK}${PARTBASE}${PARTRPOOL}"
  539.     init_system_partitions "${TARGET}" "${DISK}${PARTBASE}${PARTESP}"
  540.  
  541.     # Generate fstab
  542.     # $TARGET/etc has been destroyed by the creation of the zfs partitition
  543.     # Recreate it
  544.     mkdir -p "${TARGET}/etc"
  545.     if [ -f "${FSTAB_PARTMAN}" ]; then
  546.         echo "I: Creating fstab"
  547.         grep -Ev '\s/\s|/swapfile' "${FSTAB_PARTMAN}" > "${TARGET}/etc/fstab"
  548.     fi
  549.  
  550.     if ! grep -q "boot/efi" "${TARGET}/etc/fstab"; then
  551.         espuuid=$(blkid -s UUID -o value "${DISK}${PARTBASE}${PARTESP}")
  552.         echo "UUID=${espuuid}\t/boot/efi\tvfat\tumask=0022,fmask=0022,dmask=0022\t0\t1" >> "${TARGET}/etc/fstab"
  553.     fi
  554.  
  555.     # Bind mount grub from ESP to the expected location
  556.     echo "/boot/efi/grub\t/boot/grub\tnone\tdefaults,bind\t0\t0" >> "${TARGET}/etc/fstab"
  557.  
  558.     if [ -n "${SWAPFILE}" ]; then
  559.         swap_device="${DISK}${PARTBASE}${PARTSWAP}"
  560.         if [ ${ENCRYPTION} -eq 1 ]; then
  561.             # Format swap as Luks
  562.             swap_name="cryptoswap"
  563.             touch ${ZSYSTMP}/swap.keyfile
  564.             cryptsetup -q --key-file=${ZSYSTMP}/swap.keyfile luksFormat "${swap_device}"
  565.             cryptsetup -q --key-file=${ZSYSTMP}/swap.keyfile luksOpen "${swap_device}" "${swap_name}"
  566.             udevadm settle
  567.             orig_swap_device="${swap_device}"
  568.             swap_device="/dev/mapper/${swap_name}"
  569.  
  570.             # Update crypttab
  571.             printf "${swap_name}\t${orig_swap_device}\t/dev/urandom\tswap,initramfs" >> "${TARGET}/etc/crypttab"
  572.             swap_dev_fstab="${swap_device}"
  573.         fi
  574.         mkswap -f "${swap_device}"
  575.         if [ ${ENCRYPTION} -eq 0 ]; then
  576.             # for unencrypted swap, this has to be after mkswap to read the right device id
  577.             swap_dev_fstab="UUID=$(blkid -s UUID -o value "${swap_device}")"
  578.         fi
  579.         printf "${swap_dev_fstab}\tnone\tswap\tsw\t0\t0\n" >> "${TARGET}/etc/fstab"
  580.         swapon -v "${swap_device}"
  581.     fi
  582.     # Make /boot/{grub,efi} world readable
  583.     sed -i 's#\(.*boot/efi.*\)umask=0077\(.*\)#\1umask=0022,fmask=0022,dmask=0022\2#' "${TARGET}/etc/fstab"
  584.  
  585.     echo "I: Marking ZFS utilities to be kept in the target system"
  586.     apt-install zfsutils-linux 2>/dev/null
  587.     apt-install zfs-initramfs 2>/dev/null
  588.     # apt-install zsys 2>/dev/null
  589.     apt-install cryptsetup 2>/dev/null
  590.     apt-install cryptsetup-initramfs 2>/dev/null
  591.  
  592.     touch "$INIT_FLAG"
  593. elif [ "${COMMAND}" = "finalize" ]; then
  594.     if [ ! -f "$INIT_FLAG" ]; then
  595.         echo "W: zsys init didn't succeed. Not proceeding with command: ${COMMAND}. Aborting!"
  596.         exit 1
  597.     fi
  598.  
  599.     # Activate zfs generator.
  600.     # After enabling the generator we should run zfs set canmount=on DATASET
  601.     # in the chroot for one dataset of each pool to refresh the zfs cache.
  602.     echo "I: Activating zfs generator"
  603.  
  604.     # Create zpool cache
  605.     zpool set cachefile= bpool
  606.     zpool set cachefile= rpool
  607.     cp /etc/zfs/zpool.cache "${TARGET}/etc/zfs/"
  608.     mkdir -p "${TARGET}/etc/zfs/zfs-list.cache"
  609.     touch "${TARGET}/etc/zfs/zfs-list.cache/bpool" "${TARGET}/etc/zfs/zfs-list.cache/rpool"
  610.  
  611.     # Handle userdata
  612.     UUID_ORIG=$(head -100 /dev/urandom | tr -dc 'a-z0-9' |head -c6)
  613.     mkdir -p "${TARGET}/tmp/home"
  614.     for user in ${TARGET}/home/*; do
  615.         if [ -d "${user}" ]; then
  616.             user="$(basename $user)"
  617.             move_user "${TARGET}" "${user}" "/home/${user}" "${UUID_ORIG}"
  618.         fi
  619.     done
  620.  
  621.     move_user "${TARGET}" root /root "${UUID_ORIG}"
  622.  
  623.     echo "I: Changing sync mode of rpool to standard"
  624.     zfs set sync=standard rpool
  625.  
  626.     # Disable resumable device
  627.     if [ -b /dev/mapper/cryptoswap ]; then
  628.         mkdir -p "${TARGET}/etc/initramfs-tools/conf.d"
  629.         echo "RESUME=none" > "${TARGET}/etc/initramfs-tools/conf.d/resume"
  630.         chroot "${TARGET}" update-initramfs -u
  631.     fi
  632.  
  633.     echo "I: ZFS setup complete"
  634. else
  635.     echo "E: Unknown command: $COMMAND"
  636.     exit 1
  637. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement