Advertisement
Nukien

Ubuntu/Elementary/Mint 16.04 root-on-zfs optionally on luks

Feb 22nd, 2016
1,181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 111.23 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. # ZFS-setup.sh      2019-01-27 17:50        http://pastebin.com/fa83QrBk
  4.  
  5. # Any parameter passed in is set to the DISTRO variable - see below
  6.  
  7. # Auto-installer for clean new system using root on zfs, and optionally on
  8. # luks encrypted disks.  It installs Ubuntu 14.04.04 or 16.04 or Elementary OS
  9. # (based on 16.04) or Linux Mint 18.1 Serena (also based on 16.04) with everything
  10. # needed to support ZFS and potentially LUKS.  Without LUKS everything lives
  11. # in the main ${POOLNAME} pool.  With LUKS then /boot lives in its own boot pool.
  12. # Grub2 is installed to all disks, so the system can boot cleanly from *any*
  13. # disk, even with a failed disk.  User home dirs are in isolated datasets sitting
  14. # in a dedicated HOME dataset.  This means that new user creation is a little more
  15. # than just a "useradd ..." command
  16. #
  17. #   zfs create -o mountpoint=/home/NewUser tank/HOME/NewUser
  18. #   useradd -c "User name" --create-home --home-dir /home/NewUser --user-group NewUser
  19. #   rsync -av /etc/skel/ /home/NewUser
  20. #   chown -R NewUser.NewUser /home/NewUser
  21.  
  22. # This script is meant to be run from an Ubuntu live-CD or a minimal
  23. # install (from a usb key for example).  It will create a list of all disks it
  24. # can see then ask the user to edit that list if required.  All disks listed
  25. # in the created ZFS-setup.disks.txt file will be wiped CLEAN for the install.
  26.  
  27. #############################################################################
  28. # Be aware that plymouth has a weirdness about it.  After booting and seeing
  29. # the cool solar graphical boot splash, you may appear to be left with a
  30. # stuck system.  It's not stuck - just use alt-F2 to switch to tty2 and
  31. # alt-F1 to switch back to tty1.  For some reason it doesn't clear
  32. # the screen properly after boot.
  33. #############################################################################
  34.  
  35. # This script can copy the /etc/ssh directory from the build-host into the newly
  36. # created system.  Makes for *much* easier testing when running multiple times,
  37. # since you have the same host key.  It gets old editing your known_hosts file ...
  38.  
  39. # Basic use from ubuntu-16.04-desktop-amd64.iso Live-CD
  40. #
  41. # Boot ISO, select "Try Ubuntu"
  42. # Open terminal
  43. # sudo -i
  44. # (create a ZFS-Custom.sh file containing any custom stuff you want installed/configured)
  45. # wget http://pastebin.com/raw/fa83QrBk -O ZFS-setup.sh
  46. # chmod +x ZFS-setup.sh ZFS-Custom.sh
  47. # nano ZFS-setup.sh
  48. # (if you use vi or vim you *may* have to do :1,$s/^M// to remove ctrl-M at end of each line)
  49. # (where ^M means ctrl-V followed by <return/enter>)
  50. #    set variables in ZFS-setup.sh - see below for the full list with explanations
  51. # ./ZFS-setup.sh
  52. #    ctrl-C to exit at list of disks
  53. # nano ZFS-setup.disks.txt
  54. #    Ensure list of disks is correct
  55. # ./ZFS-setup.sh
  56. #    press <enter> to accept list of disks and swap size
  57. #    enter password for main userid
  58. #    enter password again
  59. #    press <enter> to accept final disk layout
  60.  
  61. # It will create a few scripts - seen as the "cat > /path/script.sh << EOF" below.
  62.  
  63. # Setup.sh                 : Goes in /root of the new system, and is used to build/install
  64. #                          : the rest of the system after debootstrap.
  65. # Reboot-testing.sh        : Goes in the local build-host /root, and is used for
  66. #                          : entering/exiting the new system via chroot for debugging.
  67. # Replace-failed-drive.sh  : Goes in /root of new system, used to replace a failed drive.
  68. #                          : NOTE - this is incomplete
  69.  
  70. # The following stock files are modified
  71. #
  72. # /usr/share/initramfs-tools/scripts/local-top/cryptroot            (if using LUKS)
  73. # /etc/default/grub
  74. # /etc/default/locale
  75. # /etc/crypttab                                                     (if using LUKS)
  76. # /etc/modules
  77. # /etc/timezone
  78. # /etc/localtime
  79. # /etc/hostname
  80. # /etc/hosts
  81. # /etc/fstab
  82. # /etc/bash.bashrc
  83. # /etc/skel/.bashrc
  84. # /etc/network/interfaces
  85. # /etc/apt/sources.list
  86. # /etc/mdadm/mdadm.conf                                             (if using LUKS)
  87. # /etc/initramfs-tools/initramfs.conf                               (if using LUKS)
  88. # /etc/initramfs-tools/conf.d/resume
  89.  
  90. # The following new files are created
  91. #
  92. # /root/.ssh/authorized_keys
  93. # /etc/udev/rules.d/99-local-crypt.rules                            (if using LUKS)
  94. # /etc/udev/rules.d/61-zfs-vdev.rules
  95. # /etc/apt/apt.conf.d/03proxy                                       (if proxy is defined)
  96. # /etc/apt/apt.conf.d/02periodic
  97. # /etc/sudoers.d/zfsALLOW
  98. # /etc/initramfs-tools/modules
  99. # /etc/initramfs-tools/scripts/luks/get.root_crypt.decrypt_derived  (if using LUKS)
  100. # /etc/initramfs-tools/conf.d/dropbear_network                      (if using LUKS)
  101. # /etc/initramfs-tools/hooks/clean_cryptroot                        (if using LUKS)
  102. # /etc/initramfs-tools/hooks/copy_cryptheaders                      (if using LUKS)
  103. # /etc/initramfs-tools/hooks/mount_cryptroot                        (if using LUKS)
  104. # /etc/initramfs-tools/hooks/busybox2                               (if using LUKS)
  105. # /etc/initramfs-tools/hooks/dropbear.fixup2                        (if using LUKS)
  106. # /etc/initramfs-tools/root/.ssh/authorized_keys                    (if using LUKS)
  107. # /usr/share/initramfs-tools/conf-hooks.d/forcecryptsetup           (if using LUKS)
  108. # /etc/initramfs-tools/scripts/init-premount/zzmdraidforce          (if using LUKS)
  109. # /etc/initramfs-tools/scripts/init-premount/network-down
  110.  
  111. # FIXMEs
  112. #
  113. # - 16.04/xenial now uses new systemd device naming, so eth0 becomes enp0s3 or similar.
  114. #   So /etc/initramfs-tools/scripts/init-premount/network-down must be customized, or we
  115. #   must put "net.ifnames=0 biosdevname=0" on the grub cmdline to use old eth0 style network
  116. #   names rather than the newer enp3s0 type.  Search below for GRUB_CMDLINE_LINUX_DEFAULT
  117. # or
  118. #   https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
  119. #   https://askubuntu.com/questions/628217/use-of-predictable-network-interface-names-with-alternate-kernels
  120. #   ln -s /dev/null /mnt/etc/udev/rules.d/80-net-setup-link.rules
  121. #   ln -s /dev/null /mnt/etc/udev/rules.d/75-persistent-net-generator.rules
  122.  
  123. # General Notes
  124. #
  125. # If you're backing this system up to a remote backup server (called backup.local) you can set up
  126. # a nice systemd env to handle using mbuffer and zfs to receive the backup streams on the backup box.
  127. #
  128. # Choose a port (13371) to have it listen on and a pool to receive to (backup1)
  129. # Send stream with : zfs send -Rv pool/dataset@snapshot | mbuffer -s 256k -m 500m -O backup.local:13371
  130. # Start/stop and final size/speed msgs go into syslog
  131. #
  132. # /etc/systemd/system/zfs.backup1.service
  133. #
  134. # [Unit]
  135. # Description=Start mbuffer to zfs recv for backup1 pool
  136. # Requires=zfs-mount.service
  137. #
  138. # [Service]
  139. # Type=simple
  140. # ExecStart=/bin/sh -c "/usr/bin/mbuffer -v 2 -q -s 256k -m 500m -I 13371 | /sbin/zfs recv -Fdvu backup1"
  141. # Restart=always
  142. #
  143. # [Install]
  144. # WantedBy=multi-user.target
  145.  
  146.  
  147. # -------Set the following variables -----------------------------------------------------------
  148.  
  149. # Which version of Ubuntu to install trusty=14.04 xenial=16.04
  150. SUITE=xenial
  151.  
  152. # If a parameter is passed in, use that for the DISTRO variable
  153. # NOTE: Setting a value to DISTRO means you intend to install the full
  154. #       desktop environment for that particular distribution ...
  155. #       It chooses the repos accordingly.
  156. #       The desktop install doesn't happen in this script - here we just look
  157. #       for an Ansible playbook to install the rest of the stuff.  If it's there,
  158. #       good, it will run the playbook with DISTRO as an extra-var.
  159. #       Otherwise, no harm no foul.
  160. ### Ubuntu 16.04 Gnome
  161. ### DISTRO=xenial
  162. ### ElementaryOS Loki
  163. ### DISTRO=loki
  164. ### Mint Cinnamon serena
  165. ### DISTRO=serena
  166. if [ ! -z ${1+x} ] ; then
  167.     if [ $1 == "xenial" ] || [ $1 == "loki" ] || [ $1 == "serena" ] ; then
  168.         DISTRO=$1
  169.         echo "-----------------------------------------------------------------------------"
  170.         echo ">>>>  Setting desktop distro to ${DISTRO}  <<<<"
  171.         echo "-----------------------------------------------------------------------------"
  172.         sleep 4
  173.     fi
  174. fi
  175.  
  176. # Base set of packages to install after debootstrap
  177. # Very annoying - can't use { } as in linux-{image,headers}-generic - expansion of variable fails in apt-get in Setup.sh,
  178. # around line 1203 in this script.  So have to use individual packages names, linux-header-generic linux-image-generic and so on
  179. # whois needed for mkpasswd
  180. # ansible is installed, and the PPA for it is added down in the Setup.sh bootstrap script
  181. BASE_PACKAGES="most openssh-server openssh-blacklist openssh-blacklist-extra whois rsync gdisk parted linux-headers-generic-hwe-16.04 linux-image-generic-hwe-16.04 debian-keyring ntp vim-nox openssl openssl-blacklist htop mlocate bootlogd apt-transport-https friendly-recovery irqbalance manpages uuid-runtime apparmor grub-pc-bin acpi-support acpi grub-efi-amd64 efibootmgr xauth memtest86+ avahi-daemon intel-microcode amd64-microcode ansible python-apt"
  182.  
  183. # Userid, full name and password to create in new system. If UPASSWORD is blank, will prompt for password
  184. USERNAME=zuser
  185. UCOMMENT='Main User'
  186. UPASSWORD=
  187.  
  188. # SSH pubkey to add to new system
  189. SSHPUBKEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3uB7roSJ3EYs9hBAQiUZ9Of53Lm3+JZ6ZVokZnp3CRoRfuVT3zND7DAQYSCo+0MZaaydGB1JrWQfgLImWouiC4bsZEzNhnX6uYQ8qSL8zxsK7xOfeVocP+FHdkKcB85giQFp/onuNwHBWLXw9iC2Z/rrbjN2dPSaDKFWQT7ukE2vqt9TQ6mMpYFBCiHpJUfSxXjgjL7Y1MN58QCJ+PesQEY8hh1DzRBwgY0lY9LYAdrqWwj6AIPPawZTcJnNAwz9wO3a8hAS6i9dK+zHDtSIlArevmP8mpcqhpHEtKZ4TbAel7YRtbvY+w7pENbXQiiNMRkdZ28m6FJAFlIHv/wMpUhgZG3SyfFTDg33VhVFlS0qzvIYjTxMPjGLT4oBXK3+CSBuZKwE3xG39S/oTu++feTCtSu5VZZm9rkzrE77tIoWfGi0eGbfJURP9F9q96F0YuNUAS+gnCw5LzR48sMjqXcUpNHVRwi8XE7TDgl7Fk4JHfJelL3LBjFsZC7uaLmy8I1tk+87xTFd0VyG0cAaX/jMbWn1XGVo1V1uXFYRVmfyiPcJBhUaPQ6z1QDXQzsQLed9nQL9qFFPyjoL0zN7Fp+AVka0kPNhkEl0HIL8KqU7cuoypSeA7EO8Qxk7ay8nSP1PLlYzVUZEvEleBjPHTzO6YZxNMRLZSljp8BoY+lw== Johnny Bravo"
  190.  
  191. # Github SSH pubkey(s) to add
  192. GITPUBKEYS=nukien
  193. # GITPUBKEYS="nukien george harry"
  194.  
  195. # Custom script to run after Setup.sh has run in the debootstrap system.  This is to further install any
  196. # other packages you want, or perform any other setup you need.  It can be simply the name of a bash
  197. # script that you have ready in the same dir as this ZFS-setup.sh script, or it can be a URL, in which case
  198. # it will be fetched and copied into the new system alongside Setup.sh, and executed from within Setup.sh
  199. # NOTE: It will be renamed to "Setup-Custom.sh" in the new system
  200. CUSTOMSCRIPT=ZFS-Custom.sh
  201. # CUSTOMSCRIPT="http://pastebin.com/raw/faX12Y34Z"
  202.  
  203. # System name (also used for mdadm raid set names and filesystem LABELs)
  204. # Note: Only first 10 chars of name will be used for LABELs and the pool name
  205. SYSNAME=installerbox
  206.  
  207. # Do we want /home to be a separate dataset container, with /home/username
  208. # each being a unique dataset ? Set to y to enable.
  209. HOMEPOOL=
  210.  
  211. # zpool pool name - usually taken from the system name above. Can be overridden here
  212. # POOLNAME=
  213.  
  214. # Using LUKS for encryption (y/n) ? Please use a nice long complicated passphrase ...
  215. # If enabled, will encrypt partition_swap (md raid) and partition_data (zfs)
  216. # If PASSPHRASE is blank, will prompt for a passphrase
  217. LUKS=
  218. PASSPHRASE=password
  219. # Use detached headers ?  If y then save LUKS headers in /root/headers
  220. # NOTE: not working yet - have to figure out /etc/crypttab and /etc/initramfs-tools/conf.d/cryptroot
  221. DETACHEDHEADERS=
  222.  
  223. # Randomize or zero out the disks for LUKS ?  (y/n)
  224. # Randomizing makes for much better encryption
  225. # Zeroing is good for prepping to create an OVA file, makes for better compression
  226. # NOTE: Can only choose one, not both !
  227. RANDOMIZE=
  228. ZERO=
  229.  
  230. # Using a proxy like apt-cacher-ng ?
  231. # PROXY=http://192.168.2.104:3142/
  232. # PROXY=
  233.  
  234. # zpool raid level to use for more than 2 disks - raidz, raidz2, raidz3, mirror
  235. # For 2 disks, will be forced to mirror
  236. ZPOOLEVEL=raidz
  237.  
  238. ###################################################
  239. # Specify the host key for the new root-on-zfs system ?
  240. # Can be the RSA or ECDSA key from /etc/ssh
  241. # Leave blank for no specific key - ie: use whatever is generated by the openssh installation
  242. # Be sure to use SINGLE quotes for private key
  243. HOST_ECDSA_KEY='-----BEGIN EC PRIVATE KEY-----
  244. MHcCAQEEIO+XmG1AGCiQUejcjS/aVMGaocBe7TCsEmLctyNoJWFqoAoGCCqGSM49
  245. AwEHoUQDQgAEMG1kiuILJZsxJCi1j5xOrA2CpNETWQ5rA94tgjsX6aqpI8re1pwa
  246. /rnYIYrCL/JafwsmlqKG/HfrkvgozqVn/A==
  247. -----END EC PRIVATE KEY-----'
  248. # Be sure to use DOUBLE quotes for public key
  249. HOST_ECDSA_KEY_PUB="ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDBtZIriCyWbMSQotY+cTqwNgqTRE1kOawPeLYI7F+mqqSPK3tacGv652CGKwi/yWn8LJpaihvx365L4KM6lZ/w= root@installerbox"
  250. # Be sure to use SINGLE quotes for private key
  251. HOST_RSA_KEY='-----BEGIN RSA PRIVATE KEY-----
  252. MIIEpQIBAAKCAQEAzCR0pGQ2ITL2KSgzeASWCGgP+mNQRv+Z7VlOCyjmVctODDl3
  253. SiMHdsLRyhcP1M9jfTBEncKrt4AQIt1f1bjAG4kNEgh18dMUYWtIIZ3HlGP+Ieux
  254. EixkakZ2o1qnhmfPG7W3pnw6UHwwZw3Qg6H760PWAmU12gG3YOEuq9DKmBdw2i80
  255. jqcGGREj+BIdROuPKdH+n3DGE0phQ+NwQzMU77czPh1XwcLBGGpEvvk1zbavyqv5
  256. dunsz3msMuJZH2oBE2PeWr8E2x+nNQ2XZIZdHJD8WJMiPBvHUBYMo7CSEAzwdWcs
  257. g8f4umes/LKakv9/h4e47dOOzU1xFwCNo9lOnQIDAQABAoIBAQCPL8Lgy6lr/+LJ
  258. W3k+ZXkWzGboqWBVbFL7N/iVu0pUQxWrXWNejNNfaabcqPBhxFV0Kbb3MORhAWJQ
  259. EhZ2Qe/9YFPaojSYOgXBjw45BgJHAxvtjvPUW27TXDk6uwtmKsoKFZuLGveMHI+W
  260. uQnYSnX4vswNQhBTqYCGY2vo97oikoyTLGEPURbyNpc1NOI7TGuOXHmOAEhw7WN8
  261. jd1wTm2TEjdqMO6Zk03VJn9h5yu6sR7siqEkzIF5p/sfOXoA2Iwh3Sazrsv63R2p
  262. XBYhnfnrM3UuEd4cKGJjXrv1gxNu1AKGKdq34izjKw/YKJhGRuiLh+9gdMva2TcV
  263. dqOqfYQBAoGBAPm2ocF2Hn10Ud/UkcqQc2uPV7+bHhNALzHG5YeXH9vHJq/rm9D8
  264. UFt3OBneaZMXCWRSl1dTlidmt+yl2wk0JyWFmEHZK2wDu+qcRPKT6y4Du+7QRBQY
  265. IwrBHWi8reCbM/wL+s8cEGFt19ip6jw1K1JIxkTtC2vtG0ayPATJJyexAoGBANFI
  266. IAEnZuf3zqECjdNfSr8ITMIfLZhDs/oPBzWUkwMm9jaIi+cf96hSlLFhMWANZOM6
  267. i2x/68AHT9hINqo25cJeQB0UqLeHaU2JDAKn3LOLtCu7D0bpZKbAVFVgd3XsYrRJ
  268. z5+Zz80WyXa+pHTqnrhTP0xkvCCmbWjz+Q5T9jytAoGBAKAOzvmpE3wITd5xaw1y
  269. r3iXBYCcFZfzQQzf1wmk9Vey+/oww8wdnggyj3QNWpBcaLm0MqtXuVwB/AwkdxQc
  270. KKdlTSWP5MQ0VIPZrFvsMgdpf1FgjvJuUi+3fnk+zxizgougxh9wdpNsi7ilmK0E
  271. y4LPgL53TiXccepLnirXIFDRAoGAXLzaOcitCCO+c4i/Migq5iYWZXsNaEiwCyH3
  272. rt2Mm7v7JMUzQZLf2r3lWAjaqVamGy8JM2YoIKrczdmKJ7k17QB45qoN7W3a0tnk
  273. 8ZRS71j72NkGdwTbbi0R8ddSeHXsczm2AGJXO+laEv19wLVq6gExrneBCfLVzsk1
  274. 1wyLs+0CgYEAuux1i+/7TMh1LyaiNbqQt4uzlDR+EWnbOBTtku9cE7u/dHuy1roE
  275. QA4S2UhEX0sXdekqsFsIS/Qo3+H9pLC8mAZ1X0sQl102z2Cks1WVruodf8tF58iu
  276. FCMSOeHX+wYqyZSm1zLDONoneY5B3zu1Grc8dZRJSons3iaXWl7zj3M=
  277. -----END RSA PRIVATE KEY-----'
  278. # Be sure to use DOUBLE quotes for public key
  279. HOST_RSA_KEY_PUB="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMJHSkZDYhMvYpKDN4BJYIaA/6Y1BG/5ntWU4LKOZVy04MOXdKIwd2wtHKFw/Uz2N9MESdwqu3gBAi3V/VuMAbiQ0SCHXx0xRha0ghnceUY/4h67ESLGRqRnajWqeGZ88btbemfDpQfDBnDdCDofvrQ9YCZTXaAbdg4S6r0MqYF3DaLzSOpwYZESP4Eh1E648p0f6fcMYTSmFD43BDMxTvtzM+HVfBwsEYakS++TXNtq/Kq/l26ezPeawy4lkfagETY95avwTbH6c1DZdkhl0ckPxYkyI8G8dQFgyjsJIQDPB1ZyyDx/i6Z6z8spqS/3+Hh7jt047NTXEXAI2j2U6d root@installerbox"
  280. ###################################################
  281.  
  282. # Are we configuring to use UEFI ?
  283. # NOTE: Most information for EFI install comes from here :
  284. #   http://blog.asiantuntijakaveri.fi/2014/12/headless-ubuntu-1404-server-with-full.html
  285. # If it detects /sys/firmware/efi then it forces this to y
  286. # Currently not booting properly under UEFI dangit
  287. UEFI=
  288.  
  289. # Force the swap partition size for each disk in MB if you don't want it calculated
  290. # If you want Resume to work, total swap must be > total ram
  291. # For 2 disks, will use raid-1 striped, so total = size_swap * num_disks
  292. # For 3+ disks, will use raid-10, so total = size_swap * num_disks / 2
  293. # Set to 0 to disable (SIZE_SWAP = swap partitions, SIZE_ZVOL = zfs zvol in ${POOLNAME})
  294. SIZE_SWAP=100
  295. # Use a zfs volume for swap ?  Set the total size of that volume here.
  296. # NOTE: Cannot be used for Resume
  297. SIZE_ZVOL=100
  298.  
  299. # Use zswap compressed page cache in front of swap ? https://wiki.archlinux.org/index.php/Zswap
  300. USE_ZSWAP="\"zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=25\""
  301. # USE_ZSWAP=
  302.  
  303. # If the system uses a Realtek 8168/8169 ethernet, the driver version specified here
  304. # will be downloaded and installed
  305. RTL8168_VERSION="8.044.02"
  306.  
  307. # Remove systemd ?  If set to y will remove systemd and replace with upstart
  308. ##### NOTE : Not working yet
  309. # REMOVE_SYSTEMD=yes
  310.  
  311. # Set the source of debootstrap - can be a local repo built with apt-move or uncommenting the the lines below
  312. # https://wiki.ubuntu.com/SergeHallyn_localrepo
  313. DEBOOTSTRAP="http://us.archive.ubuntu.com/ubuntu/"
  314. # DEBOOTSTRAP="file:///root/UBUNTU"
  315. #-------------------------------------------------
  316. # mkdir -p ${DEBOOTSTRAP}/dists/${SUITE}/main/binary-amd64 ${DEBOOTSTRAP}/pool/main
  317. # apt-get --no-install-recommends install debootstrap apt-utils
  318. # debootstrap --download-only ${SUITE} ${DEBOOTSTRAP}/cache
  319. # mv ${DEBOOTSTRAP}/cache/var/cache/apt/archive/* ${DEBOOTSTRAP}/pool/main
  320. # cd ${DEBOOTSTRAP}
  321. # apt-ftparchive package pool/main | gzip -9c > dists/${SUITE}/main/binary-amd64/Packages.gz
  322. # cat > release.conf << EOF
  323. # APT::FTPArchive::Release {
  324. # Origin "APT-Move";
  325. # Label "APT-Move";
  326. # Suite "${SUITE}";
  327. # Codename "${SUITE}";
  328. # Architectures "amd64";
  329. # Components "main";
  330. # Description "Local Updates";
  331. # };
  332. # EOF
  333. # apt-ftparchive -c release.conf release dists/${SUITE}/ > dists/${SUITE}/Release
  334. #-------------------------------------------------
  335.  
  336. # Generic partition setup as follows
  337. # sdX1 :    EFI boot
  338. # sdX2 :    Grub boot
  339. # sdX3 :    /boot (only used for LUKS)
  340. # sdX4 :    swap
  341. # sdX5 :    main ZFS partition
  342. # sdX9 :    ZFS reserved
  343.  
  344. # Partition numbers and sizes of each partition in MB
  345. PARTITION_EFI=1
  346. SIZE_EFI=256
  347. PARTITION_GRUB=2
  348. SIZE_GRUB=5
  349. PARTITION_BOOT=3
  350. SIZE_BOOT=500
  351. PARTITION_SWAP=4
  352. PARTITION_DATA=5
  353. PARTITION_RSVD=9
  354.  
  355. # ------ End of user settable variables ---------------------------------------------------
  356.  
  357. if [[ $EUID -ne 0 ]]; then
  358.     echo "This script must be run as root" 1>&2
  359.     exit 1
  360. fi
  361.  
  362. [ -d /sys/firmware/efi ] && UEFI=y
  363.  
  364. # System name for labels, main pool, etc.
  365. BOXNAME=${SYSNAME:0:10}
  366. # Main pool name
  367. [ ! ${POOLNAME} ] && POOLNAME=${SYSNAME:0:10}
  368. if [ ${#SYSNAME} -gt 10 ]; then
  369.     echo "$(tput setaf 1)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$(tput sgr0)"
  370.     echo "$(tput setaf 1)!!$(tput sgr0)"
  371.     echo "$(tput setaf 1)!!$(tput setaf 6) ${SYSNAME}$(tput sgr0) is too long - must be 10 chars max"
  372.     echo "$(tput setaf 1)!!$(tput sgr0) Will use $(tput setaf 6)${BOXNAME}$(tput sgr0) in labels and poolname"
  373.     echo "$(tput setaf 1)!!$(tput sgr0)"
  374.     echo "$(tput setaf 1)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$(tput sgr0)"
  375.     echo "$(tput setaf 3) Press <enter> to continue, or ctrl-C to abort $(tput setaf 1)"
  376.     read -t 10 QUIT
  377.     echo ""
  378. fi
  379.  
  380. # Generate (if necessary) list of disks and ask user below if it's good to go
  381. [ ! -e /root/ZFS-setup.disks.txt ] && for disk in $(ls -l /dev/disk/by-id | egrep -v '(CDROM|CDRW|-ROM|CDDVD|-part|md-|dm-|wwn-)' | sort -t '/' -k3 | tr -s " " | cut -d' ' -f9); do echo $disk >> /root/ZFS-setup.disks.txt; done
  382.  
  383. i=1
  384. for disk in $(cat /root/ZFS-setup.disks.txt) ; do
  385.     DISKS[$i]=$disk
  386.     i=$(($i+1))
  387. done
  388.  
  389. # Calculate proper SWAP size (if not defined above) - should be same size as total RAM in system
  390. MEMTOTAL=$(cat /proc/meminfo | fgrep MemTotal | tr -s ' ' | cut -d' ' -f2)
  391. [ ${SIZE_SWAP} ] || SIZE_SWAP=$(( ${MEMTOTAL} / ${#DISKS[@]} / 1024 ))
  392.  
  393. echo -n "$(tput setaf 1)!!!!!!!!!!!!!!!! $(tput setaf 4)Installing $(tput setaf 7)${SUITE} "
  394. [ ${SUITE} = "trusty" ] && echo -n "14.04"
  395. [ ${SUITE} = "xenial" ] && echo -n "16.04"
  396. if [ "ZZ${LUKS}" = "ZZy" ]; then
  397.     echo -n " $(tput setaf 4)on LUKS "
  398. else
  399.     echo -n "$(tput setaf 1)!!!!!!!!!"
  400. fi
  401. echo "$(tput setaf 1)!!!!!!!!!!!!!!!!!!!!!!!!!!!"
  402. echo "$(tput setaf 1)!!"
  403. echo "$(tput setaf 1)!!$(tput sgr0)  These are the disks we're about for $(tput setaf 1)FORMAT$(tput sgr0) for ZFS"
  404. echo "$(tput setaf 1)!!"
  405. i=1
  406. for disk in $(seq 1 ${#DISKS[@]}) ; do
  407.     echo "$(tput setaf 1)!!$(tput sgr0)  disk $i = ${DISKS[$i]} ($(readlink /dev/disk/by-id/${DISKS[$i]} | cut -d/ -f3))"
  408.     i=$(($i+1))
  409. done
  410. echo "$(tput setaf 1)!!"
  411. echo "$(tput setaf 1)!!$(tput sgr0)  Be $(tput setaf 1)SURE$(tput sgr0), really $(tput setaf 1)SURE$(tput sgr0), as they will be wiped completely"
  412. echo "$(tput setaf 1)!!$(tput sgr0)  Otherwise abort and edit the $(tput setaf 6)/root/ZFS-setup.disks.txt$(tput sgr0) file"
  413. echo "$(tput setaf 1)!!"
  414.  
  415. if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  416.     if [ ${#DISKS[@]} = 1 ]; then
  417.         SIZE_SWAP_TOTAL=${SIZE_SWAP}
  418.     elif [ ${#DISKS[@]} = 2 ]; then
  419.         # raid1 striped size
  420.         SIZE_SWAP_TOTAL=$(( ${SIZE_SWAP} * ${#DISKS[@]} ))
  421.     else # More than 2 disks
  422.         # raid10 size
  423.         SIZE_SWAP_TOTAL=$(( ${SIZE_SWAP} * ${#DISKS[@]} / 2 ))
  424.     fi
  425.     echo "$(tput setaf 1)!!$(tput sgr0)  ${#DISKS[@]} SWAP partitions of ${SIZE_SWAP}MB = $(( ${SIZE_SWAP_TOTAL} / 1024 ))GB = ${SIZE_SWAP_TOTAL}MB total"
  426.     echo -n "$(tput setaf 1)!!$(tput sgr0)  Ram = ${MEMTOTAL}kb Swap partitions $(tput setaf 3)"
  427.     if [ ${#DISKS[@]} = 1 ]; then
  428.         echo -n ""
  429.     elif [ ${#DISKS[@]} = 2 ]; then
  430.         echo -n "raid1"
  431.     else
  432.         echo -n "raid10"
  433.     fi
  434.     echo " $(tput sgr0)= $(( ${SIZE_SWAP_TOTAL} * 1024 ))kb "
  435.  
  436.     # Say whether resume is possible
  437.     if [ ${MEMTOTAL} -gt $(( ${SIZE_SWAP_TOTAL} * 1024 )) ] ; then
  438.         SWAPRESUME=n
  439.         echo "$(tput setaf 1)!!$(tput sgr0)  Hibernate/Resume $(tput setaf 1)NOT$(tput sgr0) possible"
  440.     else
  441.         SWAPRESUME=y
  442.         echo "$(tput setaf 1)!!$(tput sgr0)  Hibernate/Resume $(tput setaf 6)IS$(tput sgr0) possible"
  443.     fi
  444.    
  445.     echo "$(tput setaf 1)!!$(tput sgr0)  Edit $(tput setaf 6)/root/ZFS-setup.sh$(tput sgr0) to force the swap partition size with SIZE_SWAP"
  446.     echo "$(tput setaf 1)!!$(tput sgr0)  NOTE: If only 2 disks   -> swap partitions are raid1/mirrored."
  447.     echo "$(tput setaf 1)!!$(tput sgr0)        More than 2 disks -> swap partitions are raid10."
  448.     echo "$(tput setaf 1)!!"
  449. fi
  450.  
  451. echo "$(tput setaf 1)!!!!!!!!$(tput setaf 3) Press <enter> to continue, or ctrl-C to abort $(tput setaf 1)!!!!!!!!!!!!!!!!!!!!!$(tput sgr0)"
  452. read -t 10 QUIT
  453.  
  454. IMPORT_POOLS=$(zpool import 2>&1)
  455. CURRENT_POOLS=$(zpool list 2>&1)
  456. if [[ "${IMPORT_POOLS}" =~ "${POOLNAME}" ]] || [[ "${CURRENT_POOLS}" =~ "${POOLNAME}" ]] ; then
  457.     echo "$(tput setaf 1)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$(tput sgr0)"
  458.     echo "$(tput setaf 1)!!$(tput sgr0)"
  459.     echo "$(tput setaf 1)!!$(tput sgr0)  ZFS pool ${POOLNAME} already exists"
  460.     echo "$(tput setaf 1)!!$(tput sgr0)"
  461.     echo "$(tput setaf 1)!!$(tput sgr0)  Current pools list"
  462.     echo "$(tput setaf 6)${CURRENT_POOLS}"
  463.     echo "$(tput setaf 1)!!$(tput sgr0)"
  464.     echo "$(tput setaf 1)!!$(tput sgr0)  Importable pools list"
  465.     echo "$(tput setaf 6)${IMPORT_POOLS}"
  466.     echo "$(tput setaf 1)!!$(tput sgr0)"
  467.     echo "$(tput setaf 1)!!$(tput sgr0)  You must destroy that pool (importing first if needed)"
  468.     echo "$(tput setaf 1)!!$(tput sgr0)     zpool import -R /mnt ${POOLNAME}"
  469.     echo "$(tput setaf 1)!!$(tput sgr0)     zfs destroy ${POOLNAME}"
  470.     echo "$(tput setaf 1)!!$(tput sgr0)"
  471.     echo "$(tput setaf 1)!!!!!!!!$(tput setaf 3) Exiting ZFS-setup $(tput setaf 1)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$(tput sgr0)"
  472.     exit
  473. fi
  474.  
  475.  
  476. # Input USERNAME password for main id
  477. if [ "ZZ${UPASSWORD}" = "ZZ" ] ; then
  478.     DONE=false
  479.     until ${DONE} ; do
  480.         echo ""
  481.         echo "$(tput sgr0)Please enter password for $(tput setaf 3)${USERNAME}$(tput sgr0) in new system"
  482.         read -s -p "Password: " PASSWORD1
  483.         echo ""
  484.         read -s -p "Password again: " PASSWORD2
  485.         [ ${PASSWORD1} = ${PASSWORD2} ] && DONE=true
  486.     done
  487.     echo ""
  488.     UPASSWORD=${PASSWORD1}
  489. fi
  490.  
  491. # Input LUKS encryption passphrase
  492. if [ "ZZ${PASSPHRASE}" = "ZZ" ] && [ "ZZ${LUKS}" = "ZZy" ] ; then
  493.     DONE=false
  494.     until ${DONE} ; do
  495.         echo ""
  496.         echo "$(tput sgr0)Please enter $(tput setaf 3)passphrase$(tput sgr0) for disk encryption for new system"
  497.         read -s -p "Passphrase: " PASSWORD1
  498.         echo ""
  499.         read -s -p "Passphrase again: " PASSWORD2
  500.         [ ${PASSWORD1} = ${PASSWORD2} ] && DONE=true
  501.     done
  502.     echo ""
  503.     PASSPHRASE=${PASSWORD1}
  504. fi
  505.  
  506. # Log everything we do
  507. rm -f /root/ZFS-setup.log
  508. exec > >(tee -a "/root/ZFS-setup.log") 2>&1
  509.  
  510. # Proxy
  511. if [ ${PROXY} ]; then
  512.     # These are for debootstrap
  513.     export http_proxy=${PROXY}
  514.     export ftp_proxy=${PROXY}
  515.     # This is for apt-get
  516.     echo 'Acquire::http::proxy "${PROXY}";' > /etc/apt/apt.conf.d/03proxy
  517. fi
  518.  
  519. # If a CDROM is listed in sources.list it borks things up.  We want latest from internet anyway ...
  520. # ElementaryOS and Linux Mint18 have a cdrom listed for example
  521. sed -i 's/deb cdrom/## deb cdrom/' /etc/apt/sources.list
  522.  
  523. ### TODO
  524. # Need to wait till apt update is finished
  525. # Elementary uses packagekitd when booted from dvd/iso
  526. # Elementary uses apt.systemd.daily when booted from minimal install
  527. #
  528. # Sample ansible tasks to do this
  529. #
  530. # - name: Check for apt.systemd.daily
  531. #   shell: ps axf | grep apt.systemd.daily | grep -v grep | cut -c1-5 | tr -d ' '
  532. #   register: apt_systemd_daily
  533. #
  534. # - name: Wait for apt.systemd.daily ({{ apt_systemd_daily.stdout }}) to exit
  535. #   wait_for:
  536. #     path: "/proc/{{ apt_systemd_daily.stdout }}/cmdline"
  537. #     state: absent
  538. #     timeout: 180
  539. #   when: apt_systemd_daily.stdout != ""
  540.  
  541. apt-get -qq update > /dev/null
  542. for UTIL in /sbin/{gdisk,mdadm,cryptsetup} /usr/sbin/debootstrap ; do
  543.     [ ! -e ${UTIL} ] && apt-get -qq -y --no-install-recommends install `basename ${UTIL}`
  544. done
  545.  
  546. echo "-----------------------------------------------------------------------------"
  547. echo "Clearing out md raid and LUKS info from disks"
  548. # Unmount any mdadm disks that might have been automounted
  549. umount /dev/md* > /dev/null 2>&1
  550. # Stop all found mdadm arrays
  551. mdadm --stop --force /dev/md* > /dev/null 2>&1
  552. for DISK in `seq 1 ${#DISKS[@]}` ; do
  553.     echo ">>>>> ${DISKS[${DISK}]}"
  554.     # Wipe mdadm superblock from all partitions found, even if not md raid partition
  555.     mdadm --zero-superblock --force /dev/disk/by-id/${DISKS[${DISK}]} > /dev/null 2>&1
  556.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_BOOT} ] && mdadm --zero-superblock --force /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_BOOT} > /dev/null 2>&1
  557.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_SWAP} ] && mdadm --zero-superblock --force /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_SWAP} > /dev/null 2>&1
  558.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_RSVD} ] && mdadm --zero-superblock --force /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_RSVD} > /dev/null 2>&1
  559.  
  560.     # Clear any old LUKS or mdadm info
  561.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} ] && dd if=/dev/zero of=/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} bs=512 count=20480 > /dev/null 2>&1
  562.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_SWAP} ] && dd if=/dev/zero of=/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_SWAP} bs=512 count=20480 > /dev/null 2>&1
  563.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_RSVD} ] && dd if=/dev/zero of=/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_RSVD} bs=512 count=4096 > /dev/null 2>&1
  564.  
  565.     # wipe it out ...
  566.     wipefs -a /dev/disk/by-id/${DISKS[${DISK}]}
  567.     # Zero old MBR and GPT partition information on disks
  568.     sgdisk -Z /dev/disk/by-id/${DISKS[${DISK}]}
  569.     sgdisk --clear /dev/disk/by-id/${DISKS[${DISK}]}
  570. done
  571.  
  572. # Make sure we have utilities we need
  573. if [ ! -e /sbin/zpool ]; then
  574.     if [ "$(lsb_release -cs)" = "trusty" ] ; then
  575.         apt-add-repository --yes ppa:zfs-native/stable
  576.         echo "--- apt-get update"
  577.         apt-get -qq update > /dev/null
  578.         apt-get -qq -y --no-install-recommends install ubuntu-zfs zfsutils
  579.     fi
  580.     # DISTRO can be either Ubuntu16.04 = xenial  ElementaryOS = loki  Mint18 Cinnamon = serena
  581.     # It can also NOT be defined (as for a simple server) in which case we need "xenial"
  582.     if [ "$(lsb_release -cs)" = "xenial" ] || [ "$(lsb_release -cs)" = "${DISTRO}" ] ; then
  583.         sed -i 's/restricted/restricted universe/' /etc/apt/sources.list
  584.         echo "--- apt-get update"
  585.         apt-get -qq update > /dev/null
  586.         apt-get -qq -y --no-install-recommends install zfsutils-linux spl
  587.     fi 
  588.     modprobe zfs
  589. fi
  590.  
  591. # For more packages whose name doesn't match the executable, use this method
  592. #
  593. # UTIL_FILE[0]=/sbin/mdadm ;            UTIL_PKG[0]=mdadm
  594. # UTIL_FILE[1]=/sbin/gdisk ;            UTIL_PKG[1]=gdisk
  595. # UTIL_FILE[3]=/usr/sbin/debootstrap ;  UTIL_PKG[2]=debootstrap
  596. # UTIL_FILE[4]=/usr/sbin/sshd ;         UTIL_PKG[4]=openssh-server
  597. # for UTIL in `seq 0 ${#UTIL_FILE[@]}` ; do
  598. #   UTIL_INSTALL="${UTIL_INSTALL} ${UTIL_PKG[${UTIL}]}"
  599. # done
  600. # apt-get -qq -y --no-install-recommends install ${UTIL_INSTALL}
  601.  
  602. # Unmount any mdadm disks that might have been automounted
  603. umount /dev/md* > /dev/null 2>&1
  604. # Stop all found mdadm arrays - again, just in case.  Sheesh.
  605. mdadm --stop --force /dev/md* > /dev/null 2>&1
  606.  
  607. # Randomize or zero entire disk if requested
  608. if [ "ZZ${RANDOMIZE}" = "ZZy" ] || [ "ZZ${ZERO}" = "ZZy" ]; then
  609.     echo "-----------------------------------------------------------------------------"
  610.     if [ "ZZ${RANDOMIZE}" = "ZZy" ] ; then
  611.         echo "Fetching frandom kernel module"
  612.         # urandom is limited, so use frandom module
  613.         [ ! -e /var/lib/dpkg/info/build-essential.list ] && apt-get -qq -y install build-essential
  614.         mkdir -p /usr/src/frandom
  615.         wget --no-proxy http://billauer.co.il/download/frandom-1.1.tar.gz -O /usr/src/frandom/frandom-1.1.tar.gz
  616.         cd /usr/src/frandom
  617.         tar xvzf frandom-1.1.tar.gz
  618.         cd frandom-1.1
  619.         make
  620.         install -m 644 frandom.ko /lib/modules/`uname -r`/kernel/drivers/char/
  621.         depmod -a
  622.         modprobe frandom
  623.         SRC_DEV="/dev/frandom"
  624.     else
  625.         SRC_DEV="/dev/zero"
  626.     fi
  627.  
  628.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  629.         echo "Zeroing/Randomizing ${DISKS[${DISK}]}"
  630.         dd if=${SRC_DEV} of=/dev/disk/by-id/${DISKS[${DISK}]} bs=512 count=$(blockdev --getsz /dev/disk/by-id/${DISKS[${DISK}]}) &
  631.         WAITPIDS="${WAITPIDS} "$!
  632.     done
  633.  
  634.     # USR1 dumps status of dd, this will take around 6 hours for 3TB SATA disk
  635.     # killall -USR1 dd
  636.  
  637.     echo "Waiting for disk zeroing/randomizing to finish"
  638.     wait ${WAITPIDS}
  639.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  640.         partprobe /dev/disk/by-id/${DISKS[${DISK}]}
  641.     done
  642. fi
  643.  
  644. echo "-----------------------------------------------------------------------------"
  645. echo "Clearing out zpool info from disks, creating partitions"
  646. for DISK in `seq 1 ${#DISKS[@]}` ; do
  647.     echo ">>>>> ${DISKS[${DISK}]}"
  648.  
  649.     # Clear any old zpool info
  650.     zpool labelclear -f /dev/disk/by-id/${DISKS[${DISK}]} > /dev/null 2>&1
  651.     [ -e /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} ] && zpool labelclear -f /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} > /dev/null 2>&1
  652.  
  653.     # Create new GPT partition label on disks
  654.     parted -s -a optimal /dev/disk/by-id/${DISKS[${DISK}]} mklabel gpt
  655.     # Rescan partitions
  656.     partprobe /dev/disk/by-id/${DISKS[${DISK}]}
  657.  
  658.     if [ "ZZ${UEFI}" = "ZZy" ]; then
  659.         sgdisk -n1:2048:+${SIZE_EFI}M -t1:EF00 -c1:"EFI_${DISK}"  /dev/disk/by-id/${DISKS[${DISK}]}
  660.     fi
  661.         sgdisk -n2:0:+${SIZE_GRUB}M -t2:EF02 -c2:"GRUB_${DISK}" /dev/disk/by-id/${DISKS[${DISK}]}
  662.     if [ "ZZ${LUKS}" = "ZZy" ]; then
  663.         sgdisk -n3:0:+${SIZE_BOOT}M -t3:FD00 -c3:"BOOT_${DISK}" /dev/disk/by-id/${DISKS[${DISK}]}
  664.     fi
  665.     if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  666.         sgdisk -n4:0:+${SIZE_SWAP}M -t4:FD00 -c4:"SWAP_${DISK}" /dev/disk/by-id/${DISKS[${DISK}]}
  667.     fi
  668.         sgdisk -n5:0:-8M            -t5:BF01 -c5:"ZFS_${DISK}"  /dev/disk/by-id/${DISKS[${DISK}]}
  669.         sgdisk -n9:0:0              -t9:BF07 -c9:"RSVD_${DISK}" /dev/disk/by-id/${DISKS[${DISK}]}
  670.     partprobe /dev/disk/by-id/${DISKS[${DISK}]}
  671.     echo ""
  672. done
  673. echo "---- Sample disk layout -----------------------------------"
  674. gdisk -l /dev/disk/by-id/${DISKS[1]}
  675.  
  676. # Have to make sure we can actually SEE all the new partitions, so sleep a couple of times
  677. # If you get errors about No such file or directory for /dev/disk/by-id/ata-xxxxxx this is needed
  678. sleep 5
  679. echo "---- List of disks and -part5 partitions ------------------"
  680. for DISK in `seq 1 ${#DISKS[@]}` ; do
  681.     partprobe /dev/disk/by-id/${DISKS[${DISK}]}
  682.     ls -la /dev/disk/by-id/${DISKS[${DISK}]}
  683.     ls -la /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA}
  684. done
  685. sleep 5
  686.  
  687. # Build list of partitions to use for ...
  688. # Boot partition (mirror across all disks)
  689. PARTSBOOT=
  690. PARTSSWAP=
  691. PARTSRSVD=
  692. PARTSEFI=
  693. # ZFS partitions to create zpool with
  694. ZPOOLDISK=
  695. for DISK in `seq 1 ${#DISKS[@]}` ; do
  696.     PARTSSWAP="/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_SWAP} ${PARTSSWAP}"
  697.     PARTSBOOT="/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_BOOT} ${PARTSBOOT}"
  698.     PARTSEFI="/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_EFI} ${PARTSEFI}"
  699.     if [ "ZZ${LUKS}" = "ZZy" ]; then
  700.         PARTSRSVD="/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_RSVD} ${PARTSRSVD}"
  701.         ZPOOLDISK="/dev/mapper/root_crypt${DISK} ${ZPOOLDISK}"
  702.     else
  703.         ZPOOLDISK="/dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} ${ZPOOLDISK}"
  704.     fi
  705. done
  706.  
  707. # Pick raid level to use dependent on number of disks
  708. # disks = 2 : zpool and swap use mirror
  709. # disks > 2 : zpool use raidz, swap use raid10
  710. case ${#DISKS[@]} in
  711.     0)
  712.         echo "*****************************************"
  713.         echo "***  Something wrong - no drives defined"
  714.         echo "*****************************************"
  715.         exit 1
  716.         ;;
  717.     1)
  718.         ZPOOLEVEL=
  719.         # And, just to be sure, since sometimes stuff hangs around
  720.         # Unmount any mdadm disks that might have been automounted
  721.         umount /dev/md* > /dev/null 2>&1
  722.         # Stop all found mdadm arrays
  723.         mdadm --stop --force /dev/md* > /dev/null 2>&1
  724.  
  725.         ;;
  726.     2)
  727.         ZPOOLEVEL=mirror
  728.         SWAPRAID=raid1
  729.         ;;
  730.     *)
  731.         # ZPOOLEVEL is left to whatever you chose at top in vars list
  732.         SWAPRAID="raid10 -p f2"
  733.         ;;
  734. esac
  735.  
  736. # Create raid for swap if SIZE_SWAP defined (use -p f2 for raid10)
  737. if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  738.     if [ ${#DISKS[@]} = 1 ]; then
  739.         SWAPDEVRAW=${PARTSSWAP}
  740.     elif [ ${#DISKS[@]} -gt 1 ]; then
  741.         echo "-----------------------------------------------------------------------------"
  742.         echo "Creating ${BOXNAME}:swap ${SWAPRAID} for new system"
  743.         echo y | mdadm --create /dev/md/${BOXNAME}:swap --metadata=1.0 --force --level=${SWAPRAID} --raid-devices=${#DISKS[@]} --homehost=${BOXNAME} --name=swap --assume-clean ${PARTSSWAP}
  744.         SWAPDEVRAW="/dev/md/${BOXNAME}:swap"
  745.     fi
  746. fi
  747.  
  748. # Format EFI System Partitions on all disks as FAT32 in raid1
  749. if [ "ZZ${UEFI}" = "ZZy" ]; then
  750.     if [ ${#DISKS[@]} = 1 ]; then
  751.         EFIDEVRAW=${PARTSEFI}
  752.     elif [ ${#DISKS[@]} -gt 1 ]; then
  753.         echo "-----------------------------------------------------------------------------"
  754.         echo "Creating ${BOXNAME}:efi mirror for new system"
  755.         echo y | mdadm --create /dev/md/${BOXNAME}:efi --metadata=1.0 --force --level=mirror --raid-devices=${#DISKS[@]} --homehost=${BOXNAME} --name=efi --assume-clean ${PARTSEFI}
  756.         EFIDEVRAW="/dev/md/${BOXNAME}:efi"
  757.     fi
  758.     mkfs.vfat -v -F32 -s2 -n "${BOXNAME}_efi" ${EFIDEVRAW} > /dev/null
  759.  
  760.     #for DISK in `seq 1 ${#DISKS[@]}` ; do
  761.     #   echo "${DISKS[${DISK}]}-part${PARTITION_EFI}"
  762.     #   mkfs.vfat -v -F32 -s2 -n "EFI_${DISK}" /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_EFI} > /dev/null 2>&1
  763.     #done
  764. fi
  765.  
  766. # Create LUKS devices if LUKS enabled
  767. if [ "ZZ${LUKS}" = "ZZy" ]; then
  768.     echo "-----------------------------------------------------------------------------"
  769.     mkdir -p /root/headers
  770.     # Create encrypted rsvd on top of md array - used as main key for other encrypted
  771.     if [ ${#DISKS[@]} = 1 ]; then
  772.         RSVDDEVRAW=${PARTSRSVD}
  773.     else
  774.         RSVDDEVRAW="/dev/md/${BOXNAME}:rsvd"
  775.         echo "Creating ${BOXNAME}:rsvd raid0 for new system"
  776.         echo y | mdadm --create ${RSVDDEVRAW} --metadata=1.0 --force --level=raid1 --raid-devices=${#DISKS[@]} --homehost=${BOXNAME} --name=rsvd ${PARTSRSVD}
  777.     fi
  778.    
  779.     # If using detached headers
  780.     if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  781.         truncate -s 2M /root/headers/LUKS-header-${BOXNAME}:rsvd.luksheader
  782.         LUKSHEADER="--align-payload=0 --header /root/headers/LUKS-header-${BOXNAME}:rsvd.luksheader"
  783.     else
  784.         LUKSHEADER=
  785.     fi
  786.  
  787.     echo "Encrypting ${RSVDDEVRAW}"
  788.     echo ${PASSPHRASE} | cryptsetup --batch-mode luksFormat ${LUKSHEADER} -c aes-xts-plain64 -s 512 -h sha512 ${RSVDDEVRAW}
  789.     echo ${PASSPHRASE} | cryptsetup luksOpen ${LUKSHEADER} ${RSVDDEVRAW} ${BOXNAME}:rsvd
  790.     ln -sf /dev/mapper/${BOXNAME}:rsvd /dev
  791.  
  792.     # Get derived key to insert into other encrypted devices
  793.     # More secure - do this into a small ramdisk
  794.     /lib/cryptsetup/scripts/decrypt_derived ${BOXNAME}:rsvd > /tmp/key
  795.     echo "-----------------------------------------------------------------------------"
  796.  
  797.     # Create encrypted swap on top of md raid array
  798.     if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  799.         echo "Encrypting SWAP ${SWAPDEVRAW}"
  800.  
  801.         # If using detached headers
  802.         if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  803.             truncate -s 2M /root/headers/LUKS-header-${BOXNAME}:swap.luksheader
  804.             echo ${PASSPHRASE} | cryptsetup --batch-mode luksFormat -c aes-xts-plain64 -s 512 -h sha512 --align-payload=0 --header /root/headers/LUKS-header-${BOXNAME}:swap.luksheader ${SWAPDEVRAW}
  805.             echo ${PASSPHRASE} | cryptsetup luksOpen --align-payload=0 --header /root/headers/LUKS-header-${BOXNAME}:swap.luksheader ${SWAPDEVRAW} ${BOXNAME}:swap
  806.             echo ${PASSPHRASE} | cryptsetup luksAddKey /root/headers/LUKS-header-${BOXNAME}:swap.luksheader /tmp/key
  807.         else
  808.             # No detached header
  809.             echo ${PASSPHRASE} | cryptsetup --batch-mode luksFormat -c aes-xts-plain64 -s 512 -h sha512 ${SWAPDEVRAW}
  810.             echo ${PASSPHRASE} | cryptsetup luksOpen ${SWAPDEVRAW} ${BOXNAME}:swap
  811.             # Insert derived key
  812.             echo ${PASSPHRASE} | cryptsetup luksAddKey ${SWAPDEVRAW} /tmp/key
  813.         fi
  814.  
  815.         ln -sf /dev/mapper/${BOXNAME}:swap /dev/${BOXNAME}:swap
  816.     fi
  817.  
  818.     # Create encrypted ZFS source partitions
  819.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  820.         echo "Encrypting ZFS partition ${DISKS[${DISK}]}-part${PARTITION_DATA}"
  821.         # If using detached headers
  822.         if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  823.             truncate -s 2M /root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader
  824.             echo ${PASSPHRASE} | cryptsetup --batch-mode luksFormat -c aes-xts-plain64 -s 512 -h sha512 --align-payload=0 --header /root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA}
  825.             echo ${PASSPHRASE} | cryptsetup luksOpen --align-payload=0 --header /root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} root_crypt${DISK}
  826.             # Insert derived key
  827.             echo ${PASSPHRASE} | cryptsetup luksAddKey /root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader /tmp/key
  828.             # Backup LUKS headers for ZFS partitions
  829.             cryptsetup luksHeaderBackup /root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader --header-backup-file /root/headers/LUKS-header-backup-${DISKS[${DISK}]}-part${PARTITION_DATA}.img
  830.         else
  831.             # No detached header
  832.             echo ${PASSPHRASE} | cryptsetup --batch-mode luksFormat -c aes-xts-plain64 -s 512 -h sha512 /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA}
  833.             echo ${PASSPHRASE} | cryptsetup luksOpen /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} root_crypt${DISK}
  834.             # Insert derived key
  835.             echo ${PASSPHRASE} | cryptsetup luksAddKey /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} /tmp/key
  836.             # Backup LUKS headers for ZFS partitions
  837.             cryptsetup luksHeaderBackup /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} --header-backup-file /root/headers/LUKS-header-backup-${DISKS[${DISK}]}-part${PARTITION_DATA}.img
  838.         fi # Detached headers
  839.  
  840.         # Really, REALLY ugly hack to accomodate update-grub
  841.         ln -sf /dev/mapper/root_crypt${DISK} /dev/root_crypt${DISK}
  842.         ln -sf /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_BOOT} /dev
  843.     done
  844. else # not LUKS
  845.     # Really, REALLY ugly hack to accomodate update-grub
  846.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  847.         # Only create non-mapper DATA partition link if *not* using LUKS
  848.         ln -sf /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} /dev
  849.         # Also need the EFI partition
  850.         if [ "ZZ${UEFI}" = "ZZy" ]; then
  851.             ln -sf /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_EFI} /dev
  852.         fi
  853.     done
  854. fi # LUKS
  855.  
  856. # Now create the ZFS pool(s) - only need the boot pool if using LUKS
  857. echo "-----------------------------------------------------------------------------"
  858. if [ "ZZ${LUKS}" = "ZZy" ]; then
  859.     echo "Creating pool $(tput setaf 1)boot$(tput sgr0) ${ZPOOLEVEL}"
  860.     # Looks like grub boots up fine with all features enabled
  861.     # zpool create -f -o ashift=12 -m none \
  862.     #   -d \
  863.     #   -o feature@async_destroy=enabled \
  864.     #   -o feature@empty_bpobj=enabled \
  865.     #   -o feature@lz4_compress=enabled \
  866.     #   -o feature@spacemap_histogram=enabled \
  867.     #   -o feature@enabled_txg=enabled \
  868.     zpool create -f -o ashift=12 -m none \
  869.         -O atime=off -O canmount=off -O compression=lz4 \
  870.         boot ${ZPOOLEVEL} ${PARTSBOOT}
  871.  
  872.     zfs set com.sun:auto-snapshot=false boot
  873.     zpool export boot
  874. fi # LUKS
  875.  
  876. # Create main zpool - named for 1st 10 chars of system name
  877. echo "Creating main pool $(tput setaf 1)${POOLNAME}$(tput sgr0) ${ZPOOLEVEL}"
  878. # Looks like grub boots up fine with all features enabled
  879. # zpool create -f -o ashift=12 \
  880. #   -d \
  881. #   -o feature@async_destroy=enabled \
  882. #   -o feature@empty_bpobj=enabled \
  883. #   -o feature@lz4_compress=enabled \
  884. #   -o feature@spacemap_histogram=enabled \
  885. #   -o feature@enabled_txg=enabled \
  886. zpool create -f -o ashift=12 \
  887.     -O atime=off -O canmount=off -O compression=lz4 \
  888.     ${POOLNAME} ${ZPOOLEVEL} ${ZPOOLDISK}
  889. zfs set mountpoint=/ ${POOLNAME}
  890.  
  891. # Mount ${POOLNAME} under /mnt/zfs to install system, clean /mnt/zfs first
  892. zpool export ${POOLNAME}
  893. rm -rf /mnt/zfs
  894. if [ "ZZ${LUKS}" = "ZZy" ]; then
  895.     zpool import -d /dev/mapper -R /mnt/zfs ${POOLNAME}
  896. else
  897.     zpool import -d /dev/disk/by-id -R /mnt/zfs ${POOLNAME}
  898. fi
  899.  
  900. # No need to auto-snapshot the pool itself, though you have to explicitly set true for datasets
  901. zfs set com.sun:auto-snapshot=false ${POOLNAME}
  902. # Set threshold for zfs-auto-snapshot so if you *do* enable snapshots, there's a sane default
  903. zfs set com.sun:snapshot-threshold=2000000 ${POOLNAME}
  904.  
  905. # Create container for root dataset
  906. zfs create -o canmount=noauto -o mountpoint=/ -o compression=lz4 -o atime=off -o xattr=sa ${POOLNAME}/ROOT
  907.  
  908. # Enable auto snapshots with zfs-auto-snapshot
  909. zfs set com.sun:auto-snapshot=true ${POOLNAME}/ROOT
  910. # Set threshold for zfs-auto-snapshot
  911. zfs set com.sun:snapshot-threshold=2000000 ${POOLNAME}/ROOT
  912.  
  913. # Create root dataset to hold main filesystem
  914. zpool set bootfs=${POOLNAME}/ROOT ${POOLNAME}
  915. zfs mount ${POOLNAME}/ROOT
  916.  
  917. if [ "ZZ${HOMEPOOL}" = "ZZy" ]; then
  918.     # Create container for HOME datasets
  919.     zfs create -o canmount=off -o mountpoint=none -o compression=lz4 -o atime=off ${POOLNAME}/HOME
  920.    
  921.     # Enable auto snapshots with zfs-auto-snapshot
  922.     zfs set com.sun:auto-snapshot=true ${POOLNAME}/HOME
  923.     # Set threshold for zfs-auto-snapshot
  924.     zfs set com.sun:snapshot-threshold=2000000 ${POOLNAME}/HOME
  925.    
  926.     # Create home dataset for main user
  927.     zfs create -o canmount=on -o mountpoint=/home/${USERNAME} -o compression=lz4 -o atime=off -o xattr=sa ${POOLNAME}/HOME/${USERNAME}
  928.     # zfs mount ${POOLNAME}/HOME/${USERNAME}
  929. fi
  930.  
  931. if [ "ZZ${LUKS}" = "ZZy" ]; then
  932.     zpool import -d /dev/disk/by-id -R /mnt/zfs boot
  933.     # Set up /boot filesystem and possibly for EFI
  934.     # Create dataset to hold boot filesystem
  935.     zfs create -o mountpoint=/boot -o compression=zle -o atime=off -o xattr=sa boot/ubuntu
  936.     # Enable auto snapshots with zfs-auto-snapshot
  937.     zfs set com.sun:auto-snapshot=true boot/ubuntu
  938.     # Set threshold for zfs-auto-snapshot
  939.     zfs set com.sun:snapshot-threshold=2000000 boot/ubuntu
  940.  
  941.     # Copy header backups and detached headers
  942.     mkdir -p /mnt/zfs/root/headers
  943.     cp -a /root/headers /mnt/zfs/root/
  944. fi
  945.  
  946. # Create swap in zfs
  947. if [ ${SIZE_ZVOL} != 0 ]; then
  948.     zfs create -V ${SIZE_ZVOL}M -b $(getconf PAGESIZE) \
  949.               -o compression=zle \
  950.               -o primarycache=metadata \
  951.               -o secondarycache=none \
  952.               -o sync=always \
  953.               -o logbias=throughput \
  954.               -o com.sun:auto-snapshot=false ${POOLNAME}/SWAP
  955. fi
  956.  
  957. # Copy Custom script into debootstrap system.  If it has "http" in the name, fetch it, then copy it
  958. # Script is renamed to Setup-Custom.sh in new system
  959. if [ ! -z ${CUSTOMSCRIPT+x} ] ; then
  960.     echo "Installing $(tput setaf 6)Setup-Custom.sh$(tput sgr0) from ${CUSTOMSCRIPT}"
  961.     mkdir -p /mnt/zfs/root
  962.     if [[ "${CUSTOMSCRIPT}" =~ "http" ]]; then
  963.         wget --no-proxy ${CUSTOMSCRIPT} -O /mnt/zfs/root/Setup-Custom.sh
  964.     else
  965.         if [ -e ${CUSTOMSCRIPT} ]; then
  966.             cp ${CUSTOMSCRIPT} /mnt/zfs/root/Setup-Custom.sh
  967.         else
  968.             echo "$(tput setaf 1)**** NOTE: $(tput setaf 3)${CUSTOMSCRIPT}$(tput setaf 1) does not exist !!$(tput sgr0)"
  969.         fi
  970.     fi
  971.     [ -e /mnt/zfs/root/Setup-Custom.sh ] && chmod +x /mnt/zfs/root/Setup-Custom.sh
  972. fi
  973.  
  974. echo "--------------------- $(tput setaf 1)About to debootstrap into /mnt/zfs$(tput sgr0) --------------------"
  975. df -h
  976. echo "--------------------- $(tput setaf 1)About to debootstrap into /mnt/zfs$(tput sgr0) --------------------"
  977. zpool status -v
  978. zfs list -t all
  979. echo "--------------------- $(tput setaf 1)About to debootstrap into /mnt/zfs$(tput sgr0) --------------------"
  980. echo "------- $(tput setaf 1)Please check the above listings to be sure they're right$(tput sgr0) ------------"
  981. echo "------- $(tput setaf 3)Press <enter> About to debootstrap into /mnt/zfs$(tput sgr0) --------------------"
  982. read -t 10 QUIT
  983.  
  984. # Copy existing kernel modules into new system so depmod will work when zfs is installed there
  985. mkdir -p /mnt/zfs/lib/modules
  986. cp -a /lib/modules/* /mnt/zfs/lib/modules
  987.  
  988. # Install core system - need wget to get signing keys in Setup.sh
  989. # See # https://wiki.ubuntu.com/SergeHallyn_localrepo for how to set up a local repository
  990. # Possible cmd : debootstrap --arch amd64 --no-check-gpg --variant=minbase --include=python-minimal,openssh-server,grub-legacy-ec2,libpython2.7-stdlib,sudo,ifupdown,resolvconf,iproute2,rsyslog,acpid,grub2-common,grub-pc-bin,isc-dhcp-client,wget ${SUITE} /mnt/zfs ${DEBOOTSTRAP}
  991. # https://www.byte.nl/blog/dont-run-this-on-any-system-you-expect-to-be-up-they-said-but-we-did-it-anyway
  992. debootstrap --arch=amd64 --no-check-gpg --include=wget ${SUITE} /mnt/zfs ${DEBOOTSTRAP}
  993.  
  994. # ======== Now create Setup.sh script ====================================================
  995. #   Setup.sh    : To use inside chroot - NOTE this runs when we actually chroot into /mnt/zfs
  996.  
  997. # Locale etc just nasty - trying to get it set up front for when we chroot in to run Setup.sh
  998. cat > /mnt/zfs/root/.bash_aliases << EOF
  999. export LC_ALL="en_US.UTF-8"
  1000. export LANG="en_US.UTF-8"
  1001. export LANGUAGE="en_US"
  1002. EOF
  1003.  
  1004. cat > /mnt/zfs/root/Setup.sh << __EOFSETUP__
  1005. #!/bin/bash
  1006. export BOXNAME=${BOXNAME}
  1007. export SYSNAME=${SYSNAME}
  1008. export POOLNAME=${POOLNAME}
  1009. export HOMEPOOL=${HOMEPOOL}
  1010. export LUKS=${LUKS}
  1011. export DETACHEDHEADERS=${DETACHEDHEADERS}
  1012. export PASSPHRASE=${PASSPHRASE}
  1013. export UEFI=${UEFI}
  1014. export EFIDEVRAW=${EFIDEVRAW}
  1015. export PROXY=${PROXY}
  1016. export REMOVE_SYSTEMD=${REMOVE_SYSTEMD}
  1017. export SUITE=${SUITE}
  1018. export BASE_PACKAGES="${BASE_PACKAGES}"
  1019. export DISTRO=${DISTRO}
  1020. export USERNAME=${USERNAME}
  1021. export UCOMMENT="${UCOMMENT}"
  1022. export UPASSWORD=${UPASSWORD}
  1023. export SSHPUBKEY="${SSHPUBKEY}"
  1024. export GITPUBKEYS="${GITPUBKEYS}"
  1025. export SIZE_SWAP=${SIZE_SWAP}
  1026. export SIZE_ZVOL=${SIZE_ZVOL}
  1027. export SWAPRESUME=${SWAPRESUME}
  1028. export SWAPDEVRAW=${SWAPDEVRAW}
  1029. export USE_ZSWAP=${USE_ZSWAP}
  1030. export RTL8168_VERSION=${RTL8168_VERSION}
  1031. export RSVDDEVRAW=${RSVDDEVRAW}
  1032. export CUSTOMSCRIPT=${CUSTOMSCRIPT}
  1033. export PARTITION_EFI=${PARTITION_EFI}
  1034. export PARTITION_GRUB=${PARTITION_GRUB}
  1035. export PARTITION_BOOT=${PARTITION_BOOT}
  1036. export PARTITION_SWAP=${PARTITION_SWAP}
  1037. export PARTITION_DATA=${PARTITION_DATA}
  1038. export PARTITION_RSVD=${PARTITION_RSVD}
  1039. export HOST_ECDSA_KEY_PUB="${HOST_ECDSA_KEY_PUB}"
  1040. export HOST_RSA_KEY_PUB="${HOST_RSA_KEY_PUB}"
  1041. __EOFSETUP__
  1042. # Ugly hack to get multiline variable into Setup.sh
  1043. # Note using single quotes like this  HOST_RSA_KEY='blahblah' surrounded by double quotes
  1044. echo -n "HOST_ECDSA_KEY='" >> /mnt/zfs/root/Setup.sh
  1045. echo "${HOST_ECDSA_KEY}'" >> /mnt/zfs/root/Setup.sh
  1046. echo -n "HOST_RSA_KEY='" >> /mnt/zfs/root/Setup.sh
  1047. echo "${HOST_RSA_KEY}'" >> /mnt/zfs/root/Setup.sh
  1048.  
  1049. for DISK in $(seq 1 ${#DISKS[@]}) ; do
  1050.     echo "DISKS[${DISK}]=${DISKS[${DISK}]}" >> /mnt/zfs/root/Setup.sh
  1051. done
  1052.  
  1053. # Note use of ' for this section to avoid replacing $variables - did not use ' above
  1054. cat >> /mnt/zfs/root/Setup.sh << '__EOFSETUP__'
  1055.  
  1056. # Testing functionality of removing systemd completely
  1057. # https://askubuntu.com/questions/779640/how-to-remove-systemd-from-ubuntu-16-04-and-prevent-its-usage
  1058. Remove_systemd() {
  1059.     apt-get install -y upstart-sysv sysvinit-utils
  1060.  
  1061.     # Set up preferences to pin systemd AWAY
  1062.     apt-get remove --purge --auto-remove -y --allow-remove-essential systemd
  1063.     echo -e 'Package: systemd\nPin: release *\nPin-Priority: -1' > /etc/apt/preferences.d/systemd
  1064.     echo -e '\n\nPackage: *systemd*\nPin: release *\nPin-Priority: -1' >> /etc/apt/preferences.d/systemd
  1065.     echo -e '\nPackage: systemd:amd64\nPin: release *\nPin-Priority: -1' >> /etc/apt/preferences.d/systemd
  1066.     echo -e '\nPackage: systemd:i386\nPin: release *\nPin-Priority: -1' >> /etc/apt/preferences.d/systemd
  1067. }
  1068.  
  1069. # Stuff to do after a basic debootstrap
  1070. set -x
  1071. # Log everything we do
  1072. exec > >(tee -a /root/Setup.log) 2>&1
  1073.  
  1074. # Proxy
  1075. if [ ${PROXY} ]; then
  1076.     # This is for apt-get
  1077.     echo "Acquire::http::proxy \"${PROXY}\";" > /etc/apt/apt.conf.d/03proxy
  1078. fi
  1079.  
  1080. # Disable predicatable network interface names - see :
  1081. #   https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
  1082. #   https://askubuntu.com/questions/628217/use-of-predictable-network-interface-names-with-alternate-kernels
  1083. # Also setting net.ifnames=0 in /etc/default/grub further down
  1084. ln -s /dev/null /etc/udev/rules.d/80-net-setup-link.rules
  1085.  
  1086. # Basic network interfaces
  1087. cat >> /etc/network/interfaces << __EOF__
  1088. # The loopback network interface
  1089. auto lo
  1090. iface lo inet loopback
  1091.  
  1092. # The primary network interface
  1093. auto eth0
  1094. iface eth0 inet dhcp
  1095. __EOF__
  1096.  
  1097. # Nice clean sources.list, if on Amazon AWS grab local region archive address
  1098. # plymouth makes no sense for AWS, never see the console. PLYMOUTH variable
  1099. # is used for apt install below.  AWS implies it's a VPS ...
  1100. mv /etc/apt/sources.list /etc/apt/sources.list.orig
  1101. EC2=$(fgrep ec2 /etc/apt/sources.list.orig | fgrep ${SUITE} | head -1 | sed 's/^.*\/\///; s/ ${SUITE}.*//')
  1102. if [ "ZZ${EC2}" = "ZZ" ]; then
  1103.     # Not Amazon AWS, so need a source
  1104.     EC2=archive.ubuntu.com/ubuntu
  1105.     if [ ${SUITE} = trusty ]; then
  1106.         PLYMOUTH="plymouth-theme-solar"
  1107.     else
  1108.         PLYMOUTH="plymouth-theme-ubuntu-logo plymouth-label plymouth-themes"
  1109.     fi
  1110. else
  1111.     # Amazon AWS, so EC2 is already pointing at right local source
  1112.     PLYMOUTH=
  1113.     VPS=true
  1114. fi
  1115. cat > /etc/apt/sources.list << EOF
  1116. deb http://${EC2} ${SUITE} main restricted universe multiverse
  1117. deb http://${EC2} ${SUITE}-updates main restricted universe multiverse
  1118. deb http://${EC2} ${SUITE}-backports main restricted universe multiverse
  1119. deb http://archive.canonical.com/ubuntu ${SUITE} partner
  1120. deb http://security.ubuntu.com/ubuntu ${SUITE}-security main restricted universe multiverse
  1121. EOF
  1122. if [ ${SUITE} = trusty ]; then
  1123.     echo "deb http://extras.ubuntu.com/ubuntu ${SUITE} main" >> /etc/apt/sources.list
  1124. fi
  1125.  
  1126. # Set up for periodic apt updates
  1127. cat > /etc/apt/apt.conf.d/02periodic << EOFAPT1
  1128. // This enables periodic upgrades of packages - see /etc/cron.daily/apt for details
  1129. // NOTE: These default Ubuntu settings are in /etc/apt/apt.conf.d/20auto-upgrades
  1130. // APT::Periodic::Unattended-Upgrade "1";
  1131.  
  1132. APT::Periodic::Update-Package-Lists "1";
  1133. APT::Periodic::Enable "1";
  1134. APT::Periodic::Download-Upgradeable-Packages "1";
  1135. APT::Periodic::AutocleanInterval "7";
  1136. EOFAPT1
  1137.  
  1138. # Prevent apt-get from asking silly questions
  1139. export DEBIAN_FRONTEND=noninteractive
  1140.  
  1141. # apt-key adv fails within a debootstrap, so try wget
  1142. # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3E5C1192
  1143. # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CA8DA16B
  1144. # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 437D05B5
  1145. # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C0B21F32
  1146. wget --no-proxy "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x3E5C1192" -O- | apt-key add - > /dev/null 2>&1
  1147. wget --no-proxy "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0xCA8DA16B" -O- | apt-key add - > /dev/null 2>&1
  1148. wget --no-proxy "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x437D05B5" -O- | apt-key add - > /dev/null 2>&1
  1149. # apt-fast PPA key
  1150. wget --no-proxy "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0xC0B21F32" -O- | apt-key add - > /dev/null 2>&1
  1151. # Ansible
  1152. wget --no-proxy "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x7BB9C367" -O- | apt-key add - > /dev/null 2>&1
  1153.  
  1154. # Ugly hack to prevent launching of services while setting up system with apt-get
  1155. ##### NOTE : Putting update-initramfs here to prevent it from running a bazillion times during the install
  1156. #####          : Will remove it and run update-initramfs manually at the end
  1157. mkdir -p /tmp/fakestart
  1158. ln -s /bin/true /tmp/fakestart/initctl
  1159. ln -s /bin/true /tmp/fakestart/invoke-rc.d
  1160. ln -s /bin/true /tmp/fakestart/restart
  1161. ln -s /bin/true /tmp/fakestart/start
  1162. ln -s /bin/true /tmp/fakestart/stop
  1163. ln -s /bin/true /tmp/fakestart/start-stop-daemon
  1164. ln -s /bin/true /tmp/fakestart/service
  1165. ln -s /bin/true /tmp/fakestart/update-initramfs
  1166. export PATH=/tmp/fakestart:$PATH
  1167.  
  1168. export LC_ALL="en_US.UTF-8"
  1169. export LANG="en_US.UTF-8"
  1170. export LANGUAGE="en_US"
  1171.  
  1172. # Set up locale - must set langlocale variable (defaults to en_US)
  1173. cat > /tmp/selections << EOFLOCALE
  1174. # tzdata
  1175. tzdata  tzdata/Zones/US                         select Eastern
  1176. tzdata  tzdata/Zones/America                    select New_York
  1177. tzdata  tzdata/Areas                            select US
  1178. # localepurge will not take any action
  1179. localepurge     localepurge/remove_no           note
  1180. # Inform about new locales?
  1181. localepurge     localepurge/dontbothernew       boolean false
  1182. localepurge     localepurge/showfreedspace      boolean true
  1183. # Really remove all locales?
  1184. localepurge     localepurge/none_selected       boolean false
  1185. # Default locale for the system environment:
  1186. locales locales/default_environment_locale      select en_US.UTF-8
  1187. localepurge     localepurge/verbose             boolean false
  1188. # Selecting locale files
  1189. localepurge     localepurge/nopurge             multiselect en, en_US.UTF-8
  1190. localepurge     localepurge/use-dpkg-feature    boolean true
  1191. locales locales/locales_to_be_generated         multiselect en_US.UTF-8 UTF-8
  1192. localepurge     localepurge/quickndirtycalc     boolean true
  1193. localepurge     localepurge/mandelete           boolean true
  1194. # Do not configure grub during package install
  1195. grub-pc         grub-pc/install_devices_empty   select true
  1196. grub-pc         grub-pc/install_devices         select
  1197. EOFLOCALE
  1198.  
  1199. # if ! [ -e /etc/default/locale ]; then
  1200.     cat > /etc/default/locale << EOF
  1201. LC_ALL=en_US.UTF-8
  1202. LANG=en_US.UTF-8
  1203. LANGUAGE=en_US:en
  1204. EOF
  1205. # fi
  1206. cat /etc/default/locale >> /etc/environment
  1207.  
  1208. cat /tmp/selections | debconf-set-selections
  1209. echo "--- apt-get update"
  1210. apt-get -qq update > /dev/null
  1211. apt-get -qq -y install localepurge locales language-pack-en-base
  1212. locale-gen --purge "en_US.UTF-8"
  1213. # dpkg-reconfigure -f noninteractive locales
  1214.  
  1215. # This is a workaround for https://bugs.launchpad.net/ubuntu/+source/tzdata/+bug/1554806
  1216. echo "America/New_York" > /etc/timezone
  1217. ln -fs /usr/share/zoneinfo/US/Eastern /etc/localtime
  1218. dpkg-reconfigure -f noninteractive tzdata
  1219.  
  1220. echo "${SYSNAME}" > /etc/hostname
  1221. echo "127.0.1.1 ${SYSNAME}.local    ${SYSNAME}" >> /etc/hosts
  1222.  
  1223. # Remove systemd if requested
  1224. if [ ! -z ${REMOVE_SYSTEMD} ]; then
  1225.     Remove_systemd
  1226. fi
  1227.  
  1228. apt-get -qq -y install ubuntu-minimal software-properties-common
  1229.  
  1230. if [ ${SUITE} = trusty ]; then
  1231.     apt-add-repository --yes ppa:zfs-native/stable
  1232. fi
  1233.  
  1234. # If we're installing ElementaryOS or Linux Mint 18.1, set up the additional PPAs
  1235. # Regular Ubuntu uses ubuntu-standard - change below for ElementaryOS or Linux Mint
  1236. STANDARD="ubuntu-standard"
  1237.  
  1238. # NOTE: DISTRO might not be set, so have to compare with ZZ
  1239. if [ "${DISTRO}ZZ" == "lokiZZ" ]; then
  1240.     add-apt-repository --yes ppa:elementary-os/stable
  1241.     add-apt-repository --yes ppa:elementary-os/os-patches
  1242.     # Use elementary-standard rather than ubuntu-standard for ElementaryOS
  1243.     STANDARD="elementary-standard"
  1244.     cat > /etc/apt/preferences.d/elementary-os-patches.pref << EOF
  1245. # Explanation: OS patches for elementary OS.
  1246. # Explanation: We need this pin because our patched build can lag a few hours behind Ubuntu's updates,
  1247. # Explanation: and during those few hours packages can be overwritten with unpatched ones.
  1248. Package: *
  1249. Pin: release o=LP-PPA-elementary-os-os-patches
  1250. Pin-Priority: 999
  1251. EOF
  1252. fi # Elementary
  1253.  
  1254. if [ "${DISTRO}ZZ" == "serenaZZ" ]; then
  1255.     # Cinnamon uses the stock ubuntu-standard
  1256.  
  1257.     # Mint PPA key 451BBBF2 or sub is A5D54F76
  1258.     # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 451BBBF2
  1259.     wget --no-proxy "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x451BBBF2" -O- | apt-key add - > /dev/null 2>&1
  1260.  
  1261.     cat > /etc/apt/preferences.d/cinnamon-extra.pref << EOF
  1262. Package: *
  1263. Pin: origin build.linuxmint.com
  1264. Pin-Priority: 700
  1265. EOF
  1266.  
  1267.     cat > /etc/apt/preferences.d/cinnamon-packages.pref << EOF
  1268. Package: *
  1269. Pin: origin live.linuxmint.com
  1270. Pin-Priority: 750
  1271.  
  1272. Package: *
  1273. Pin: release o=linuxmint,c=upstream
  1274. Pin-Priority: 700
  1275.  
  1276. Package: *
  1277. Pin: release o=Ubuntu
  1278. Pin-Priority: 500
  1279. EOF
  1280.  
  1281.     cat > /etc/apt/sources.list.d/linux-mint-serena.list<< EOF
  1282. deb http://packages.linuxmint.com serena main upstream import backport #id:linuxmint_main
  1283. EOF
  1284. fi # Cinnamon
  1285.  
  1286. # Installing ansible
  1287. add-apt-repository --yes ppa:ansible/ansible
  1288.  
  1289. echo "--- apt-get update"
  1290. apt-get -qq update > /dev/null
  1291.  
  1292. # Force overwrite of config files - needed when installed from 16.04 live disc
  1293. # https://askubuntu.com/questions/56761/force-apt-get-to-overwrite-file-installed-by-another-package
  1294. # https://askubuntu.com/questions/104899/make-apt-get-or-aptitude-run-with-y-but-not-prompt-for-replacement-of-configu
  1295.  
  1296. # STANDARD is set above, choosing between ElementaryOS and Ubuntu version of the -standard package
  1297. # Regular ubuntu-standard is these packages :
  1298. # Depends: busybox-static, cpio, cron, dmidecode, dnsutils, dosfstools, ed, file, ftp, hdparm, info, iptables, language-selector-common, libpam-systemd, logrotate, lshw, lsof, ltrace, man-db, mime-support, parted, pciutils, popularity-contest, psmisc, rsync, strace, systemd-sysv, time, usbutils, wget
  1299.  
  1300. apt-get -qq -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -o Dpkg::Options::="--force-overwrite" -y --no-install-recommends install ${BASE_PACKAGES} ${PLYMOUTH} ${STANDARD}
  1301.  
  1302. # Check for Realtek 8168/8169 ethernet - if there, then install latest driver from Realtek
  1303. # http://12244.wpc.azureedge.net/8012244/drivers/rtdrivers/cn/nic/0009-r8168-8.044.02.tar.bz2
  1304. apt-get -qq --no-install-recommends -y install pciutils
  1305. RTL8168=$(lspci | fgrep 8168)
  1306. if [ "${RTL8168}" != "" ] ; then
  1307.     apt-get -qq --no-install-recommends -y install dkms
  1308.     mkdir /usr/src/r8168-${RTL8168_VERSION}
  1309.     wget http://12244.wpc.azureedge.net/8012244/drivers/rtdrivers/cn/nic/0009-r8168-${RTL8168_VERSION}.tar.bz2 -O /tmp/r8168.tar.bz2
  1310.     cd /tmp
  1311.     tar xvjf /tmp/r8168.tar.bz2
  1312.     mv /tmp/r8168-${RTL8168_VERSION}/src/* /usr/src/r8168-${RTL8168_VERSION}
  1313.     cat > /usr/src/r8168-${RTL8168_VERSION}/dkms.conf << EOF
  1314. PACKAGE_NAME="r8168"
  1315. PACKAGE_VERSION="${RTL8168_VERSION}"
  1316. BUILT_MODULE_NAME[0]="\$PACKAGE_NAME"
  1317. DEST_MODULE_LOCATION[0]="/updates/dkms"
  1318. AUTOINSTALL="YES"
  1319. REMAKE_INITRD="YES"
  1320. EOF
  1321.  
  1322.     cat > /etc/modprobe.d/r8168-dkms.conf << EOF
  1323. # settings for r8168-dkms
  1324.  
  1325. # map the specific PCI IDs instead of blacklisting the whole r8169 module
  1326. alias   pci:v00001186d00004300sv00001186sd00004B10bc*sc*i*      r8168
  1327. alias   pci:v000010ECd00008168sv*sd*bc*sc*i*                    r8168
  1328.  
  1329. # if the aliases above do not work, uncomment the following line
  1330. # to blacklist the whole r8169 module
  1331. #blacklist r8169
  1332. EOF
  1333.  
  1334.     cat > /usr/share/initramfs-tools/hooks/r8168-dkms << "EOF"
  1335. #!/bin/sh
  1336. set -e
  1337.  
  1338. case $1 in
  1339. prereqs)
  1340.         echo ""
  1341.         exit 0
  1342.         ;;
  1343. esac
  1344.  
  1345. . /usr/share/initramfs-tools/hook-functions
  1346.  
  1347. manual_add_modules r8168
  1348. EOF
  1349.     chmod 755 /usr/share/initramfs-tools/hooks/r8168-dkms
  1350.  
  1351.     # Now actually build the thing
  1352.     /usr/lib/dkms/common.postinst r8168 ${RTL8168_VERSION}
  1353. fi # if r8168
  1354.  
  1355. # Set host ssh keys if defined
  1356. # Test if variable set - https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash
  1357. # DOESN'T work if variable is set to null, as in HOST=  that creates the variable, so +x test fails
  1358. # if [ ! -z ${HOST_RSA_KEY+x} ] ; then
  1359. if [ "${HOST_RSA_KEY}ZZ" != "ZZ" ] ; then
  1360.     echo "${HOST_RSA_KEY}" > /etc/ssh/ssh_host_rsa_key
  1361.     echo "${HOST_RSA_KEY_PUB}" > /etc/ssh/ssh_host_rsa_key.pub
  1362.     chmod 600 /etc/ssh/ssh_host_rsa_key
  1363.     chmod 644 /etc/ssh/ssh_host_rsa_key.pub
  1364. fi
  1365. if [ "${HOST_ECDSA_KEY}ZZ" != "ZZ" ] ; then
  1366.     echo "${HOST_ECDSA_KEY}" > /etc/ssh/ssh_host_ecdsa_key
  1367.     echo "${HOST_ECDSA_KEY_PUB}" > /etc/ssh/ssh_host_ecdsa_key.pub
  1368.     chmod 600 /etc/ssh/ssh_host_ecdsa_key
  1369.     chmod 644 /etc/ssh/ssh_host_ecdsa_key.pub
  1370. fi
  1371.  
  1372. # Only need mdadm installed if our pool is more than 1 disk
  1373. if [ ${#DISKS[@]} -gt 1 ]; then
  1374.     apt-get -qq -y --no-install-recommends install mdadm
  1375.     # Set up mdadm - clear out any previous array definitions
  1376.     cat /etc/mdadm/mdadm.conf | fgrep -v ARRAY > /tmp/ttt
  1377.     mv /tmp/ttt /etc/mdadm/mdadm.conf
  1378.     mdadm --detail --scan >> /etc/mdadm/mdadm.conf
  1379. fi
  1380.  
  1381. # spl package (from ubuntu-zfs) provides /etc/hostid
  1382. rm -f /etc/hostid
  1383. if [ ${SUITE} = trusty ]; then
  1384.         apt-get -qq -y --no-install-recommends install ubuntu-zfs ubuntu-extras-keyring
  1385. fi
  1386. if [ ${SUITE} = xenial ]; then
  1387.         apt-get -qq -y --no-install-recommends install zfsutils-linux spl zfs-zed
  1388.         depmod -a
  1389.         modprobe zfs
  1390. fi
  1391. apt-get -qq -y install zfs-initramfs
  1392.  
  1393. # Allow read-only zfs commands with no sudo password
  1394. cat /etc/sudoers.d/zfs | sed -e 's/#//' > /etc/sudoers.d/zfsALLOW
  1395.  
  1396. # Create swap
  1397. if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  1398.     if [ "ZZ${LUKS}" = "ZZy" ]; then
  1399.         echo "Create encrypted SWAP ${BOXNAME}_swap on top of ${BOXNAME}:swap"
  1400.         mkswap -L "${BOXNAME}_swap" /dev/mapper/${BOXNAME}:swap
  1401.         [ ${SWAPRESUME} = y ] && echo "RESUME=/dev/mapper/${BOXNAME}:swap" > /etc/initramfs-tools/conf.d/resume
  1402.     else
  1403.         mkswap -L "${BOXNAME}_swap" ${SWAPDEVRAW}
  1404.         [ ${SWAPRESUME} = y ] && echo "RESUME=${SWAPDEVRAW}" > /etc/initramfs-tools/conf.d/resume
  1405.     fi
  1406. fi
  1407. if [ ${SIZE_ZVOL} != 0 ]; then
  1408.     mkswap -L "${BOXNAME}_zwap"  /dev/zvol/${POOLNAME}/SWAP
  1409. fi
  1410.  
  1411. # If using LUKS set up crypttab etc
  1412. if [ "ZZ${LUKS}" = "ZZy" ]; then
  1413.     apt-get -qq -y install cryptsetup
  1414.     if [ "`cat /proc/cpuinfo | fgrep aes`" != "" ] ; then
  1415.         echo "aesni-intel" >> /etc/modules
  1416.         echo "aesni-intel" >> /etc/initramfs-tools/modules
  1417.     fi
  1418.     echo "aes-x86_64" >> /etc/modules
  1419.     echo "aes-x86_64" >> /etc/initramfs-tools/modules
  1420.  
  1421.     # Was using dedicated per-luks-device lines for 99-local-crypt.rules
  1422.     # But https://github.com/zfsonlinux/zfs/wiki/Ubuntu-16.04-Root-on-ZFS shows a generic way, which I think is better
  1423.     #if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  1424.     #   echo "ENV{DM_NAME}==\"${BOXNAME}:swap\", SYMLINK+=\"${BOXNAME}:swap\"" > /etc/udev/rules.d/99-local-crypt.rules
  1425.     #fi
  1426.     #echo "ENV{DM_NAME}==\"${BOXNAME}:rsvd\", SYMLINK+=\"${BOXNAME}:rsvd\"" >> /etc/udev/rules.d/99-local-crypt.rules
  1427.     #for DISK in `seq 1 ${#DISKS[@]}` ; do
  1428.     #   echo "ENV{DM_NAME}==\"root_crypt${DISK}\", SYMLINK+=\"root_crypt${DISK}\"" >> /etc/udev/rules.d/99-local-crypt.rules
  1429.     #done
  1430.     cat > /etc/udev/rules.d/99-local-crypt.rules << 'EOF'
  1431. # Was using dedicated per-luks-device lines for 99-local-crypt.rules
  1432. # But https://github.com/zfsonlinux/zfs/wiki/Ubuntu-16.04-Root-on-ZFS shows a generic way, which I think is better
  1433. #
  1434. # Old way
  1435. #   echo "ENV{DM_NAME}==\"${BOXNAME}:swap\", SYMLINK+=\"${BOXNAME}:swap\"" > /etc/udev/rules.d/99-local-crypt.rules
  1436.  
  1437. ENV{DM_NAME}!="", SYMLINK+="$env{DM_NAME}"
  1438. ENV{DM_NAME}!="", SYMLINK+="dm-name-$env{DM_NAME}"
  1439. EOF
  1440.  
  1441.     # Make decrypt_derived only use the encrypted :rsvd system for pulling the derived key
  1442.     mkdir /etc/initramfs-tools/scripts/luks
  1443.     cp /lib/cryptsetup/scripts/decrypt_derived /etc/initramfs-tools/scripts/luks/get.root_crypt.decrypt_derived
  1444.     cp /lib/cryptsetup/scripts/decrypt_derived /etc/initramfs-tools/scripts/luks/decrypt_derived
  1445.     sed -i "
  1446.     { 2 a\
  1447.         CRYPT_DEVICE=${BOXNAME}:rsvd \\
  1448.     }
  1449.     { s/\$1/\${CRYPT_DEVICE}/g }
  1450.     " /etc/initramfs-tools/scripts/luks/get.root_crypt.decrypt_derived
  1451.  
  1452.     # Force inclusion of cryptsetup
  1453.     echo "export CRYPTSETUP=y" > /usr/share/initramfs-tools/conf-hooks.d/forcecryptsetup
  1454.  
  1455.     # Reduce cryptroot timeout from 180s to 30s and remove dropping to shell if missing device
  1456.     # Also ignore fstype check for ${BOXNAME}:rsvd - ZFS safety partition 9
  1457.     # That is used as the source key for unlocking all the other luks devices
  1458.     # Include system IP address on boot unlock screen
  1459.     sed -i "
  1460.        s/slumber=180/slumber=30/g
  1461.        s/panic/break # panic/
  1462.        /cryptsetup: unknown fstype, bad password or options/ {
  1463.        i \
  1464.            if [[ ! \"\$crypttarget\" =~ \":rsvd\" ]] ; then
  1465.  
  1466.        N ; N ; N ; a\
  1467.            fi  # check for ZFS
  1468.        }
  1469.         s/Please unlock disk/For \$eth0IP Please unlock disk/
  1470.         /PREREQ=/ {
  1471.         a \
  1472. # Need to pause here to let network come up\n\
  1473. sleep 7\n\
  1474. eth0IP=\$(ifconfig eth0 | sed -n '/inet addr/s/.*inet addr: *\([^[:space:]]\+\).*/\1/p')
  1475.        
  1476.         }
  1477.     " /usr/share/initramfs-tools/scripts/local-top/cryptroot
  1478.    
  1479.     # Help update-initramfs to find all encrypted disks for root - remove "return" from get_root_device()
  1480.     sed -i '/echo "$device"/ { N ; s!echo "$device"\n\(.*\)return!echo "$device"\n\1# https://newspaint.wordpress.com/2015/03/22/installing-xubuntu-14-04-trusty-on-zfs-with-luks-encryption/\n\1# return! } ' /usr/share/initramfs-tools/hooks/cryptroot
  1481.  
  1482. #-------------------------------------------------------------------------------------------------------------------
  1483.     cat > /etc/initramfs-tools/hooks/clean_cryptroot << '__EOF__'
  1484. #!/bin/sh
  1485.  
  1486. # Create /etc/crypttab
  1487. # Trying to use main decrypt_derived script, but /usr/share/initramfs-tools/hooks/cryptroot
  1488. # seems to be duplicating the :rsvd entry from /etc/crypttab. Every time :rsvd is used as a
  1489. # key, it gets added to the list of devices to be put into /etc/initramfs-tools/conf.d/cryptroot
  1490. # So ugly workaround - script to remove dupes from cryptroot
  1491.    
  1492. PREREQ="cryptroot"
  1493.  
  1494. prereqs() {
  1495.         echo "$PREREQ"
  1496. }
  1497.  
  1498. case $1 in
  1499. # get pre-requisites
  1500. prereqs)
  1501.         prereqs
  1502.         exit 0
  1503.         ;;
  1504. esac
  1505.  
  1506. . /usr/share/initramfs-tools/hook-functions
  1507.  
  1508. # Need to make sure that :rsvd is at the top since that has to be unlocked first.
  1509. # Then it uses the derived_key from that to unlock the rest of the devices
  1510. cat ${DESTDIR}/conf/conf.d/cryptroot | fgrep ":rsvd,source" | uniq > ${DESTDIR}/conf/conf.d/cryptroot.sorted
  1511. cat ${DESTDIR}/conf/conf.d/cryptroot | fgrep ":rsvd,keyscript" >> ${DESTDIR}/conf/conf.d/cryptroot.sorted
  1512. mv ${DESTDIR}/conf/conf.d/cryptroot.sorted ${DESTDIR}/conf/conf.d/cryptroot
  1513. __EOF__
  1514.     chmod +x /etc/initramfs-tools/hooks/clean_cryptroot
  1515.  
  1516. #-------------------------------------------------------------------------------------------------------------------
  1517.     # Need to copy detached headers when creating initramfs - NOTE: Detached headers not quite working yet
  1518.     if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  1519.         cat > /etc/initramfs-tools/hooks/copy_cryptheaders << '__EOF__'
  1520. #!/bin/sh
  1521.  
  1522. PREREQ="cryptroot"
  1523.  
  1524. prereqs() {
  1525.         echo "$PREREQ"
  1526. }
  1527.  
  1528. case $1 in
  1529. # get pre-requisites
  1530. prereqs)
  1531.         prereqs
  1532.         exit 0
  1533.         ;;
  1534. esac
  1535.  
  1536. . /usr/share/initramfs-tools/hook-functions
  1537.  
  1538. if [ ! -d "$DESTDIR/headers" ]; then
  1539.         mkdir -p "$DESTDIR/headers"
  1540. fi
  1541.  
  1542. for header in  "/root/headers/*" ; do
  1543.         copy_exec ${header} headers
  1544. done
  1545. __EOF__
  1546.         chmod +x /etc/initramfs-tools/hooks/copy_cryptheaders
  1547.  
  1548.         ######## Detached headers
  1549.         # RSVD - LUKS-header-${BOXNAME}:rsvd.luksheader
  1550.         # SWAP - LUKS-header-${BOXNAME}:swap.luksheader
  1551.         # ROOT - LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader
  1552.  
  1553.         echo "${BOXNAME}:rsvd   UUID=$(blkid ${RSVDDEVRAW} -s UUID -o value)    none    luks,header=/root/headers/LUKS-header-${BOXNAME}:rsvd.luksheader" >> /etc/crypttab
  1554.         if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  1555.             echo "${BOXNAME}:swap   UUID=$(blkid ${SWAPDEVRAW} -s UUID -o value)    ${BOXNAME}:rsvd luks,noauto,keyscript=/etc/initramfs-tools/scripts/luks/decrypt_derived,header=/root/headers/LUKS-header-${BOXNAME}:swap.luksheader" >> /etc/crypttab
  1556.         fi
  1557.         for DISK in `seq 1 ${#DISKS[@]}` ; do
  1558.             echo "root_crypt${DISK} UUID=$(blkid /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} -s UUID -o value)  ${BOXNAME}:rsvd luks,noauto,keyscript=/etc/initramfs-tools/scripts/luks/decrypt_derived,header=/root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader" >> /etc/crypttab
  1559.         done
  1560.     else
  1561.         echo "${BOXNAME}:rsvd   UUID=$(blkid ${RSVDDEVRAW} -s UUID -o value)    none    luks" >> /etc/crypttab
  1562.         if [ ${SIZE_SWAP} ] &&[ ${SIZE_SWAP} != 0 ]; then
  1563.             # echo "${BOXNAME}:swap UUID=$(blkid ${SWAPDEVRAW} -s UUID -o value)    none    luks,noauto,keyscript=/etc/initramfs-tools/scripts/luks/get.root_crypt.decrypt_derived" >> /etc/crypttab
  1564.             echo "${BOXNAME}:swap   UUID=$(blkid ${SWAPDEVRAW} -s UUID -o value)    ${BOXNAME}:rsvd luks,noauto,keyscript=/etc/initramfs-tools/scripts/luks/decrypt_derived" >> /etc/crypttab
  1565.         fi
  1566.         for DISK in `seq 1 ${#DISKS[@]}` ; do
  1567.             # echo "root_crypt${DISK}   UUID=$(blkid /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} -s UUID -o value)  none    luks,noauto,keyscript=/etc/initramfs-tools/scripts/luks/get.root_crypt.decrypt_derived" >> /etc/crypttab
  1568.             echo "root_crypt${DISK} UUID=$(blkid /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} -s UUID -o value)  ${BOXNAME}:rsvd luks,noauto,keyscript=/etc/initramfs-tools/scripts/luks/decrypt_derived" >> /etc/crypttab
  1569.         done
  1570.     fi # detached headers
  1571.  
  1572. #-------------------------------------------------------------------------------------------------------------------
  1573.    
  1574. #############################################
  1575. ## Testing using main ubuntu scripts, so don't create initramfs cryptroot
  1576. ## Leaving this here just in case we need to use it at some point
  1577. cat > /dev/null << '__EOF__'
  1578.     # Create initramfs cryptroot
  1579.     echo "target=${BOXNAME}:rsvd,source=UUID=$(blkid ${RSVDDEVRAW} -s UUID -o value),key=none" > /etc/initramfs-tools/conf.d/cryptroot
  1580.  
  1581.     if [ ${SIZE_SWAP} ] &&[ ${SIZE_SWAP} != 0 ]; then
  1582.         echo "" >> /etc/initramfs-tools/conf.d/cryptroot
  1583.         echo "### target=${BOXNAME}:swap,source=UUID=$(blkid ${SWAPDEVRAW} -s UUID -o value),key=none,discard,keyscript=/scripts/luks/get.root_crypt.decrypt_derived" >> /etc/initramfs-tools/conf.d/cryptroot
  1584.     fi
  1585.  
  1586.     echo "" >> /etc/initramfs-tools/conf.d/cryptroot
  1587.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  1588.         echo "### target=root_crypt${DISK},source=UUID=$(blkid /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} -s UUID -o value),rootdev,keyscript=/scripts/luks/get.root_crypt.decrypt_derived" >> /etc/initramfs-tools/conf.d/cryptroot
  1589.     done
  1590. __EOF__
  1591. #############################################
  1592.    
  1593.     # make sure that openssh-server is installed before installing dropbear
  1594.     apt-get -qq -y install openssh-server
  1595.     apt-get -qq -y install dropbear
  1596.  
  1597. #-------------------------------------------------------------------------------------------------------------------
  1598. ##### Force dropbear to use dhcp - can also set up real IP
  1599.     cat > /etc/initramfs-tools/conf.d/dropbear_network << '__EOFF__'
  1600. # dropbear doesn't use IP=dhcp anymore - it just defaults to dhcp
  1601. # export IP=dhcp
  1602. DROPBEAR=y
  1603. CRYPTSETUP=y
  1604. __EOFF__
  1605.  
  1606. ##### Not using busybox, using klibc
  1607. ## sed -i 's/^BUSYBOX=.*/BUSYBOX=n/' /etc/initramfs-tools/initramfs.conf
  1608.  
  1609. #-------------------------------------------------------------------------------------------------------------------
  1610. ##### Need the full version of busybox if we use it
  1611.     cat > /etc/initramfs-tools/hooks/busybox2 << '__EOFF__'
  1612. #!/bin/sh
  1613. ##### Need the full version of busybox if we use it
  1614.  
  1615. PREREQ=""
  1616.  
  1617. prereqs() {
  1618.         echo "$PREREQ"
  1619. }
  1620.  
  1621. case $1 in
  1622. # get pre-requisites
  1623. prereqs)
  1624.         prereqs
  1625.         exit 0
  1626.         ;;
  1627. esac
  1628.  
  1629. # busybox
  1630. if [ "${BUSYBOX}" != "n" ] && [ -e /bin/busybox ]; then
  1631.     . /usr/share/initramfs-tools/hook-functions
  1632.     rm -f ${DESTDIR}/bin/busybox
  1633.     copy_exec /bin/busybox /bin
  1634.     copy_exec /usr/bin/xargs /bin
  1635. fi
  1636. __EOFF__
  1637.     chmod +x /etc/initramfs-tools/hooks/busybox2
  1638.  
  1639. #-------------------------------------------------------------------------------------------------------------------
  1640. ##### Create script to start md arrays no matter what, but only this if the
  1641. ##### pool has more than 1 disk, which means mdadm would be used
  1642.     if [ ${#DISKS[@]} -gt 1 ]; then
  1643.         cat > /etc/initramfs-tools/scripts/init-premount/zzmdraidforce <<'__EOF__'
  1644. #!/bin/sh
  1645.  
  1646. # start md arrays no matter what
  1647.  
  1648. PREREQ=""
  1649. prereqs() {
  1650.         echo "$PREREQ"
  1651. }
  1652. case "$1" in
  1653.     prereqs)
  1654.          prereqs
  1655.          exit 0
  1656.     ;;
  1657. esac
  1658. . /scripts/functions
  1659.  
  1660. sleep 10
  1661. echo "Looking for inactive arrays ..."
  1662. cat /proc/mdstat
  1663. echo ""
  1664. i=0;
  1665. for md in $(cat /proc/mdstat | grep inactive | cut -d" " -f1); do
  1666.     devs="$(cat /proc/mdstat | grep ^${md} | cut -d" " -f5- | sed -e 's/\[[0-9]\]//g' -e 's/sd/\/dev\/sd/g')"
  1667.     echo "${md} is inactive. Devices: ${devs}"
  1668.     echo "Stopping ${md} ..."
  1669.     mdadm --stop /dev/${md}
  1670.     echo "Assembling ${md} ..."
  1671.     mdadm --assemble /dev/${md} ${devs} || ( echo "Assembling ${md} (--force) ..."; mdadm --assemble --force /dev/${md} ${devs})
  1672.     echo ""
  1673.     i=$(( ${i} + 1 ))
  1674. done
  1675. echo ""
  1676. if [ $i -gt 0 ]; then
  1677.     echo "${i} arrays were inactive."
  1678.     echo "/proc/mdstat is now:"
  1679.     cat /proc/mdstat
  1680.     sleep 5
  1681. else
  1682.     echo "All arrays seem to be active"
  1683. fi
  1684. echo ""
  1685. __EOF__
  1686.  
  1687.         # Make it executable
  1688.         chmod a+x /etc/initramfs-tools/scripts/init-premount/zzmdraidforce
  1689.     fi # if disks > 1
  1690.  
  1691. #-------------------------------------------------------------------------------------------------------------------
  1692. ##### Unlock script for dropbear in initramfs
  1693.     cat > /etc/initramfs-tools/hooks/mount_cryptroot << '__EOFF__'
  1694. #!/bin/sh
  1695.  
  1696. # This script generates two scripts in the initramfs output,
  1697. # /root/mount_cryptroot.sh and /root/.profile
  1698. # https://projectgus.com/2013/05/encrypted-rootfs-over-ssh-with-debian-wheezy/
  1699.  
  1700. ALLOW_SHELL=1
  1701. # Set this to 1 before running update-initramfs if you want
  1702. # to allow authorized users to type Ctrl-C to drop to a
  1703. # root shell (useful for debugging, potential for abuse.)
  1704. #
  1705. # (Note that even with ALLOW_SHELL=0 it may still be possible
  1706. # to achieve a root shell.)
  1707.  
  1708. PREREQ="dropbear"
  1709. prereqs() {
  1710.     echo "$PREREQ"
  1711. }
  1712. case "$1" in
  1713.     prereqs)
  1714.         prereqs
  1715.         exit 0
  1716.     ;;
  1717. esac
  1718.  
  1719. . "${CONFDIR}/initramfs.conf"
  1720. . /usr/share/initramfs-tools/hook-functions
  1721.  
  1722. if [ -z ${DESTDIR} ]; then
  1723.     exit
  1724. fi
  1725.  
  1726. # 16.04/xenial uses a tempdir for /root homedir, so need to find which one it is
  1727. # something like /root-2EpTFt/
  1728. ROOTDIR=`ls -1d ${DESTDIR}/root* | tail -1`
  1729. SCRIPT="${ROOTDIR}/mount_cryptroot.sh"
  1730. cat > "${SCRIPT}" << 'EOF'
  1731. #!/bin/sh
  1732. CMD=
  1733. while [ -z "$CMD" -o -z "`pidof askpass plymouth`" ]; do
  1734.   # force use of busybox for ps
  1735.   CMD=`busybox ps -o args | grep cryptsetup | grep -i open | grep -v grep`
  1736.   # Not using busybox, using klibc
  1737.   # CMD=`ps -o args | grep cryptsetup | grep -i open | grep -v grep`
  1738.  
  1739.   sleep 0.1
  1740. done
  1741. while [ -n "`pidof askpass plymouth`" ]; do
  1742.   $CMD && kill -9 `pidof askpass plymouth` && echo "Success"
  1743. done
  1744. EOF
  1745.  
  1746. chmod +x "${SCRIPT}"
  1747.  
  1748. # Run mount_cryptroot by default and close the login session afterwards
  1749. # If ALLOW_SHELL is set to 1, you can press Ctrl-C to get to an interactive prompt
  1750. cat > "${ROOTDIR}/.profile" << EOF
  1751. ctrl_c_exit() {
  1752.   exit 1
  1753. }
  1754. ctrl_c_shell() {
  1755.   # Ctrl-C during .profile appears to mangle terminal settings
  1756.   reset
  1757. }
  1758. if [ "$ALLOW_SHELL" == "1" ]; then
  1759.   echo "Unlocking rootfs... Type Ctrl-C for a shell."
  1760.   trap ctrl_c_shell INT
  1761. else
  1762.   echo "Unlocking rootfs..."
  1763.   trap ctrl_c_exit INT
  1764. fi
  1765. ${ROOTDIR#$DESTDIR}/mount_cryptroot.sh && exit 1 || echo "Run ./mount_cryptroot.sh to try unlocking again"
  1766. trap INT
  1767. EOF
  1768. __EOFF__
  1769.     chmod +x /etc/initramfs-tools/hooks/mount_cryptroot
  1770.  
  1771. #-------------------------------------------------------------------------------------------------------------------
  1772.     ##### Second script to handle converting SSH keys.
  1773.     # You might NOT want to use this as now your SSH keys are stored inside
  1774.     # plaintext initramfs instead of only encypted volume.
  1775.     cat > /etc/initramfs-tools/hooks/dropbear.fixup2 <<'__EOFF__'
  1776. #!/bin/sh
  1777. PREREQ="dropbear"
  1778. prereqs() {
  1779.     echo "$PREREQ"
  1780. }
  1781. case "$1" in
  1782.     prereqs)
  1783.         prereqs
  1784.         exit 0
  1785.     ;;
  1786. esac
  1787.    
  1788. . "${CONFDIR}/initramfs.conf"
  1789. . /usr/share/initramfs-tools/hook-functions
  1790.    
  1791. # Convert SSH keys
  1792. if [ "${DROPBEAR}" != "n" ] && [ -r "/etc/crypttab" ] ; then
  1793.     echo "----- Installing host SSH keys into dropbear initramfs -----"
  1794.     # /usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key ${DESTDIR}/etc/dropbear/dropbear_dss_host_key
  1795.     /usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key ${DESTDIR}/etc/dropbear/dropbear_rsa_host_key
  1796.     /usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_ecdsa_key ${DESTDIR}/etc/dropbear/dropbear_ecdsa_host_key
  1797. fi
  1798. __EOFF__
  1799.  
  1800. # Make it executable
  1801. chmod a+x /etc/initramfs-tools/hooks/dropbear.fixup2
  1802.  
  1803. #-------------------------------------------------------------------------------------------------------------------
  1804.     # Put SSH pubkey in initramfs
  1805.     echo "-----------------------------------------------------------------------------"
  1806.     echo "Installing sshpubkey ${SSHPUBKEY} and ${GITPUBKEYS} pubkey(s) into dropbear initramfs"
  1807.     [ ! -e /etc/initramfs-tools/root/.ssh ] && mkdir -p /etc/initramfs-tools/root/.ssh
  1808.     echo "${SSHPUBKEY}" >> /etc/initramfs-tools/root/.ssh/authorized_keys
  1809.     for GITKEY in ${GITPUBKEYS} ; do
  1810.         echo "####### Github ${GITKEY} keys #######" >> /etc/initramfs-tools/root/.ssh/authorized_keys
  1811.         echo "$(wget --quiet -O- https://github.com/${GITKEY}.keys)" >> /etc/initramfs-tools/root/.ssh/authorized_keys
  1812.         echo "####### Github ${GITKEY} keys #######" >> /etc/initramfs-tools/root/.ssh/authorized_keys
  1813.         echo "#" >> /etc/initramfs-tools/root/.ssh/authorized_keys
  1814.     done
  1815.     echo "-----------------------------------------------------------------------------"
  1816.    
  1817. fi # if LUKS
  1818.  
  1819. #-------------------------------------------------------------------------------------------------------------------
  1820. # udev rule to enable seeing vmware scsi disks
  1821. cat > /etc/udev/rules.d/99-vmware.rules << "EOF"
  1822. # VMWare SCSI devices have no serial - use VMWARE_ and device ID as serial
  1823. KERNEL=="sd*[!0-9]|sr*", ENV{ID_VENDOR}=="VMware_" IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_SERIAL}="VMWARE_%k"
  1824.  
  1825. KERNEL=="sd*|sr*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
  1826.  
  1827. KERNEL=="sd*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n"
  1828.  
  1829. # ----------------------------- scsi type disk
  1830. # ID_SCSI=1
  1831. # ID_VENDOR=VMware_
  1832. # ID_VENDOR_ENC=VMware\x2c\x20
  1833. # ID_MODEL=VMware_Virtual_S
  1834. # ID_MODEL_ENC=VMware\x20Virtual\x20S
  1835. # ID_REVISION=1.0
  1836. # ID_TYPE=disk
  1837. # ----------------------------- sata type disk
  1838. # ID_SCSI=1
  1839. # ID_VENDOR=ATA
  1840. # ID_VENDOR_ENC=ATA\x20\x20\x20\x20\x20
  1841. # ID_MODEL=VMware_Virtual_S
  1842. # ID_MODEL_ENC=VMware\x20Virtual\x20S
  1843. # ID_REVISION=0001
  1844. # ID_TYPE=disk
  1845. # ID_SERIAL=35000c293157635fb
  1846. # ID_SERIAL_SHORT=5000c293157635fb
  1847. # ID_WWN=0x5000c293157635fb
  1848. # ID_WWN_WITH_EXTENSION=0x5000c293157635fb
  1849. # ID_SCSI_SERIAL=00000000000000000001
  1850. EOF
  1851.  
  1852. cat > /etc/udev/rules.d/61-zfs-vdev.rules << "EOF"
  1853. # These create links for the ZFS partitions in /dev
  1854. # So the various update-* utilities work, since they don't look in
  1855. # /dev/disk/by-id for whatever reason :(
  1856.  
  1857. # This from https://bugs.launchpad.net/ubuntu/+source/zfs-initramfs/+bug/1530953
  1858. # Also https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Ubuntu-14.04---15.04-to-a-Native-ZFS-Root-Filesystem
  1859.  
  1860. KERNEL=="sd*[0-9]", IMPORT{parent}=="ID_*", ENV{ID_FS_TYPE}=="zfs_member", SYMLINK+="$env{ID_BUS}-$env{ID_SERIAL}-part%n"
  1861. KERNEL=="nvme*", ENV{ID_FS_TYPE}=="zfs_member", SYMLINK+="nvme-$env{ID_SERIAL}-part%n"
  1862. EOF
  1863.  
  1864. # https://bugs.launchpad.net/ubuntu/+source/zfs-initramfs/+bug/1530953/comments/28
  1865. # HRM - this one isn't working
  1866. # echo 'KERNEL=="sd*[0-9]", IMPORT{parent}=="ID_*", ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_TYPE}=="6a898cc3-1dd2-11b2-99a6-080020736631", SYMLINK+="$env{ID_BUS}-$env{ID_SERIAL}-part%n"' > /etc/udev/rules.d/60-zfs-vdev.rules
  1867.  
  1868.  
  1869. #-------------------------------------------------------------------------------------------------------------------
  1870. ##### Script to shutdown initramfs network before passing control to regular Ubuntu scripts
  1871. # Without this network config from initramfs is used forever plus causes extra
  1872. # few minutes of delay plus errors on bootup.
  1873. cat > /etc/initramfs-tools/scripts/init-bottom/network-down << '__EOFF__'
  1874. #!/bin/sh
  1875.  
  1876. PREREQ=""
  1877.  
  1878. prereqs() {
  1879.         echo "$PREREQ"
  1880. }
  1881.  
  1882. case $1 in
  1883. # get pre-requisites
  1884. prereqs)
  1885.         prereqs
  1886.         exit 0
  1887.         ;;
  1888. esac
  1889. # Shutdown initramfs network before passing control to regular Ubuntu scripts
  1890. # Without this network config from initramfs is used forever plus causes extra
  1891. # few minutes of delay plus errors on bootup.
  1892. ifconfig eth0 0.0.0.0 down
  1893. __EOFF__
  1894. chmod +x /etc/initramfs-tools/scripts/init-bottom/network-down
  1895.  
  1896. #-------------------------------------------------------------------------------------------------------------------
  1897. # Create fstab
  1898. echo "tmpfs                   /tmp    tmpfs   defaults,noatime,mode=1777      0 0" >> /etc/fstab
  1899.  
  1900. if [ ${SIZE_ZVOL} ] && [ ${SIZE_ZVOL} != 0 ]; then
  1901.     echo "" >> /etc/fstab
  1902.     echo "# ${BOXNAME}_zwap is the zfs SWAP zvol" >> /etc/fstab
  1903.     echo "/dev/zvol/${POOLNAME}/SWAP    none    swap    defaults                        0 0" >> /etc/fstab
  1904. fi
  1905.  
  1906. if [ ${SIZE_SWAP} ] && [ ${SIZE_SWAP} != 0 ]; then
  1907.     echo "" >> /etc/fstab
  1908.     echo "# ${BOXNAME}_swap is the mdadm array of partition ${PARTITION_SWAP} on all drives" >> /etc/fstab
  1909.     echo "UUID=$(blkid -t LABEL=${BOXNAME}_swap -s UUID -o value) none swap defaults   0 0" >>/etc/fstab
  1910. fi
  1911.  
  1912. if [ "ZZ${UEFI}" = "ZZy" ]; then
  1913.     # If there's only one disk, be certain to find the UUID
  1914.     if [ ${#DISKS[@]} = 1 ]; then
  1915.         echo "" >> /etc/fstab
  1916.         echo "UUID=$(blkid -t PARTLABEL=EFI_1 -s UUID -o value) /boot/efi vfat defaults  0 1" >>/etc/fstab
  1917.     else
  1918.         # Multiple disks --> EFI partitions are in a raid mirror array
  1919.         #   so ${BOXNAME}_efi should be the label generated by mdadm
  1920.         #   when creating the array
  1921.         echo "" >> /etc/fstab
  1922.         echo "UUID=$(blkid -t LABEL=${BOXNAME}_efi -s UUID -o value) /boot/efi vfat defaults  0 1" >>/etc/fstab
  1923.     fi
  1924.  
  1925.     #for DISK in `seq 1 ${#DISKS[@]}` ; do
  1926.     #   echo "UUID=$(blkid -t LABEL=EFI_${DISK} -s UUID -o value) /boot/efi_${DISK} vfat defaults  0 1" >>/etc/fstab
  1927.     #done
  1928. fi
  1929.  
  1930. #-------------------------------------------------------------------------------------------------------------------
  1931. # Set GRUB to use VBE and framebuffer for 16.04
  1932. if [ ${SUITE} = xenial ]; then
  1933.     cat >> /etc/default/grub << '__EOF__'
  1934.  
  1935. # https://onetransistor.blogspot.com/2016/03/plymouth-fix-nvidia.html
  1936. # Also see /etc/initramfs-tools/conf.d/splash
  1937. GRUB_GFXPAYLOAD_LINUX="keep"
  1938. GRUB_GFXMODE="800x600x32"
  1939. __EOF__
  1940.     # NOTE: VBE is only for non-EFI systems
  1941.     if [ "ZZ${UEFI}" != "ZZy" ]; then
  1942.         echo 'GRUB_VIDEO_BACKEND="vbe"' >> /etc/default/grub
  1943.     fi
  1944.     echo "FRAMEBUFFER=y" > /etc/initramfs-tools/conf.d/splash
  1945.    
  1946.     # Manually enable solar theme (cuz I like it), and update-alternatives doesn't show it
  1947.     # The flares don't work on bootup, boo hiss, although they do work on shutdown.  WTF ?
  1948.     # Actually, they work until the password prompt is put up.  Double WTF ?
  1949.     rm -f /etc/alternatives/default.plymouth
  1950.     ln -s /usr/share/plymouth/themes/solar/solar.plymouth /etc/alternatives/default.plymouth
  1951. fi
  1952.  
  1953. # Set GRUB to use zfs - enable zswap if USE_ZSWAP="zswap parameters"
  1954. # Also disabling persistent interface names, sticking to eth0 and so on
  1955. sed -i "s/GRUB_CMDLINE_LINUX_DEFAULT.*/GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0 biosdevname=0 rpool=${POOLNAME} bootfs=${POOLNAME}\/ROOT boot=zfs bootdegraded=true ${USE_ZSWAP} splash\"/" /etc/default/grub
  1956. # If using zswap enable lz4 compresstion
  1957. if [ "ZZ${USE_ZSWAP}" != "ZZ" ]; then
  1958.     echo "lz4" >> /etc/modules
  1959.     echo "lz4" >> /etc/initramfs-tools/modules
  1960. fi
  1961.  
  1962. #-------------------------------------------------------------------------------------------------------------------
  1963. # Export and import boot zpool to populate /etc/zfs/zpool.cache if using LUKS
  1964. if [ "ZZ${LUKS}" = "ZZy" ]; then
  1965.     zpool export boot
  1966.     zpool import -f -d /dev/disk/by-id boot
  1967. fi
  1968.  
  1969. #-------------------------------------------------------------------------------------------------------------------
  1970. # Clear existing EFI NVRAM boot order, it's more than likely incorrect for our needs by now
  1971. # Also sets 10 second timeout for EFI boot menu just in case it was set to too low value earlier
  1972. # NOTE: Most information for EFI install comes from here :
  1973. #   http://blog.asiantuntijakaveri.fi/2014/12/headless-ubuntu-1404-server-with-full.html
  1974. if [ -e /sys/firmware/efi ]; then
  1975.     efibootmgr --delete-bootorder --timeout 10 --write-signature
  1976.  
  1977.     # Remove unwanted, existing boot entries from EFI list
  1978.     for f in `seq 0 6`; do
  1979.         efibootmgr --delete-bootnum --bootnum 000${f}
  1980.     done
  1981. fi
  1982.  
  1983. #-------------------------------------------------------------------------------------------------------------------
  1984. # Create grub device.map for just install drives - eg.
  1985. # grub-mkdevicemap -nvv
  1986. # (hd0) /dev/disk/by-id/ata-VBOX_HARDDISK_VB7e33e873-e3c9fd91
  1987. # (hd1) /dev/disk/by-id/ata-VBOX_HARDDISK_VB3f3328bd-1d7db667
  1988. # (hd2) /dev/disk/by-id/ata-VBOX_HARDDISK_VB11f330ab-76c3340a
  1989. #
  1990. # We do this manually rather than grub-mkdevicemap to ensure we only use the disks
  1991. # listed in ZFS-setup.disks.txt, in case there are other disks in the system
  1992. echo "" > /boot/grub/device.map
  1993. for DISK in `seq 1 ${#DISKS[@]}` ; do
  1994.     HD=$(($DISK - 1))
  1995.     echo "(hd${HD}) /dev/disk/by-id/${DISKS[${DISK}]}" >> /boot/grub/device.map
  1996. done
  1997. # cat /boot/grub/device.map
  1998.  
  1999. # Install and update grub  https://ubuntuforums.org/showthread.php?t=2223856&page=3
  2000. for DISK in `seq 1 ${#DISKS[@]}` ; do
  2001.     sgdisk -C /dev/disk/by-id/${DISKS[${DISK}]}
  2002.     sgdisk -h ${PARTITION_GRUB} /dev/disk/by-id/${DISKS[${DISK}]}
  2003.    
  2004. ##  if [ "ZZ${UEFI}" = "ZZy" ]; then
  2005. ##      mkdir -p /boot/efi_${DISK}
  2006. ##      mount /boot/efi_${DISK}
  2007. ##     
  2008. ##      # Install grub to EFI system partition
  2009. ##      echo "Ignore errors from grub-install here if not in EFI mode"
  2010. ##      grub-install --boot-directory=/boot --bootloader-id="ZFS-${DISK}" --no-floppy --recheck --target=x86_64-efi --efi-directory=/boot/efi_${DISK} /dev/disk/by-id/${DISKS[${DISK}]}
  2011. ##  fi
  2012.     grub-install --target=i386-pc /dev/disk/by-id/${DISKS[${DISK}]}
  2013. done
  2014.  
  2015. #-------------------------------------------------------------------------------------------------------------------
  2016. if [ "ZZ${UEFI}" = "ZZy" ]; then
  2017.     mkdir -p /boot/efi
  2018.     mount /boot/efi
  2019.  
  2020.     # Install grub to EFI system partition
  2021.     echo "Ignore errors from grub-install here if not in EFI mode"
  2022.     grub-install --boot-directory=/boot --bootloader-id="ZFS" --no-floppy --recheck --target=x86_64-efi --efi-directory=/boot/efi ${EFIDEVRAW}
  2023.  
  2024. ##  # Make disks bootable on non-EFI system
  2025. ##  for DISK in `seq 1 ${#DISKS[@]}` ; do
  2026. ##      mkdir -p /boot/efi_${DISK}/EFI/BOOT
  2027. ##      cp -a "/boot/efi_${DISK}/EFI/ZFS-${DISK}/grubx64.efi" /boot/efi_${DISK}/EFI/BOOT/bootx64.efi
  2028. ##      [ -d /sys/firmware/efi ] && efibootmgr --create --disk /dev/disk/by-id/${DISKS[${DISK}]} --part ${PARTITION_EFI} --write-signature --loader '\EFI\BOOT\bootx64.efi' --label "EFI fallback disk ${DISK}"
  2029. ##  done
  2030.  
  2031.     mkdir -p /boot/efi/EFI/BOOT
  2032.     # Get EFI shell
  2033.     wget --no-proxy -O /boot/efi/shellx64.efi https://svn.code.sf.net/p/edk2/code/trunk/edk2/EdkShellBinPkg/FullShell/X64/Shell_Full.efi
  2034.     cp /boot/efi/shellx64.efi /boot/efi/EFI/BOOT
  2035.     cp -a "/boot/efi/EFI/ZFS/grubx64.efi" /boot/efi/EFI/BOOT/bootx64.efi
  2036.  
  2037.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  2038.         [ -d /sys/firmware/efi ] && efibootmgr --create --disk /dev/disk/by-id/${DISKS[${DISK}]} --part ${PARTITION_EFI} --write-signature --loader '\EFI\BOOT\bootx64.efi' --label "EFI fallback disk ${DISK}"
  2039.  
  2040.         # grub-install here should build entries in bootmgr - equivalent efibootmgr cmd below
  2041.         grub-install --boot-directory=/boot --bootloader-id="ZFS-${DISK}" --no-floppy --recheck --target=x86_64-efi --efi-directory=/boot/efi_${DISK} /dev/disk/by-id/${DISKS[${DISK}]}
  2042.         ## [ -d /sys/firmware/efi ] && efibootmgr --create --disk /dev/disk/by-id/${DISKS[${DISK}]} --part ${PARTITION_EFI} --write-signature --loader '\EFI\ZFS\grubx64.efi' --label "ZFS-${DISK}"
  2043.     done
  2044.  
  2045. ##  # Create grub.cfg
  2046. ##  grub-mkconfig -o /boot/efi_1/EFI/grub.cfg
  2047. ##  for DISK in `seq 2 ${#DISKS[@]}` ; do
  2048. ##      cp -a /boot/efi_1/EFI/grub.cfg /boot/efi_${DISK}/EFI
  2049. ##  done
  2050.     grub-mkconfig -o /boot/efi/EFI/grub.cfg
  2051.  
  2052. fi #UEFI
  2053. update-grub
  2054.  
  2055. ### Re-order EFI boot order
  2056. ##if [ "ZZ${UEFI}" = "ZZy" ]; then
  2057. ##  for DISK in `seq 1 ${#DISKS[@]}` ; do
  2058. ##      umount /boot/efi_${DISK}
  2059. ##  done
  2060. ## 
  2061. ##  # 2 entries per disk - regular in /boot/efi_X/EFI/ZFS-X and fallback in /boot/efi_X/BOOT
  2062. ##  EFIENTRIES=$(( ${#DISKS[@]} * 2 ))
  2063. ##  EFIORDER="0"
  2064. ##  for ENTRY in `seq 1 $(( ${EFIENTRIES} - 1 ))` ; do
  2065. ##      EFIORDER="${EFIORDER},${ENTRY}"
  2066. ##  done
  2067. ##  [ -d /sys/firmware/efi ] && efibootmgr --bootorder ${EFIORDER}
  2068. ##fi
  2069.  
  2070. #-------------------------------------------------------------------------------------------------------------------
  2071. # Nicer PS1 prompt
  2072. cat >> /etc/bash.bashrc << EOF
  2073.  
  2074. PS1="${debian_chroot:+($debian_chroot)}\[\$(tput setaf 2)\]\u@\[\$(tput bold)\]\[\$(tput setaf 5)\]\h\[\$(tput sgr0)\]\[\$(tput setaf 7)\]:\[\$(tput bold)\]\[\$(tput setaf 4)\]\w\[\$(tput setaf 7)\]\\$ \[\$(tput sgr0)\]"
  2075.  
  2076. # https://unix.stackexchange.com/questions/99325/automatically-save-bash-command-history-in-screen-session
  2077. PROMPT_COMMAND="history -a; history -c; history -r; \${PROMPT_COMMAND}"
  2078. HISTSIZE=5000
  2079. export LC_ALL=en_US.UTF-8
  2080. export LANG=en_US.UTF-8
  2081. export LANGUAGE=en_US.UTF-8
  2082. EOF
  2083. cat >> /etc/skel/.bashrc << EOF
  2084.  
  2085. PS1="${debian_chroot:+($debian_chroot)}\[\$(tput setaf 2)\]\u@\[\$(tput bold)\]\[\$(tput setaf 5)\]\h\[\$(tput sgr0)\]\[\$(tput setaf 7)\]:\[\$(tput bold)\]\[\$(tput setaf 4)\]\w\[\$(tput setaf 7)\]\\$ \[\$(tput sgr0)\]"
  2086.  
  2087. # https://unix.stackexchange.com/questions/99325/automatically-save-bash-command-history-in-screen-session
  2088. PROMPT_COMMAND="history -a; history -c; history -r; \${PROMPT_COMMAND}"
  2089. HISTSIZE=5000
  2090. alias ls='ls --color=auto'
  2091. alias l='ls -la'
  2092. alias lt='ls -lat | head -25'
  2093. alias vhwinfo='wget --no-check-certificate https://vhwinfo.com/vhwinfo.sh -O - -o /dev/null|bash'
  2094. EOF
  2095. cat >> /root/.bashrc << "EOF"
  2096. # PS1='\[\033[01;37m\]\[\033[01;41m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]$ '
  2097. PS1='\[\033[01;37m\]\[\033[01;41m\]\u@\[\033[00m\]\[$(tput bold)\]\[$(tput setaf 5)\]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]$ '
  2098.  
  2099. # https://unix.stackexchange.com/questions/99325/automatically-save-bash-command-history-in-screen-session
  2100. PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND}"
  2101. HISTSIZE=5000
  2102. export LC_ALL=en_US.UTF-8
  2103. export LANG=en_US.UTF-8
  2104. export LANGUAGE=en_US.UTF-8
  2105. EOF
  2106.  
  2107. cat >> /root/.bash_aliases << EOF
  2108. alias ls='ls --color=auto'
  2109. alias l='ls -la'
  2110. alias lt='ls -lat | head -25'
  2111. alias vhwinfo='wget --no-check-certificate https://vhwinfo.com/vhwinfo.sh -O - -o /dev/null|bash'
  2112.  
  2113. # Rebuild all dkms modules
  2114. alias dkms_rebuild='ls /var/lib/initramfs-tools | sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start'
  2115. EOF
  2116.  
  2117. #-------------------------------------------------------------------------------------------------------------------
  2118. # Create user and apply Custom config script if defined
  2119. # Not using --create-home as dir should already exist as a zfs dataset
  2120. # -M to prevent it from trying to create a home dir
  2121. useradd -c "${UCOMMENT}" -p $(echo "${UPASSWORD}" | mkpasswd -m sha-512 --stdin) -M --home-dir /home/${USERNAME} --user-group --groups adm,sudo,dip,plugdev --shell /bin/bash ${USERNAME}
  2122. # Since /etc/skel/* files aren't copied, have to do it manually
  2123. rsync -a /etc/skel/ /home/${USERNAME}
  2124.  
  2125. mkdir -p /root/.ssh /home/${USERNAME}/.ssh
  2126. echo "${SSHPUBKEY}" >> /root/.ssh/authorized_keys
  2127. for GITKEY in ${GITPUBKEYS} ; do
  2128.     echo "####### Github ${GITKEY} keys #######" >> /root/.ssh/authorized_keys
  2129.     echo "$(wget --quiet -O- https://github.com/${GITKEY}.keys)" >> /root/.ssh/authorized_keys
  2130.     echo "####### Github ${GITKEY} keys #######" >> /root/.ssh/authorized_keys
  2131.     echo "#" >> /root/.ssh/authorized_keys
  2132. done
  2133. cp /root/.ssh/authorized_keys /home/${USERNAME}/.ssh
  2134. chmod 700 /root/.ssh /home/${USERNAME}/.ssh
  2135. chown -R ${USERNAME}.${USERNAME} /home/${USERNAME}
  2136.  
  2137. #-----------------------------------------------------------------------------
  2138. # Now finally make an initramfs
  2139. # Ugly hack to get kernel version
  2140. KVER=$(basename $(ls -1 /boot/vmlinuz* | sort -rn) | sed -e 's/vmlinuz-//')
  2141. rm -fv /tmp/fakestart/update-initramfs
  2142. update-initramfs -c -k ${KVER}
  2143. update-grub
  2144.  
  2145. #-----------------------------------------------------------------------------
  2146. zfs snap ${POOLNAME}/ROOT@Pre-Custom
  2147. if [ "ZZ${HOMEPOOL}" = "ZZy" ]; then
  2148.     zfs snap ${POOLNAME}/HOME/${USERNAME}@Pre-Custom
  2149. fi
  2150.  
  2151. # If Ansible dir exists, run the playbook
  2152. if [ ! -z ${DISTRO+x} ] ; then
  2153.     [ -e /root/Ansible ] && ansible-playbook -i /root/Ansible/hosts -l localhost /root/Ansible/Desktop.yml --extra-vars "distro=${DISTRO} poolname=${POOLNAME}"
  2154. else
  2155.     [ -e /root/Ansible ] && ansible-playbook -i /root/Ansible/hosts -l localhost /root/Ansible/Desktop.yml
  2156. fi
  2157.  
  2158. #-----------------------------------------------------------------------------
  2159. # Run Custom script to install user-chosen stuff and configurations - take snapshot first
  2160. if [ "${CUSTOMSCRIPT}ZZ" != "ZZ" ] ; then
  2161.     echo "Running custom script Setup-Custom.sh (from ${CUSTOMSCRIPT})"
  2162.     [ -e /root/Setup-Custom.sh ] && eval /root/Setup-Custom.sh
  2163. fi
  2164.  
  2165. # Final update - make sure we don't overwrite modified config files like bash.bashrc
  2166. # https://askubuntu.com/questions/104899/make-apt-get-or-aptitude-run-with-y-but-not-prompt-for-replacement-of-configu
  2167. apt-get -qq -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -f install
  2168. apt-get -qq -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --allow-downgrades --allow-remove-essential upgrade
  2169. apt-get -qq -y clean
  2170. apt-get -qq -y autoclean
  2171. apt-get -qq -y autoremove
  2172. # Don't need the whole list of apt files in logfile, so disable -x
  2173. set +x
  2174. rm -rf /var/lib/apt/lists/*
  2175.  
  2176. #-----------------------------------------------------------------------------
  2177. zfs snap ${POOLNAME}/ROOT@Post-Custom
  2178. if [ "ZZ${HOMEPOOL}" = "ZZy" ]; then
  2179.     zfs snap ${POOLNAME}/HOME/${USERNAME}@Post-Custom
  2180. fi
  2181.  
  2182. exit
  2183. __EOFSETUP__
  2184. chmod +x /mnt/zfs/root/Setup.sh
  2185. # ======== END create Setup.sh script ===============================================================
  2186.  
  2187. # Here are a couple of helper scripts
  2188. # Replace-failed-drive.sh - goes into /root in new system, helps to replace a failed drive
  2189. #                         - NOTE: not complete yet
  2190. # Reboot-testing.sh       - goes into /root in local system, helps to enter/exit chroot
  2191. #                           for new system for debugging
  2192.  
  2193. # ============= Replacing drive helper script ====================================================
  2194. # Script to help in replacing a failed drive - goes in new /mnt/zfs system root dir
  2195. cat > /mnt/zfs/root/Replace-failed-drive.sh << '__EOFREPLACE__'
  2196. #!/bin/bash
  2197.  
  2198. # If you're using this script, then one of the drives has failed.  You need to define a few
  2199. # things here : GOODDISK, NEWDISK and NEW
  2200.  
  2201. # These were the drives that were installed initially
  2202. __EOFREPLACE__
  2203.  
  2204. for DISK in `seq 1 ${#DISKS[@]}` ; do
  2205.     echo "DISKS[${DISK}]=${DISKS[${DISK}]}" >> /mnt/zfs/root/Replace-failed-drive.sh
  2206. done
  2207.  
  2208. cat >> /mnt/zfs/root/Replace-failed-drive.sh << __EOFREPLACE1__
  2209.  
  2210. # Representative good disk - this is the source of a good partition table
  2211. # Used to create a new partition table on the NEWDISK defined below
  2212. export GOODDISK=ata-VBOX_HARDDISK_VB2d8b0815-33f95506<<--This-is-a-sample
  2213.  
  2214. # New replacement disk
  2215. export NEWDISK=ata-VBOX_HARDDISK_VBc6d3eb9a-d59c8e36<<--This-is-a-sample
  2216.  
  2217. # Suffix for new partitions and /boot/efi_ directory
  2218. NEW=NEW
  2219.  
  2220. # NOTE: These definitions above are just *REPRESENTATIVE* - you need to fill in your
  2221. #       own real disk definitions from /dev/disk/by-id
  2222.  
  2223. ## For testing, you can offline/delete a drive, /dev/sdc
  2224. ##
  2225. ## Should unmount the /boot/efi_X before deleting the drive
  2226. #  umount /boot/efi_X
  2227. ##
  2228. #  readlink /sys/block/sdc
  2229. ## ../devices/pci0000:00/0000:00:0d.0/ata6/host5/target5:0:0/5:0:0:0/block/sdc
  2230. ##                                         ^^^^^
  2231. ## Force disconnect of drive
  2232. #  echo 1 > /sys/block/sdX/device/delete
  2233. ##                     ^^^
  2234. ## Trigger rescan of a given port
  2235. #  echo "- - -" > /sys/class/scsi_host/host5/scan
  2236. ##                                     ^^^^^
  2237.  
  2238. export BOXNAME=${BOXNAME}
  2239. export POOLNAME=${POOLNAME}
  2240. export LUKS=${LUKS}
  2241. export RANDOMIZE=${RANDOMIZE}
  2242. export UEFI=${UEFI}
  2243. export SIZE_SWAP=${SIZE_SWAP}
  2244. export PASSPHRASE=${PASSPHRASE}
  2245. export PARTITION_EFI=${PARTITION_EFI}
  2246. export PARTITION_GRUB=${PARTITION_GRUB}
  2247. export PARTITION_BOOT=${PARTITION_BOOT}
  2248. export PARTITION_SWAP=${PARTITION_SWAP}
  2249. export PARTITION_DATA=${PARTITION_DATA}
  2250. export PARTITION_RSVD=${PARTITION_RSVD}
  2251. __EOFREPLACE1__
  2252.  
  2253. cat >> /mnt/zfs/root/Replace-failed-drive.sh << '__EOFREPLACE2__'
  2254.  
  2255. if [ ${NEWDISK} = "ata-VBOX_HARDDISK_VBc6d3eb9a-d59c8e36<<--This-is-a-sample" ] ; then
  2256.     echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
  2257.     echo "!!  Must edit GOODDISK and NEWDISK variables  !!"
  2258.     echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
  2259.     exit 1
  2260. fi
  2261.  
  2262. exec > >(tee -a /root/Replace-failed-drive.log) 2>&1
  2263.  
  2264. # Randomize entire disk
  2265. if [ "ZZ${RANDOMIZE}" = "ZZy" ]; then
  2266.     # urandom is limited, so use frandom module
  2267.     [ ! -e /var/lib/dpkg/info/build-essential.list ] && apt-get -qq -y install build-essential
  2268.     if [ ! -e /usr/src/frandom ]; then
  2269.         mkdir -p /usr/src/frandom
  2270.         wget --no-proxy http://billauer.co.il/download/frandom-1.1.tar.gz -O /usr/src/frandom/frandom-1.1.tar.gz
  2271.         tar --directory /usr/src/frandom -xvzf /usr/src/frandom/frandom-1.1.tar.gz
  2272.     fi
  2273.     cd /usr/src/frandom/frandom-1.1
  2274.     rm -f *o
  2275.     make
  2276.     install -m 644 frandom.ko /lib/modules/`uname -r`/kernel/drivers/char/
  2277.     depmod -a
  2278.     modprobe frandom
  2279.  
  2280.     dd if=/dev/frandom of=/dev/disk/by-id/${NEWDISK} bs=512 count=$(blockdev --getsz /dev/disk/by-id/${NEWDISK}) &
  2281.     WAITPIDS="${WAITPIDS} "$!
  2282. fi
  2283.  
  2284. # Clear any old zpool info
  2285. zpool labelclear -f /dev/disk/by-id/${NEWDISK} > /dev/null 2>&1
  2286. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} ] && zpool labelclear -f /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} > /dev/null 2>&1
  2287.  
  2288. mdadm --zero-superblock --force /dev/disk/by-id/${NEWDISK}*
  2289. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_BOOT} ] && mdadm --zero-superblock --force /dev/disk/by-id/${NEWDISK}-part${PARTITION_BOOT} > /dev/null 2>&1
  2290. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_SWAP} ] && mdadm --zero-superblock --force /dev/disk/by-id/${NEWDISK}-part${PARTITION_SWAP} > /dev/null 2>&1
  2291. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_RSVD} ] && mdadm --zero-superblock --force /dev/disk/by-id/${NEWDISK}-part${PARTITION_RSVD} > /dev/null 2>&1
  2292.  
  2293. # Clear any old LUKS or mdadm info
  2294. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} ] && dd if=/dev/zero of=/dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} bs=512 count=20480 > /dev/null 2>&1
  2295. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_SWAP} ] && dd if=/dev/zero of=/dev/disk/by-id/${NEWDISK}-part${PARTITION_SWAP} bs=512 count=20480 > /dev/null 2>&1
  2296. [ -e /dev/disk/by-id/${NEWDISK}-part${PARTITION_RSVD} ] && dd if=/dev/zero of=/dev/disk/by-id/${NEWDISK}-part${PARTITION_RSVD} bs=512 count=4096 > /dev/null 2>&1
  2297.  
  2298. sgdisk -Z /dev/disk/by-id/${NEWDISK}
  2299. sgdisk -R /dev/disk/by-id/${NEWDISK} /dev/disk/by-id/${GOODDISK} -G
  2300. partprobe /dev/disk/by-id/${NEWDISK}
  2301.  
  2302. # Only if we have UEFI
  2303. if [ "ZZ${UEFI}" = "ZZy" ]; then
  2304.     sgdisk -c${PARTITION_EFI}:"EFI_${NEW}" /dev/disk/by-id/${NEWDISK}
  2305. fi
  2306.  
  2307. # Encrypted means /boot on its own zfs pool, and rsvd is raided
  2308. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2309.     sgdisk -c${PARTITION_BOOT}:"BOOT_${NEW}" /dev/disk/by-id/${NEWDISK}
  2310. fi
  2311.  
  2312. # Only if swap partition
  2313. if [ ${SIZE_SWAP} ] &&[ ${SIZE_SWAP} != 0 ]; then
  2314.     sgdisk -c${PARTITION_SWAP}:"SWAP_${NEW}" /dev/disk/by-id/${NEWDISK}
  2315. fi
  2316.  
  2317. # Always have these
  2318. sgdisk -c${PARTITION_GRUB}:"GRUB_${NEW}" /dev/disk/by-id/${NEWDISK}
  2319. sgdisk -c${PARTITION_RSVD}:"RSVD_${NEW}" /dev/disk/by-id/${NEWDISK}
  2320. sgdisk -c${PARTITION_DATA}:"ZFS_${NEW}" /dev/disk/by-id/${NEWDISK}
  2321. partprobe /dev/disk/by-id/${NEWDISK}
  2322.  
  2323. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2324.     if [ ${#DISKS[@]} -gt 1 ]; then
  2325.         mdadm --manage /dev/md/${BOXNAME}:rsvd --add /dev/disk/by-id/${NEWDISK}-part${PARTITION_RSVD}
  2326.     fi
  2327. fi
  2328. if [ ${SIZE_SWAP} ] &&[ ${SIZE_SWAP} != 0 ]; then
  2329.     if [ ${#DISKS[@]} -gt 1 ]; then
  2330.         mdadm --manage /dev/md/${BOXNAME}:swap --add /dev/disk/by-id/${NEWDISK}-part${PARTITION_SWAP}
  2331.     fi
  2332. fi
  2333.  
  2334. mkfs.vfat -v -F32 -s2 -n "EFI_${NEW}" /dev/disk/by-id/${NEWDISK}-part${PARTITION_EFI}
  2335.  
  2336. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2337.     # Get failed zpool partitions and new encrypted partitions
  2338.     OLD${POOLNAME}="/dev/mapper/`zpool status -v ${POOLNAME} | fgrep FAULTED | tr -s ' ' | cut -d' ' -f2`"
  2339.     NEW${POOLNAME}=/dev/mapper/root_crypt${NEW}
  2340.    
  2341.     OLDBOOT="/dev/mapper/`zpool status -v boot | fgrep FAULTED | tr -s ' ' | cut -d' ' -f2`"
  2342.     NEWBOOT="/dev/disk/by-id/${NEWDISK}-part${PARTITION_BOOT}"
  2343.     ln -sf /dev/disk/by-id/${NEWDISK}-part${PARTITION_BOOT} /dev
  2344.  
  2345.     # Replace boot pool (only used with LUKS, non-encrypted though)
  2346.     zpool replace boot ${OLDBOOT} ${NEWBOOT}
  2347.  
  2348.     # Create new root_crypt${NEW}, add derived key to it
  2349.     echo ${PASSPHRASE} | cryptsetup --batch-mode luksFormat -c aes-xts-plain64 -s 512 -h sha512 /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA}
  2350.     echo ${PASSPHRASE} | cryptsetup luksOpen /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} root_crypt${NEW}
  2351.     ln -sf /dev/mapper/root_crypt${NEW} /dev/root_crypt${NEW}
  2352.     /lib/cryptsetup/scripts/decrypt_derived ${BOXNAME}:rsvd > /tmp/key
  2353.     echo ${PASSPHRASE} | cryptsetup luksAddKey /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} /tmp/key
  2354.  
  2355.     # Recreate crypttab
  2356.     # Remove old disk
  2357.     cp /etc/crypttab /etc/crypttab.backup
  2358.     cat /etc/crypttab.backup | fgrep -v `basename ${OLD${POOLNAME}}` > /etc/crypttab
  2359.  
  2360.     # Add new disk
  2361.     echo "root_crypt${NEW}  UUID=$(blkid /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} -s UUID -o value) none    luks,discard,noauto,checkargs=${BOXNAME}:swap,keyscript=/lib/cryptsetup/scripts/decrypt_derived" >> /etc/crypttab
  2362.  
  2363.     # Recreate cryptroot
  2364.     # Remove old disk
  2365.     cp /etc/initramfs-tools/conf.d/cryptroot /etc/initramfs-tools/conf.d/cryptroot.backup
  2366.     cat /etc/initramfs-tools/conf.d/cryptroot.backup | fgrep -v `basename ${OLD${POOLNAME}}` > /etc/initramfs-tools/conf.d/cryptroot
  2367.  
  2368.     # Add new disk
  2369.     echo "target=root_crypt${NEW},source=UUID=$(blkid /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} -s UUID -o value),rootdev,keyscript=/scripts/luks/get.root_crypt.decrypt_derived" >> /etc/initramfs-tools/conf.d/cryptroot
  2370. else
  2371.     # Replace failed zpool drive/partition with new drive/partition
  2372.     OLD${POOLNAME}="/`zpool status -v ${POOLNAME} | fgrep was | cut -d'/' -f2-`"
  2373.     # NEW${POOLNAME}="/dev/disk/by-id/`ls -al /dev/disk/by-id | fgrep ${NEWDISK}-part${PARTITION_DATA} | sed -e 's/.*\(ata.*\) ->.*/\1/'`"
  2374.     NEW${POOLNAME}="/dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA}"
  2375.     ln -sf /dev/disk/by-id/${NEWDISK}-part${PARTITION_DATA} /dev
  2376. fi
  2377.  
  2378. # Recreate fstab /boot/efi entries
  2379. # Add new disk
  2380. if [ "ZZ${UEFI}" = "ZZy" ]; then
  2381.     mkdir -p /boot/efi_${NEW}
  2382.     echo "UUID=$(blkid -t LABEL=EFI_${NEW} -s UUID -o value) /boot/efi_${NEW} vfat defaults,nobootwait,nofail 0 0" >>/etc/fstab
  2383.     mount /boot/efi_${NEW}
  2384.  
  2385.     # Copy EFI stuff from good disk to new disk (/boot/efi_${NEW})
  2386.     cp -a `cat /etc/fstab | fgrep "\`blkid /dev/disk/by-id/${GOODDISK}-part${PARTITION_EFI} -s UUID -o value\`" | cut -d' ' -f2`/* /boot/efi_${NEW}
  2387.  
  2388.     # Remove old /boot/efi_ (not mounted because ... disk is gone) dir from fstab
  2389.     OLDEFI=`( mount | fgrep /boot/efi_ | cut -d' ' -f3 ; fgrep /boot/efi_ /etc/fstab | cut -d' ' -f2 ) | sort | uniq -u`
  2390.     umount -f ${OLDEFI}
  2391.     rm -rf ${OLDEFI}
  2392.     cp /etc/fstab /etc/fstab.backup
  2393.     cat /etc/fstab.backup | fgrep -v ${OLDEFI} > /etc/fstab
  2394. fi
  2395.  
  2396. zpool replace ${POOLNAME} ${OLD${POOLNAME}} ${NEW${POOLNAME}}
  2397. zpool status -v
  2398.  
  2399. # Tell initramfs about new cryptroot etc
  2400. update-initramfs -c -k all
  2401. __EOFREPLACE2__
  2402. chmod +x /mnt/zfs/root/Replace-failed-drive.sh
  2403. # ============= Replacing drive helper script ====================================================
  2404.  
  2405. # ============= Reboot testing helper script =====================================================
  2406. # This goes in build-system to allow easy entry/exit from chroot new system in /mnt/zfs
  2407. cat > /root/Reboot-testing.sh << __EOFSETUP__
  2408. #!/bin/bash
  2409.  
  2410. # This script is to help with testing the newly installed zfs-on-root(-on luks maybe) system
  2411. # Invoked as Reboot-testing.sh will simply import the zpool (after possibly opening luks devices)
  2412. # bind-mount dev/sys/proc and start a new shell for you to work in.  Exit that shell and it
  2413. # unmounts the bind-mounts and exports the zpool
  2414.  
  2415. # Invoked with -y does the same but actually chroots into the mounted system in /mnt/zfs
  2416.  
  2417. export BOXNAME=${BOXNAME}
  2418. export POOLNAME=${POOLNAME}
  2419. export LUKS=${LUKS}
  2420. export DETACHEDHEADERS=${DETACHEDHEADERS}
  2421. export PASSPHRASE=${PASSPHRASE}
  2422. export UEFI=${UEFI}
  2423. export EFIDEVRAW=${EFIDEVRAW}
  2424. export USERNAME=${USERNAME}
  2425. export UPASSWORD=${UPASSWORD}
  2426. export SSHPUBKEY="${SSHPUBKEY}"
  2427. export GITPUBKEYS="${GITPUBKEYS}"
  2428. export SIZE_SWAP=${SIZE_SWAP}
  2429. export SWAPDEVRAW=${SWAPDEVRAW}
  2430. export RSVDDEVRAW=${RSVDDEVRAW}
  2431. export PARTITION_EFI=${PARTITION_EFI}
  2432. export PARTITION_GRUB=${PARTITION_GRUB}
  2433. export PARTITION_BOOT=${PARTITION_BOOT}
  2434. export PARTITION_SWAP=${PARTITION_SWAP}
  2435. export PARTITION_DATA=${PARTITION_DATA}
  2436. export PARTITION_RSVD=${PARTITION_RSVD}
  2437.  
  2438. __EOFSETUP__
  2439.  
  2440. for DISK in `seq 1 ${#DISKS[@]}` ; do
  2441.     echo "DISKS[${DISK}]=${DISKS[${DISK}]}" >> /root/Reboot-testing.sh
  2442. done
  2443.  
  2444. cat >> /root/Reboot-testing.sh << '__EOFREBOOT__'
  2445.  
  2446. # If this is an encrypted system ...
  2447. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2448.     ######## Detached headers
  2449.     # RSVD - LUKS-header-${BOXNAME}:rsvd.luksheader
  2450.     # SWAP - LUKS-header-${BOXNAME}:swap.luksheader
  2451.     # ROOT - LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader
  2452.  
  2453.     if [ ${SIZE_SWAP} ] &&[ ${SIZE_SWAP} != 0 ]; then
  2454.         if [ ${#DISKS[@]} -gt 1 ]; then
  2455.             if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  2456.                 echo ${PASSPHRASE} | cryptsetup luksOpen /dev/md/${BOXNAME}:swap --header /root/headers/LUKS-header-${BOXNAME}:swap.luksheader ${BOXNAME}:swap
  2457.             else
  2458.                 echo ${PASSPHRASE} | cryptsetup luksOpen /dev/md/${BOXNAME}:swap ${BOXNAME}:swap
  2459.             fi
  2460.             ln -sf /dev/mapper/${BOXNAME}:swap /dev
  2461.         fi
  2462.     fi
  2463.  
  2464.     # Unlock the ZFS safety partition
  2465.     if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  2466.         echo ${PASSPHRASE} | cryptsetup luksOpen ${RSVDDEVRAW} --header /root/headers/LUKS-header-${BOXNAME}:rsvd.luksheader ${BOXNAME}:rsvd
  2467.     else
  2468.         echo ${PASSPHRASE} | cryptsetup luksOpen ${RSVDDEVRAW} ${BOXNAME}:rsvd
  2469.     fi
  2470.     ln -sf /dev/mapper/${BOXNAME}:rsvd /dev
  2471.  
  2472.     # Unlock each ZFS partition
  2473.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  2474.         if [ "ZZ${DETACHEDHEADERS}" = "ZZy" ]; then
  2475.             echo ${PASSPHRASE} | cryptsetup luksOpen /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} --header /root/headers/LUKS-header-${DISKS[${DISK}]}-part${PARTITION_DATA}.luksheader root_crypt${DISK}
  2476.         else
  2477.             echo ${PASSPHRASE} | cryptsetup luksOpen /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} root_crypt${DISK}
  2478.         fi
  2479.         ln -sf /dev/mapper/root_crypt${DISK} /dev/root_crypt${DISK}
  2480.  
  2481.         # /boot partition is NOT encrypted, so use by-id
  2482.         ln -sf /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_BOOT} /dev
  2483.     done
  2484.    
  2485.     # Import the encrypted pool
  2486.     zpool import -N -f -d /dev/mapper -R /mnt/zfs ${POOLNAME}
  2487. else  # Not LUKS
  2488.     # Just create links for the encrypted partitions in /dev
  2489.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  2490.         ln -sf /dev/disk/by-id/${DISKS[${DISK}]}-part${PARTITION_DATA} /dev
  2491.     done
  2492.    
  2493.     # Import the unencrypted pool
  2494.     zpool import -N -f -d /dev/disk/by-id -R /mnt/zfs ${POOLNAME}
  2495. fi # LUKS
  2496.  
  2497. # Mount the root dataset, THEN mount the rest of the datasets (which live on root, duh)
  2498. zfs mount ${POOLNAME}/ROOT
  2499. zfs mount -a
  2500.  
  2501. # Only have a boot pool if the rest was encrypted
  2502. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2503.     rm -rf /mnt/zfs/boot/grub
  2504.     zpool import -f -d /dev/disk/by-id -R /mnt/zfs boot
  2505. fi
  2506.  
  2507. # Mount EFI partitions
  2508. if [ "ZZ${UEFI}" = "ZZy" ]; then
  2509.     # fgrep efi_ /mnt/zfs/etc/fstab | cut -d' ' -f1-2 | sed -e 's!/boot!/mnt/zfs/boot!; s/UUID=/-U /' | xargs -L1 mount
  2510.     mount ${EFIDEVRAW} /mnt/zfs/boot/efi
  2511. fi
  2512.  
  2513. # Mount the supporting virtual filesystems
  2514. [ ! -e /mnt/zfs/etc/mtab ] && ln -s /proc/mounts /mnt/zfs/etc/mtab
  2515. mount -o bind /proc /mnt/zfs/proc
  2516. mount -o bind /dev /mnt/zfs/dev
  2517. mount -o bind /dev/pts /mnt/zfs/dev/pts
  2518. mount -o bind /sys /mnt/zfs/sys
  2519.  
  2520. # Only chroot if we passed -y into script, otherwise just start a new shell
  2521. if [ "$1" = "-y" ]; then
  2522.     chroot /mnt/zfs /bin/bash --login
  2523. else
  2524.     bash --login
  2525. fi
  2526.  
  2527. # OK, exited chroot (or shell) so unmount the virtual filesystems
  2528. [ "ZZ${UEFI}" = "ZZy" ] && umount /mnt/zfs/boot/efi
  2529. umount /mnt/zfs/sys
  2530. umount /mnt/zfs/dev/pts
  2531. umount /mnt/zfs/proc
  2532. umount /mnt/zfs/dev
  2533.  
  2534. # Export the pools again so they will cleanly import on reboot
  2535. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2536.     zpool export boot
  2537. fi
  2538. zpool export ${POOLNAME}
  2539.  
  2540. # If system is encrypted need to cleanly close the LUKS devices
  2541. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2542.     if [ ${SIZE_SWAP} ] &&[ ${SIZE_SWAP} != 0 ]; then
  2543.         cryptsetup luksClose ${BOXNAME}:swap
  2544.     fi
  2545.     cryptsetup luksClose ${BOXNAME}:rsvd
  2546.     for DISK in `seq 1 ${#DISKS[@]}` ; do
  2547.         cryptsetup luksClose root_crypt${DISK}
  2548.     done
  2549. fi # LUKS
  2550. __EOFREBOOT__
  2551. chmod +x /root/Reboot-testing.sh
  2552. # ============= END Reboot testing helper script =====================================================
  2553.  
  2554. # Copy any Ansible setup into new system
  2555. [ -e Ansible ] && cp -av Ansible /mnt/zfs/root
  2556.  
  2557. # Snapshot the clean debootstrap install
  2558. zfs snap ${POOLNAME}/ROOT@debootstrap
  2559. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2560.     zfs snap boot/ubuntu@debootstrap
  2561. fi
  2562.  
  2563. # Bind mount and chroot into new system
  2564. [ ! -e /mnt/zfs/etc/hostid ] && hostid > /mnt/zfs/etc/hostid
  2565. [ ! -e /mnt/zfs/etc/mtab ] && ln -s /proc/mounts /mnt/zfs/etc/mtab
  2566. mount -o bind /proc /mnt/zfs/proc
  2567. mount -o bind /dev /mnt/zfs/dev
  2568. mount -o bind /dev/pts /mnt/zfs/dev/pts
  2569. mount -o bind /sys /mnt/zfs/sys
  2570.  
  2571. # chroot into new system and run Setup.sh
  2572. chroot /mnt/zfs /bin/bash --login -c /root/Setup.sh
  2573. # After exit from Setup.sh in chroot continue from here
  2574.  
  2575. # Grab the Setup.log from the new system and put main ZFS-setup.log into new system
  2576. cp /mnt/zfs/root/Setup.log .
  2577. cp ZFS-setup.log /mnt/zfs/root
  2578.  
  2579. # Also put the Reboot-testing.sh script into the new root, for reference
  2580. cp Reboot-testing.sh /mnt/zfs/root
  2581.  
  2582. [ "ZZ${UEFI}" = "ZZy" ] && umount /mnt/zfs/boot/efi
  2583. umount /mnt/zfs/sys
  2584. umount /mnt/zfs/dev/pts
  2585. # Sometime binfmt_misc is there
  2586. umount /mnt/zfs/proc/sys/fs/binfmt_misc
  2587. umount /mnt/zfs/proc
  2588. umount /mnt/zfs/dev
  2589.  
  2590. if [ "ZZ${LUKS}" = "ZZy" ]; then
  2591.     echo "# ***************************************************************************************"
  2592.     echo "#"
  2593.     echo "#  Do not forget to save (and encrypt) the LUKS header backup files"
  2594.     echo "#"
  2595.     for LUKSBACKUP in headers/LUKS-header-backup* ; do
  2596.         echo "#  ${LUKSBACKUP}"
  2597.         cp ${LUKSBACKUP} /mnt/zfs/root/headers
  2598.     done
  2599.     chmod -R 700 /mnt/zfs/root/headers
  2600.     echo "#"
  2601.     echo "# ***************************************************************************************"
  2602.  
  2603.     zpool export boot
  2604. fi
  2605. zpool export ${POOLNAME}
  2606.  
  2607. exit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement