Skip to content

Instantly share code, notes, and snippets.

@aphor
Last active June 14, 2019 14:46
Show Gist options
  • Save aphor/fd1e548b0ffc9a5fb1886e616ccaeb68 to your computer and use it in GitHub Desktop.
Save aphor/fd1e548b0ffc9a5fb1886e616ccaeb68 to your computer and use it in GitHub Desktop.
Ubuntu 1804 ZFS root install hack
#!/bin/bash
# Starting from the work detailed on
# https://github.com/zfsonlinux/zfs/wiki/Ubuntu-18.04-Root-on-ZFS
ROOTPASSWD='ch4ng3m3P13453'
if [ -z "$HOSTNAME" ]
then
echo env HOSTNAME must be set >&2
exit 1
fi
SD=/dev/sda
POOL="$HOSTNAME"
BPOOL=$POOL-boot
# search for raw disk link for ZFS pool
for DISK in $( find /dev/disk/by-id -type l )
do
if [ "$( stat -L --format='%t:%T' $DISK )" == "$( stat --format='%t:%T' $SD )" ]
then
break
fi
unset DISK
done
apt update
apt install -y zfsutils debootstrap
sgdisk --zap-all $DISK
sgdisk -n2:1M:+512M -t2:EF00 $DISK
sgdisk -n3:0:+512M -t3:BF01 $DISK
sgdisk -n4:0:0 -t4:BF01 $DISK
# links do not appear immediately
udevadm settle --exit-if-exists=$DISK-part4
until [ "$( stat -L --printf=%F $DISK-part4 )" == "block special file" ]
do
sleep 0.25
done
zpool create -o ashift=12 \
-O acltype=posixacl -O canmount=off -O compression=lz4 \
-O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa \
-O mountpoint=/ -R /mnt \
$POOL $DISK-part4
# links do not appear immediately
udevadm settle --exit-if-exists=$DISK-part3
until [ "$( stat -L --printf=%F $DISK-part3 )" == "block special file" ]
do
sleep 0.25
done
zpool create -o ashift=12 -d \
-o feature@async_destroy=enabled \
-o feature@bookmarks=enabled \
-o feature@embedded_data=enabled \
-o feature@empty_bpobj=enabled \
-o feature@enabled_txg=enabled \
-o feature@extensible_dataset=enabled \
-o feature@filesystem_limits=enabled \
-o feature@hole_birth=enabled \
-o feature@large_blocks=enabled \
-o feature@lz4_compress=enabled \
-o feature@spacemap_histogram=enabled \
-o feature@userobj_accounting=enabled \
-O acltype=posixacl -O canmount=off -O compression=lz4 -O devices=off \
-O normalization=formD -O relatime=on -O xattr=sa \
-O mountpoint=/ -R /mnt \
$BPOOL $DISK-part3
zfs create -o canmount=off -o mountpoint=none $POOL/ROOT
zfs create -o canmount=off -o mountpoint=none $BPOOL/BOOT
zfs create -o mountpoint=/ $POOL/ROOT/ubuntu
zfs create -o mountpoint=/boot $BPOOL/BOOT/ubuntu
zfs mount $BPOOL/BOOT/ubuntu
zpool set bootfs=$BPOOL/BOOT/ubuntu $BPOOL
mkdir --mode=755 /mnt/boot/efi
zfs create $POOL/home
zfs create -o mountpoint=/root $POOL/home/root
zfs create -o canmount=off $POOL/var
zfs create -o canmount=off $POOL/var/lib
zfs create $POOL/var/log
zfs create $POOL/var/spool
zfs create -o com.sun:auto-snapshot=false $POOL/var/cache
zfs create -o com.sun:auto-snapshot=false $POOL/var/tmp
chmod 1777 /mnt/var/tmp
zfs create -o com.sun:auto-snapshot=false $POOL/tmp
chmod 1777 /mnt/tmp
zpool get bootfs $BPOOL
echo ========
df -h
echo ========
for etcdir in /mnt/etc /mnt/etc/netplan /mnt/etc/apt
do
[ -d $etcdir ] || mkdir --mode=775 $etcdir
done
echo "$HOSTNAME" > /mnt/etc/hostname
cat > /etc/hosts << END_ETC_HOSTS
127.0.0.1 "$HOSTNAME"
::1 "$HOSTNAME"
END_ETC_HOSTS
cat > /mnt/etc/netplan/01-netcfg.yaml << END_NETCFG
network:
version: 2
ethernets:
$( ip addr|grep UP|grep -v lo:|tr -d :|cut -d' ' -f2|head -1 ):
dhcp4: true
dhcp6: true
END_NETCFG
cat >> /mnt/etc/apt/sources.list < /etc/apt/sources.list
LANG=C TZ='US/Central' debootstrap bionic /mnt
zfs set devices=off $POOL
for mp in dev proc sys
do
[ -d /mnt/$mp ] || mkdir --mode=775 /mnt/$mp
done
mount --rbind /dev /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys /mnt/sys
chroot /mnt /bin/bash -x << END_CHROOTSCRIPT
export ZPOOL_VDEV_NAME_PATH=YES
ln -s /proc/self/mounts /etc/mtab
apt update
locale-gen --purge en_US.UTF-8 && \
echo -e 'LANG="en_US.UTF-8"\nLANGUAGE="en_US:en"\n' > /etc/default/locale
ln -fs /usr/share/zoneinfo/America/Chicago /etc/localtime
dpkg-reconfigure -f noninteractive tzdata
apt install --yes dosfstools
mkdosfs -F 32 -s 1 -n EFI $DISK-part2
[ -d /boot/efi ] && rm -rf /boot/efi/* || mkdir /boot/efi
echo PARTUUID=$(blkid -s PARTUUID -o value \
$DISK-part2) \
/boot/efi vfat nofail,x-systemd.device-timeout=1 0 1 >> /etc/fstab
[ -d /boot/efi ] || mkdir --mode 755 /boot/efi
mount /boot/efi
echo ========
df -h
echo ========
apt install --yes --no-install-recommends linux-image-generic
apt install --yes zfsutils
apt install --yes grub-efi-amd64-signed shim-signed
echo root:"$ROOTPASSWD" | chpasswd
update-initramfs -u -k all
echo 'GRUB_CMDLINE_LINUX="root=ZFS=$POOL/ROOT/ubuntu"' >> /etc/default/grub
update-grub && echo update-grub #OK
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu --recheck --no-floppy --no-rs-codes &&
echo grub-install #OK
find /boot/grub
for try in {1..10}
do
umount /boot/efi && break
echo waiting $try
sleep 0.5
done
END_CHROOTSCRIPT
# disable logrotate compression on compressed zfs log fs
find /mnt/etc/logrotate.d/* -prune| ( while read file;
do
if grep -Eq "(^|[^#y])compress" "$file" ;
then
sed -i -r "s/(^|[^#y])(compress)/\1#\2/" "$file"
fi
done )
zfs unmount $BPOOL/BOOT/ubuntu
zfs set mountpoint=legacy $BPOOL/BOOT/ubuntu
sync;sleep 0.25;sync;sleep 0.25;sync;sleep 0.25
echo $BPOOL/BOOT/ubuntu /boot zfs \
nodev,relatime,x-systemd.requires=zfs-import-bpool.service 0 0 >> /mnt/etc/fstab
zfs set mountpoint=legacy $POOL/var/log
echo $POOL/var/log /var/log zfs nodev,relatime 0 0 >> /mnt/etc/fstab
zfs set mountpoint=legacy $POOL/var/spool
echo $POOL/var/spool /var/spool zfs nodev,relatime 0 0 >> /mnt/etc/fstab
zfs set mountpoint=legacy $POOL/var/tmp
echo $POOL/var/tmp /var/tmp zfs nodev,relatime 0 0 >> /mnt/etc/fstab
zfs set mountpoint=legacy $POOL/tmp
echo $POOL/tmp /tmp zfs nodev,relatime 0 0 >> /mnt/etc/fstab
mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | xargs -i{} umount -lf {}
zfs snapshot $BPOOL/BOOT/ubuntu@preboot
zfs snapshot $POOL/ROOT/ubuntu@install
sync;sleep 0.25;sync;sleep 0.25;sync;sleep 0.25
zpool export -a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment