This procedure results in a computer that runs both Mac OS X and Ubuntu in a dual-boot configuration, each operating system using full (whole) disk encryption, and with the Ubuntu root file system stored on a ZFS pool encrypted using LUKS. The specific hardware and software versions used to document this procedure are:
-
MacBookPro8,2
-
an external storage device of some kind with a capacity of at least 8 GiB
-
Mac OS X 10.7 (upgraded in place to 10.11)
-
Ubuntu 14.04.3
The following procedure assumes that the target hard drive,
/dev/sda
, is blank.
Connect the Ethernet NIC to the LAN, since WiFi does not work in Ubuntu until after installing the bcmwl-kernel-source package.
Connect an empty USB flash drive or other form of external storage,
/dev/sdb
. Ubuntu will be installed on this device temporarily, as
the installer does not support ZFS pools.
Apple delivers firmware updates solely through the Mac App Store,
making a dual-boot configuration necessary. To begin installing Mac
OS X using
Internet Recovery, power
on the computer while pressing Command-Option-R
. NOTE: The
default version of Mac OS X depends on what Apple originally shipped
with the hardware, e.g., 10.7 for MacBookPro8,2.
Use Disk Utility to create two partitions, a 40-GB partition
formatted as Mac OS Extended (Journaled)
named Macintosh HD
and
the remaining space formatted as Free Space
. This process uses
GPT by default.
Perform a default installation of Mac OS X.
Update Mac OS X after completing the installation, and enable FileVault disk encryption after updating Mac OS X. This happens automatically as part of the upgrade to Mac OS X 10.11 (El Capitan).
To begin installing Ubuntu from CD/DVD, power on the computer while
pressing Option
. From the
Startup Manager, use the
arrow keys to select the optical disc icon labeled Windows
, then
press Enter
. This performs a legacy boot of the Ubuntu installer.
(An EFI boot may be possible but has not been tested.) When prompted,
choose Try Ubuntu
to start the live environment. From the live
environment, run the icon on the desktop labeled Install Ubuntu 14.04.3 LTS
, and perform a default installation of Ubuntu to the
external storage device with the following exceptions:
-
Download updates while installing.
-
Install third-party software. This must be enabled now in order to install non-default device drivers later in this process.
-
When prompted to select an installation type, choose
Something else
. -
Set the device for boot loader installation to the external storage device (e.g.,
/dev/sdb
). Skipping this step might interfere with booting Mac OS X. -
Create a single primary partition on the external storage device, formatted as
Ext4 journaling file system
and mounted at/
. -
Ignore warnings about a missing reserved BIOS boot area or a missing swap partition.
-
When the installer finishes, return to the live environment and open the Terminal app. The remaining steps of the Ubuntu installation process must be completed using the command line.
Install OpenZFS in the live environment by running the following commands:
sudo apt-add-repository --yes ppa:zfs-native/stable
sudo apt-get update
sudo apt-get --yes install ubuntu-zfs
sudo modprobe zfs
Add two partitions, one for the boot volume (contains the kernel and initrd), and the other for the LUKS container that will host the ZFS pool:
sudo gdisk /dev/sda <<EOF
n
+1G
c
4
boot0
n
8e00
c
5
root0
w
y
EOF
Force the kernel to re-read the partition table if necessary:
sudo partprobe
Set up the ZFS pool's encrypted backing volume (this will prompt for a password twice):
sudo cryptsetup --verbose --hash sha512 --cipher aes-xts-plain64 --verify-passphrase --batch-mode luksFormat /dev/disk/by-partlabel/root0
Attach the encrypted volume (use the password specified in the previous step):
sudo ed /etc/crypttab<<EOF
a
cryptroot0 /dev/disk/by-partlabel/root0 none luks
.
w
q
EOF
sudo cryptdisks_start cryptroot0
(The cryptdisks_start
command might break local echo in the
terminal. To fix this problem, either open a new tab or window, or
enter the reset
command.)
Zero the encrypted volume, otherwise decryption errors that would naturally result from reading uninitialized sectors will be treated as hard storage errors by ZFS:
sudo dd if=/dev/zero of=/dev/mapper/cryptroot0 bs=16777216 &
pid=$!
while sudo kill -USR1 ${pid} >/dev/null 2>&1; do
sleep 1
clear
done
Create the ZFS pool.
sudo zpool create -f -O mountpoint=none -o altroot=/mnt -o ashift=12 rpool /dev/mapper/cryptroot0
Create the root file system:
sudo zfs create -o mountpoint=none rpool/ROOT
sudo zfs create -o mountpoint=/ rpool/ROOT/ubuntu
sudo zpool set bootfs=rpool/ROOT/ubuntu rpool
Format and mount the Linux boot volume, and mount the EFI System Partition:
sudo mke2fs -F /dev/disk/by-partlabel/boot0
sudo mkdir /mnt/boot
sudo mount /dev/disk/by-partlabel/boot0 /mnt/boot
sudo mkdir /mnt/boot/efi
sudo mount -t vfat /dev/disk/by-partlabel/EFI\\x20System\\x20Partition /mnt/boot/efi
Mount the Ubuntu installation on the external storage device (e.g.,
/dev/sdb1
) and copy it to the ZFS root file system:
sudo mkdir /target
sudo mount /dev/sdb1 /target
(cd /target && sudo find . -depth -print | sudo cpio -pdmv /mnt)
Snapshot the ZFS root file system, as this simplifies the process of reverting to the original Ubuntu installation in case of any problems:
sudo zfs snapshot rpool/ROOT/ubuntu@`date -u +%Y-%m-%dT%H:%M:%SZ`
Configure the swap volume:
sudo zfs create -V 16G rpool/swap
sudo ed /etc/crypttab<<EOF
a
cryptswap0 /dev/zvol/rpool/swap /dev/urandom swap,cipher=aes-xts-plain64,hash=sha512
.
w
q
EOF
Update the lists of encrypted volumes and file system mount points:
sudo cp /etc/crypttab /mnt/etc/crypttab
sudo rm /mnt/etc/fstab
sudo ed <<EOF
a
/dev/disk/by-partlabel/boot0 /boot ext2 defaults,nosuid,nodev,noexec 0 0
/dev/disk/by-partlabel/EFI\\x20System\\x20Partition /boot/efi vfat ro,fmask=133,noauto 0 0
/dev/mapper/cryptswap0 none swap defaults 0 0
.
w /mnt/etc/fstab
q
EOF
APT requires that the /dev
, /dev/pts
, /proc
, and /sys
pseudo-file systems be mounted:
sudo mount --bind /dev /mnt/dev
sudo mount --bind /dev/pts /mnt/dev/pts
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
Temporarily enable name resolution within the ZFS root:
sudo cp /run/resolvconf/resolv.conf /mnt/run/resolvconf/resolv.conf
At a minimum the ubuntu-zfs, zfs-initramdisk, cryptsetup, and refind packages must be added to---and the grub-pc and intel-microcode packages removed from---the Ubuntu installation in order for the dual-boot process to function:
sudo chroot /mnt add-apt-repository --yes ppa:zfs-native/stable
sudo chroot /mnt add-apt-repository --yes ppa:rodsmith/refind
sudo chroot /mnt apt-get update
sudo chroot /mnt apt-get --yes purge grub-pc intel-microcode
sudo chroot /mnt apt-get --yes install ubuntu-zfs zfs-initramfs
sudo chroot /mnt apt-get --yes install cryptsetup
When prompted install rEFInd to the ESP.
sudo modprobe efivars
sudo chroot /mnt apt-get --yes install refind
Configure rEFInd:
sudo ed <<'EOF'
a
"Boot with standard options" "boot=zfs"
.
w /mnt/boot/refind_linux.conf
q
EOF
Install a version of the initramfs-tools hook script cryptroot
modified to support ZFS pools, and update the initial RAM disk image:
wget https://raw.githubusercontent.com/irtnog/helper-scripts/master/ubuntu-15.04/initramfs-tools/hooks/cryptroot
chmod a+x cryptroot
sudo cp cryptroot /mnt/etc/initramfs-tools/hooks
sudo chroot /mnt dpkg-reconfigure cryptsetup
(Note that the intel-microcode package causes the
update-initramfs
command to fail silently.)
Use the ubuntu-drivers
command to identify which non-default drivers
must be added to the installation in order for the computer to operate
normally:
sudo ubuntu-drivers devices
sudo chroot /mnt apt-get --yes install bcmwl-kernel-source
(Note that these drivers can only be found in the non-main repositories.)
Restore the original DNS resolver configuration, which should
re-create the symbolic link from /etc/resolv.conf
to
../run/resolvconf/resolv.conf
:
sudo dpkg-reconfigure --default-priority resolvconf
Unmount all file systems except for the ZFS pool:
sudo umount /target
sudo umount /mnt/sys
sudo umount /mnt/proc
sudo umount /mnt/dev/pts
sudo umount /mnt/dev
sudo umount /mnt/boot/efi
sudo umount /mnt/boot
Create another snapshot of the ZFS root file system, again to make reverting easier:
sudo zfs snapshot rpool/ROOT/ubuntu@`date -u +%Y-%m-%dT%H:%M:%SZ`
Unmount the ZFS pool:
sudo zpool export rpool
Shut down (or reboot) the Ubuntu live environment.
rEFInd must be blessed before it will replace the Apple Startup Manager; refer to "Installing rEFInd Manually Using Mac OS X" for the particulars (particularly step 8). If the computer was upgraded to Mac OS X 10.11 (El Capitan), make certain to temporarily disable System Integrity Protection (SIP) as part of the activation procedure.
To perform the activation procedure using OS X Recovery, power on the
computer while pressing Command-R
. From the Utilities
menu,
select Terminal
. The remaining steps of the rEFInd activation
process must be completed using the command line.
Disable SIP:
csrutil disable
Mount the EFI System Parition (ESP):
mkdir /Volumes/ESP
mount -t msdos /dev/disk0s1 /Volumes/ESP
Bless rEFInd:
bless --mount /Volumes/ESP --setBoot --file /Volumes/ESP/EFI/BOOT/bootx64.efi
Unmount the ESP:
umount /Volumes/ESP
Re-enable SIP:
csrutil enable
Shut down (or reboot) the OS X Recovery environment.