Last active
April 24, 2016 16:41
-
-
Save dasjoe/d12a8061bee56a966359d046a61161c6 to your computer and use it in GitHub Desktop.
A small HOWTO about installing Ubuntu 16.04 LTS on ZFS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Boot Ubuntu 16.04 LTS from a ZFS rpool | |
# | |
# | |
# We boot the remote server to its (Debian or Ubuntu based) rescue mode | |
# then ssh into it with forwarded ports for the VM's SSH and VNC servers | |
# | |
# Shell here documents that are not passed to a command are used for | |
# documentation and copy and paste sources. | |
# "<<'LOCAL'" denotes commands to be run on the local machine, 'RESCUE' | |
# and 'VM' should be run in the rescue system or the VM, respectively. | |
# | |
# This is for a single-disk pool on /dev/sda, rpools on raidz{1,2,3} or | |
# mirror vdevs are known to work, too. Just pass through the additional | |
# disks to the VM and | |
<<'LOCAL' | |
ssh \ | |
-L 5900:localhost:5900 \ | |
-L 5901:localhost:5901 \ | |
-o "UserKnownHostsFile /dev/null" \ | |
-o "StrictHostKeyChecking no" \ | |
root@91.121.135.62 | |
LOCAL | |
<<'RESCUE' | |
# Get Xubuntu iso | |
wget http://cdimage.ubuntu.com/xubuntu/releases/16.04/release/xubuntu-16.04-desktop-amd64.iso | |
# Start a VM, boot the Xubuntu iso and pass through our local disks | |
# TODO: Redirect the disks you want to use, here: /dev/sda | |
qemu-system-x86_64 \ | |
-cdrom xubuntu-16.04-desktop-amd64.iso \ | |
-boot d \ | |
-drive file=/dev/sda,media=disk \ | |
-nographic \ | |
-vnc 127.0.0.1:0 \ | |
-m 12G \ | |
-cpu host \ | |
-smp 4 \ | |
-enable-kvm \ | |
-redir tcp:5901::22 | |
# For testing the installation it's possible to run qemu without the iso | |
# attached, to start the VM from qemu's console: Ctrl+a c, "cont" | |
# TODO: same as above, you may want to add more disks | |
qemu-system-x86_64 \ | |
-drive file=/dev/sda,media=disk \ | |
-nographic \ | |
-vnc 127.0.0.1:0 \ | |
-m 12G \ | |
-cpu host \ | |
-smp 4 \ | |
-enable-kvm \ | |
-redir tcp:5901::22 \ | |
-S | |
RESCUE | |
<<'VM' | |
# Add password to 'xubuntu' user | |
echo "xubuntu:xubuntu" | chpasswd | |
# Install openssh-server | |
apt-get --quiet update | |
apt-get --yes --quiet install openssh-server | |
VM | |
<<'LOCAL' | |
# copy file over | |
scp \ | |
-P 5901 \ | |
-o "UserKnownHostsFile /dev/null" \ | |
-o "StrictHostKeyChecking no" \ | |
xenial-on-zfs.sh \ | |
xubuntu@localhost: | |
LOCAL | |
<<'VM' | |
# now run this script on the virtual machine | |
sudo bash -x /home/xubuntu/xenial-on-zfs.sh | |
VM | |
# Disable automatic installation of recommended or suggested packages | |
cat > /etc/apt/apt.conf.d/01norecommend <<EOF | |
APT::Install-Recommends "0"; | |
APT::Install-Suggests "0"; | |
EOF | |
# Zap our disks' GPT and MBR structures so we don't accidentally | |
# import an outdated pool during installation of zfsutils-linux | |
# TODO: | |
for disk in /dev/sda | |
do | |
sgdisk -Z "$disk" | |
done | |
# Get required tools, i.e. debootstrap and ZFS userspace tools | |
apt-get --quiet update | |
apt-get --yes --quiet install debootstrap zfsutils-linux | |
# We follow partman-auto's partition size for ESP: | |
# https://bugs.launchpad.net/curtin/+bug/1306164 | |
# | |
# Our disks will get partitioned in this way: | |
# (note the out-of-order partition numbering) | |
# | |
# Protective MBR | |
# LBA 0 | |
# Primary GPT | |
# LBA 1 → 33 | |
# Partition 2 | |
# LBA 34 → 2047 | |
# BIOS boot partition, used for grub | |
# Partition 3 | |
# 1 MiB → 539 MiB | |
# EFI system partition, unused as of now | |
# Partition 1 | |
# 539 MiB → -9 MiB | |
# ZFS pool | |
# Partition 9 | |
# -9 MiB → -1 MiB (= LBA -34) | |
# Reserved partition, here used for ZFS label padding | |
# Secondary GPT | |
# LBA -33 → -1 | |
# | |
# We wipe stale, overlapping ZFS labels from partition 1 if they exist | |
for disk in /dev/sda | |
do | |
sgdisk -a1 -n2:34:2047 -t2:EF02 -c2:grub \ | |
"$disk" | |
sgdisk -n3:1M:+538M -t3:EF00 -c3:EFI \ | |
-n9:-8M:0 -t9:BF07 -c9:reserved \ | |
-n1:0:0 -t1:BF01 -c1:zfs \ | |
"$disk" | |
zpool labelclear -f "$disk"1 | |
done | |
# I am using ashift=9 as my sample server uses an HUS724020ALA640: | |
# HUS724020ALE640 = 2TB, SATA 6Gb/s, 512n, 64MB buffer | |
# H = HGST | |
# U = Ultrastar | |
# S = Standard | |
# 72 = 7200 RPM | |
# 40 = Full capacity, 4TB | |
# 20 = This model's Capacity, 40 = 4TB, 30 = 3TB, 20 = 2TB | |
# A = Generation code | |
# L = 26.1mm z-height | |
# A6 = Interface, SATA 6Gb/s, 512n (E6 = SATA 512e, S6 = SAS 512n) | |
# 4 = 64MB buffer | |
# 0 = No encryption (1 = encryption) | |
# | |
# TODO: If using more than one disk, replace "/dev/sda1" with your own | |
# pool layout, e.g. "mirror /dev/sda1 /dev/sdb1" | |
zpool create \ | |
-o ashift=9 \ | |
-O normalization=formD \ | |
-O atime=off \ | |
-O canmount=off \ | |
-O compression=lz4 \ | |
-O mountpoint=/ \ | |
-O recordsize=1M \ | |
-R /mnt \ | |
rpool \ | |
/dev/sda1 | |
zfs create -o canmount=off -o mountpoint=none rpool/ROOT | |
zfs create -o canmount=noauto -o mountpoint=/ rpool/ROOT/xenial | |
# Turn synchronous requests into async ones for faster installation | |
zfs set sync=disabled rpool | |
zfs mount rpool/ROOT/xenial | |
# TODO: Replace with your closest mirror | |
debootstrap xenial /mnt http://de.archive.ubuntu.com/ubuntu | |
zfs snap rpool/ROOT/xenial@inst-debootstrap | |
# TODO: Replace with real host name | |
echo 'xenial' > /mnt/etc/hostname | |
sed -i '1 a 127.0.1.1 xenial' /mnt/etc/hosts | |
# fix "predictable" device naming, see | |
# https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ | |
ln -s /dev/null /mnt/etc/udev/rules.d/80-net-setup-link.rules | |
# TODO: This is my network configuration, use your own! | |
cat > /mnt/etc/network/interfaces.d/eth0 <<'EOF' | |
auto eth0 | |
iface eth0 inet static | |
address 91.121.135.62 | |
netmask 255.255.255.0 | |
gateway 91.121.135.254 | |
dns-nameservers 8.8.8.8 8.8.4.4 | |
iface eth0 inet6 static | |
address 2001:41d0:1:b63e::1 | |
netmask 64 | |
gateway 2001:41d0:1:b6ff:ff:ff:ff:ff | |
dns-nameservers 2001:4860:4860::8888 2001:4860:4860::8844 | |
EOF | |
# Install a sane sources.list | |
cat > /mnt/etc/apt/sources.list <<'EOF' | |
deb http://de.archive.ubuntu.com/ubuntu xenial main restricted universe multiverse | |
deb http://de.archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse | |
deb http://de.archive.ubuntu.com/ubuntu xenial-updates main restricted universe multiverse | |
deb http://de.archive.ubuntu.com/ubuntu xenial-security main restricted universe multiverse | |
EOF | |
# Disable automatic installation of recommended or suggested packages | |
cat > /mnt/etc/apt/apt.conf.d/01norecommend <<'EOF' | |
APT::Install-Recommends "0"; | |
APT::Install-Suggests "0"; | |
EOF | |
# This is a remote system, so we disable plymouth, enable quiet boot | |
# and do not wait for user input | |
cat > /mnt/etc/default/grub <<'EOF' | |
# If you change this file, run 'update-grub' afterwards to update | |
# /boot/grub/grub.cfg. | |
# For full documentation of the options in this file, see: | |
# info -f grub -n 'Simple configuration' | |
GRUB_DEFAULT=0 | |
#GRUB_HIDDEN_TIMEOUT=0 | |
GRUB_HIDDEN_TIMEOUT_QUIET=true | |
GRUB_TIMEOUT=0 | |
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` | |
GRUB_CMDLINE_LINUX_DEFAULT="noplymouth quiet" | |
GRUB_CMDLINE_LINUX="" | |
# Uncomment to enable BadRAM filtering, modify to suit your needs | |
# This works with Linux (no patch required) and with any kernel that obtains | |
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...) | |
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef" | |
# Uncomment to disable graphical terminal (grub-pc only) | |
GRUB_TERMINAL=console | |
# The resolution used on graphical terminal | |
# note that you can use only modes which your graphic card supports via VBE | |
# you can see them in real GRUB with the command `vbeinfo' | |
#GRUB_GFXMODE=640x480 | |
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux | |
#GRUB_DISABLE_LINUX_UUID=true | |
# Uncomment to disable generation of recovery mode menu entries | |
#GRUB_DISABLE_RECOVERY="true" | |
# Uncomment to get a beep at grub start | |
#GRUB_INIT_TUNE="480 440 1" | |
EOF | |
echo 'LANG="en_US.UTF-8"' > /mnt/etc/default/locale | |
# Fix the chroot's mtab | |
ln -s /proc/mounts /mnt/etc/mtab | |
mount -t devtmpfs /dev /mnt/dev | |
mount -t devpts /dev/pts /mnt/dev/pts | |
mount -t sysfs /sys /mnt/sys | |
mount -t proc /proc /mnt/proc | |
mount -t tmpfs /run /mnt/run | |
# Create temporary resolv.conf by manually setting it up | |
# TODO: feel free to use a different name server, this is Google's | |
mkdir /mnt/run/resolvconf/ | |
echo "nameserver 8.8.8.8" > /mnt/run/resolvconf/resolv.conf | |
# Finish installation in a chroot | |
chroot /mnt /bin/bash -l -- <<'EOF' | |
# Enable bash's debug mode, to show executed commands | |
set -x | |
# TODO: replace with your locale needs | |
for locale in en_US.UTF-8 de_DE.UTF-8; do locale-gen "$locale"; done | |
# TODO: edit timezone | |
# This is a workaround for https://bugs.launchpad.net/ubuntu/+source/tzdata/+bug/1554806 | |
ln -fs /usr/share/zoneinfo/Europe/Berlin /etc/localtime | |
dpkg-reconfigure -f noninteractive tzdata | |
# Update package cache and upgrade everything | |
apt-get --quiet update | |
apt-get --yes --quiet dist-upgrade | |
# Install a minimal but sane set of packages | |
# TODO: edit according your needs | |
apt-get --yes --quiet install \ | |
linux-image-generic \ | |
zfsutils-linux \ | |
zfs-initramfs \ | |
openssh-server \ | |
ssh-import-id \ | |
tmux \ | |
aptitude \ | |
vim | |
# Install grub, force usage of our custom /etc/default/grub | |
DEBIAN_FRONTEND=noninteractive apt-get --yes --quiet \ | |
-o Dpkg::Options::="--force-confdef" \ | |
-o Dpkg::Options::="--force-confold" \ | |
install grub-pc | |
# Actually install grub to disk | |
# TODO: | |
for disk in /dev/sda | |
do grub-install "$disk" | |
done | |
update-grub | |
# Add local user with appropriate groups, import SSH key from Launchpad | |
# TODO: Edit username and password to your own | |
adduser --disabled-password --gecos "Hajo Moeller,,," dasjoe | |
usermod -a -G adm,sudo dasjoe | |
echo "dasjoe:dasjoe" | chpasswd | |
sudo -Hu dasjoe ssh-import-id dasjoe | |
# Disable password login via SSH | |
sed -i 's/^#\{0,1\}\(PasswordAuthentication\) .*/\1 no/g' /etc/ssh/sshd_config | |
exit | |
EOF | |
# Prepare zpool for export, unmount /run, /proc, /sys, /dev/pts and /dev | |
umount /mnt/run | |
umount /mnt/proc | |
umount /mnt/sys | |
umount /mnt/dev/pts | |
umount /mnt/dev | |
umount /mnt | |
# Reset synchronous behaviour to ZFS defaults | |
zfs inherit sync rpool | |
zfs snap rpool/ROOT/xenial@inst-done | |
zpool export rpool | |
<<'FIXME' | |
Stuff left TODO: | |
- encryption (+ dropbear?) | |
- cpu ondemand | |
- EFI | |
- grub-mkpasswd-pbkdf2 | |
FIXME |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment