4

My goal is I want to have a Xubuntu/Ubuntu dual boot, with a catch - I want the disk to be fully encrypted with the dm-crypt (native supplied) whole disk encryption. Now I know, out of the box the ubuntu installer is not going to make this simple for me, and maybe this is not doable, because I am not sure I can ultimately trick the tools into creating the two different initrd configurations for each root filesystem.

So questions:

  1. Has anyone done this before and is there a simple way I am missing to do this?

  2. Given (1) is a negative... a. Should I create separate base ecrypted volumes for each installation (xubuntu/ubuntu) or should I just create 1 encrypted volume and separate install partitions inside it? I am leaning toward the latter to make the process simpler. However I am not sure how the boot loader will handle this.

b. Once I get the first laid in, if I go with 1 encrypted volume, how do I decrypt it and install the second distro (and get the boot loader, initrd, etc updated properly)?

I've asked about the security aspects on Security Stack Exchange.

Tek Tengu
  • 301

4 Answers4

5

I have added a new answer for Ubuntu 22.04 Jammy Jellyfish.

Here is the full account.

I have grouped the steps into phases between reboots:

  1. Preliminaries

  2. Back up your data

  3. Reboot to live-USB for main tasks a. pre-installation: make space on disk b. installation: do manual partitioning c. post-installation: supplement initramfs

  4. Reboot to primary Ubuntu to update grub

  5. Reboot to secondary Ubuntu to add keyfile

  6. Reboot to secondary Ubuntu for finishing touch

  7. Reminders for future installations

  8. About unencrypted /boot

  9. Preliminaries


I have done this on a laptop that has BIOS (for UEFI details, see Ubuntu full disk encryption with encrypted /boot), and encrypted Ubuntu 15.10 already installed (but it could as well be 14.04 LTS). I have repeated the procedure to install Ubuntu 16.10 over earlier 16.04, and then to install 18.04 over earlier 16.10. However, I had to erase the contents of the logical volume that I used for root (/) for Bionic installation. Whenever I left it unerased, either Ubiquity or update-initramfs failed various ways.

Beginning with Cosmic, LUKS2 is the default, and grub only supports LUKS1. Therefore, you cannot begin with an installation of Cosmic or later and expect to be able to add another installation in the same container the way explained here. Instead, you have to do partitioning and create a LUKS1 container manually to begin with.

I will refer to partitions and LVM volumes by the names that were created by the standard Ubuntu installation on the hard disk /dev/sda:

$ lsblk -o NAME,TYPE,FSTYPE,MOUNTPOINT
NAME                    TYPE  FSTYPE      MOUNTPOINT
sda                     disk              
├─sda1                  part  ext2        /boot
├─sda2                  part              
└─sda5                  part  crypto_LUKS 
  └─sda5_crypt          crypt LVM2_member 
    ├─ubuntu--vg-root   lvm   ext4        /
    └─ubuntu--vg-swap_1 lvm   swap        [SWAP]

The LUKS container "sda5_crypt" takes up all space on the logical partition. Shrinking a LUKS container is far too difficult for me; I do not want to destroy the existing Ubuntu installation by attempting it. So instead, I decided to shrink the logical volume "root" to make room for new installations.

The only unencrypted space on the disk therefore is the 255M /boot partition. It would be possible to split this partition, but two equal halves would only hold two kernel versions each, and for me that is not enough. So instead, I decided to place the new /boot directory under the new / root (by not pointing it to any other location). This creates some extra complications, but also leaves room for multiple installations alongside the primary Ubuntu.

All commands in the following are to be executed with sudo rights, so I have skipped the sudo part from all command lines.

Also, I will be talking about "secondary Ubuntu", because I cannot know which Linux you wish to install. Replace "secondary Ubuntu" (and any details specific to Ubiquity) with your choice of flavor.

  1. Back up your data

In addition to your normal backups, you might also want to create a separate copy of the essential settings (such as /etc/crypttab) into a location in which they are easily accessible. That will not be needed if all goes by the plan, but may help you keep your calm.

  1. Reboot to live-USB for main tasks

2.a. pre-installation: make space on disk

Open the LUKS container and activate LVM.

cryptsetup luksOpen /dev/sda5 sda5_crypt
vgscan
vgchange -ay

Shrink the existing root volume.

e2fsck -f /dev/mapper/ubuntu--vg-root
#resize2fs -p /dev/mapper/ubuntu--vg-root 16G
lvreduce -L 16G --resizefs /dev/ubuntu-vg/root
  • The commented-out line is there just in case you don't trust "lvreduce --resizefs" to do the resize bit reliably. Run the "resize2fs" if it makes you feel better.

Add a new root volume. The size is up to you to choose; 16G is just an example.

lvcreate -L 16G -n root2 ubuntu-vg

Create a new swap only if you believe you can get hibernate to work with LUKS. Otherwise, let the two installations share the existing swap space.

lvcreate -L 4G -n swap2 ubuntu-vg

Creating a new data volume seems like an obvious thing to do, but it is not essential for the installation as described here.

lvcreate -l 100%FREE -n data ubuntu-vg

At this point, a newbie might want to reboot without the live-USB and log in to the primary Ubuntu just to see that it still works. If you do, remember to re-open the LUKS container again when you reboot back to the live-USB.

Moreover, be careful to use the right command to open the LUKS container. For example, if you click the icon you see in the Launcher side bar, the container will be opened by the wrong name, and that will cause update-initramfs later on to fail to do its job.

cryptsetup luksOpen /dev/sda5 sda5_crypt

2.b. installation: do manual partitioning

Launch the installer and choose "Something else" for installation type.

  • Point / to your new root volume (/dev/ubuntu-vg/root2).
  • Do not point /boot anywhere.
  • Point swap to your new swap volume if you created one, and otherwise to the old one.
  • Carefully check that no other partition or LVM volume takes part in the installation.
  • Place grub on a logical volume. It does not matter which volume, as the point is to ensure that gub-install fails. First time around, this is the safest option. Later, when you have done this many times, you will know exactly when to choose /dev/sda.

Proceed to the rest of the installation.

  • If the installer asks if mounts should be unmounted, you have done something not mentioned here. Unmount your extra mounts.

At end of installation, choose to continue testing.

  • When the installer reports that grub-install failed, choose to continue without grub.
  • If the popup window gets stuck, just minimize the installer window.

2.c. post-installation: supplement initramfs

Mount the both root volumes.

mkdir /mnt/newroot && mount /dev/mapper/ubuntu--vg-root2 /mnt/newroot
mkdir /mnt/oldroot && mount /dev/mapper/ubuntu--vg-root /mnt/oldroot

Copy the file /etc/crypttab form the old root volume to the new one.

cp -p /mnt/oldroot/etc/crypttab /mnt/newroot/etc/
cat /mnt/newroot/etc/crypttab

If the file you copied already refers to a keyfile, copy also the keyfile and the script that you need to load the key to initrd.img.

cp -p /mnt/oldroot/crypto_keyfile.bin /mnt/newroot/
cp -p /mnt/oldroot/etc/initramfs-tools/hooks/crypto_keyfile /mnt/newroot/etc/initramfs-tools/hooks/
  • On the first time around, the key does not exist yet, and it is better to create it in a later step, because trouble-shooting is easier when changes are not all made at once.

The crucial final step is to load the changes to initrd.img in chroot jail.

for DEV in dev dev/pts sys proc; do mount --bind /$DEV /mnt/newroot/$DEV; done

chroot /mnt/newroot update-initramfs -u

Note reverse order.

for DEV in proc sys dev/pts dev; do umount /mnt/newroot/$DEV; done

  • If you get an error message saying "cryptsetup: WARNING: invalid line in /etc/crypttab", you did not open the LUKS container by the right name.

Tidy up (not 100% necessary, especially if you did not choose persistence when you created your live-USB).

umount /mnt/oldroot && rmdir /mnt/oldroot
umount /mnt/newroot && rmdir /mnt/newroot

You could also try to tidy up by closing the LUKS container, but if you had to minimize the installer window, you will get an error message saying "Device or resource busy". Don't worry, it will be closed in shutdown anyway.

cryptsetup luksClose sda5_crypt
  • The hardest part is now over.
  1. Reboot to primary Ubuntu to update grub

Edit file /etc/default/grub to enable the encrypted /boot to include:

GRUB_ENABLE_CRYPTODISK=y
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda5:sda5_crypt"
  • If you set the value of GRUB_ENABLE_CRYPTODISK to "true" or "1" or anything else, update-grub will complain the value should be "1", but it really has to be "y". This is a known bug.
  • As usual, be careful not to add a newline to the end of the file.

Next, update grub -- mainly to add the newly installed Ubuntu to the menu, but also for the modified settings.

update-grub
  1. Reboot to secondary Ubuntu to add keyfile

When you choose the secondary Ubuntu from grub menu, you will be asked for a password to open the LUKS container. And then you are asked for the same password again. Once you have logged in, we need to fix the problem of having to type in the password twice. We do it by adding a keyfile to the LUKS container.

First, we want to know how many keys the LUKS container already has. A LUKS container can have up to eight keys (numbered 0..7), so we only want to create the keys that we really need.

cryptsetup luksDump /dev/sda5
  • In Wily Werewolf, the container already has three keys. No idea why.

Next, we create the new keyfile.

dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin
chmod a=,u+r /crypto_keyfile.bin

Then we add the new key to the container. The command will as for an existing password, so type in the one you know.

cryptsetup luksAddKey /dev/sda5 /crypto_keyfile.bin

We still need a script that update-initramfs runs to load the key to initrd.img. Place the file in /etc/initramfs-tools/hooks/, and set its protection.

chmod +x /etc/initramfs-tools/hooks/crypto_keyfile

The script only needs to have one line in it:

cp /crypto_keyfile.bin "${DESTDIR}"
  • The name of the script, as well as the name of the keyfile, is up to you to decide.

We also have to add a reference to the key to /etc/crypttab. Before the modification, it looks like this:

sda5_crypt UUID=sda5-uuid-here none luks,discard

After the modification, it should look like this:

sda5_crypt UUID=sda5-uuid-here /crypto_keyfile.bin luks,discard,keyscript=/bin/cat

Now we are finally ready to update the initramfs:

update-initramfs -u
  1. Reboot to secondary Ubuntu for finishing touch

This time, when you choose the secondary Ubuntu from grub menu, you will need to type in the LUKS password only once.

Copy the keyfile to the old root volume for backup.

mkdir /mnt/oldroot
mount /dev/mapper/ububtu--vg-root /mnt/oldroot
cp /crypto_file /mnt/oldroot/

Copy also the grub settings across for backup (from the old root volume to the new). Since the grub menu is shared by both installations, its settings are the same to the both, and the menu can be installed through either installation. So even if you prefer to keep the primary Ubuntu at top of the menu for now, you may need a backup copy of the settings later on.

cp /mnt/oldroot/etc/default/grub /etc/default/
umount /mnt/oldroot
rmdir /mnt/oldroot

You may also want to modify the mount options of the logical volumes (root volumes mainly), so that the two installations do not expose each other's private parts in the GUIs. I could give you a pattern for /etc/fstab, but fortunately Disks makes such a decent job that I don't need to.

Finally, you can begin the normal deployment of the secondary Ubuntu, and also deploy the new data volume in both installations.

  1. Reminders for future installations

  • When overwriting either of the Ubuntu installations, you have to always repeat the same post-install steps, except the creation of a new keyfile for LUKS.
  • The need for the keyfile may disappear in any future release. Actually, I have found no proper documentation for the cryptsetup part of the installation, so I'm afraid anything about it could change. Beware!
  1. About unencrypted /boot

If you choose to split the unencrypted primary partition to make room for the new /boot, you can drop out some of the steps I presented:

  • You do not need a keyfile, so you also do not need the script to load the key into initrd.img, and you do not need to add a reference to the keyfile into /etc/crypttab. Even so, you still need to add the /etc/crypttab file and run update-initramfs in chroot jail in post-installation phase.
  • If the new /boot is not encrypted, you also do not need GRUB_ENABLE_CRYPTODISK in your grub ssettings, and you do not need to set startup parameters to GRUB_CMDLINE_LINUX. Even so, you still need to run update-grub to add the secondary installation to grub menu.
AimoE
  • 81
  • My method worked with Yakkety (16.10), but then I skipped Zesty and Artful. I tried the method today with Bionic (17.04 LTS), and found that running the update-initramfs step in chroot jail fails. I hoe someone could help with the trouble-shooting. – AimoE Jun 18 '18 at 16:02
  • The problem I had with Bionic turned out to not be about the use of chroot after all. I got things working by erasing the logical LVM volume (for /) before installing into it. – AimoE Jun 19 '18 at 17:03
0

Since I wrote my "full account" in 2016, the cryptsetup-initramfs integration has dropped the keyscript method in favor of just pointing out a bunch of keyfiles to include in Initramfs. Plus Grub still has some catching up to do with LUKS2, which Ubuntu installer has deployed. That and much more is captured in detail in Full_Disk_Encryption_Howto_2019, which I now recommend as the "full account". It should be easy enough to extend it to multiple installations on the same disk.

There is one aspect I would like to improve on, though.

Instead of using chroot after the installation to deal with the keyfile, I want to write the keyfile and plant it as a LUKS key already before the installation. In case the installation media was created with persistence, I explicitly write the keyfile into RAM to ensure it will never get written on my thumb drive. With the keyfile already in tow, I can then inject the keyfile and any other encryption enablers into the /target directories during the installation and let the installer run update-initramfs for me in the same way the Wiki article injects the one necessary Grub setting during installation.

Since the basics are already explained in detail in the Help Ubuntu Wiki article, I present my alternative here as a plain command sequence. Preconditions for the whole sequence are: partitioning is done, the both LUKS containers are open, the LVM volume group is activated, and the commands are executed in "sudo -i bash" environment. I tested this with Ubuntu 22.04 (Jammy Jellyfish).

First part deals with the keyfile:

# Recollect keyfile naming scheme:

keydir=/etc/luks keyfile=$keydir/boot_os.keyfile keypat=$keydir/*.keyfile

Write keyfile into RAM:

mkdir -p -m go=,u=rwx $keydir mount -t tmpfs -o size=1m tmpfs $keydir # 5k RAM would be enough (umask go=,u=rx dd if=/dev/urandom of=$keyfile bs=1 count=64 )

Recollect partition paths:

pnum2path() { echo $1$(case $1 in /dev/nvme*) echo p ;; esac)$2 } disk=/dev/nvme0n1 luks1dev=$(pnum2path $disk 1) luks2dev=$(pnum2path $disk 5)

Plant the keyfile as LUKS key in both containers:

cryptsetup luksAddKey $luks1dev $keyfile # type in passphrase cryptsetup luksAddKey $luks2dev $keyfile # type in passphrase

Second part is about injecting encryption enablers to the /target directories.

Preparations come first:

# Define helper routines:

is-ssd(){ [ $(lsblk -dno rota $1) -eq 0 ] # does the disk rotate or not? } wait-write(){ local d=${1%/*} until [ -d $d ]; do sleep 1; done (set -x; echo "$2" >> $1) }

(Due to redirection, the output file path unfortunately is not part of the command that "set -x" will show.)

# Recollect details to include in encryption enablers:

luks1name=LUKS_BOOT luks2name=${$luks2dev##*/}_crypt cryptopt="luks$(is-ssd && echo ,discard)"

Preparations, done, we're ready to install. If you copy&paste the following commands to terminal, do it as a bunch (or write the lines into a file and then run the file). Running the sequence right after answering all of Ubiquity's questions is good enough. However, if you launch the sequence around the time you launch Ubiquity in its own window, you will see that all injections are done by the time you have finished answering (with SSD, the target directories seemed to be in place around the time I was typing in my username and computer name, and all of the injections were done before I had typed in my password the second time).

# During installation, inject encryption enablers into /target directories:

umask go=r,u=rw etc=/target/etc

wait-write $etc/crypttab "# Both /boot and rootfs are encrypted. $luks1name UUID=$(cryptsetup luksUUID $luks1dev) $keyfile $cryptopt $luks2name UUID=$(cryptsetup luksUUID $luks2dev) $keyfile $cryptopt"

(set -x; cp -ar $keydir $etc/) # from RAM to disk

wait-write $etc/default/grub.d/local.cfg "GRUB_ENABLE_CRYPTODISK=y" wait-write $etc/initramfs-tools/initramfs.conf "UMASK=0077" wait-write $etc/cryptsetup-initramfs/conf-hook "KEYFILE_PATTERN="$keypat""

At end of installation, you can immediately accept Ubiquity's offer to reboot!

PS.

My original motivation is not to encrypt /boot. As the sole user of my own laptop, which has only one hard drive, I abhor the idea of ever having to resize LUKS containers that I use; managing space reservations is much simpler if you only have to deal with LVM. Therefore, I want to have only one single LUKS container into which I install 1-3 Ubuntu versions. In this setup, including each /boot in the same container is just a side effect.

In my single-container setup, I don't have to deal with the key file while running Ubuntu from the installation media. During installation, I just inject the two Grub settings I need (the other to enble os-prober), and I inject the /etc/crypttab file with "none" in place of keyfile. After installation, I do have to type in the passphrase twice, but once I have logged in to the newly installed Ubuntu, I can deal with the keyfile at my own leisure. I much prefer that, but Grub being incompatible with LUKS2 now forces me to choose.

AimoE
  • 81
0

Note: I've answered the question as asked, but what you probably want is my last paragraph.

Manual partitioning and dual boot configurations

You'll need to install from the alternate CD for dmcrypt. Select manual partitioning in the installer. If you want two separate encrypted volumes, make them both primary or extended or EFI partitions, and leave enough room for the other volume when you install the first OS. If you want two Linux distributions that share an encrypted volume (but you probably don't want that as I explain below), create one large encrypted volume and create the filesystems for each OS when you install that OS.

Make the encrypted volume an LVM physical volume and create a volume group that spans just that physical volume. If two operating systems share the encrypted volume, they'll also share the volume group: volume groups are a way to manage multiple volumes, and in that configuration there's just the one. Create at least one logical volume for each root filesystem. If the two OSes share the encrypted volume and you don't want to use hibernation, they can share the swap area.

Leave a large enough boot area, which needs to be unencrypted. I recommend at least 1GB (lets you store a rescue CD in an emergency) unless you're heavily constrained on disk space, but 200MB is enough for just one kernel and one alternate kernel.

Having two separate boot partitions is the simplest way to install. Let one distribution control the boot sector, and install the secondary distribution's bootloader on the first sector of its boot partition. Chainload the secondary distribution's bootloader from the primary bootloader.

If you want a single boot partition, install Grub only on one operating system, and share /boot between the two operating systems.

Installing two Linux distributions

Dual boot is painful to use, and not needed in most situations. If you want to run two operating systems, use some form of virtualization. The only use case I can think of for dual boot is when you need to test multiple operating systems on the same expensive hardware (even then, if you can afford it, it's more convenient to have separate machines per OS).

You will need dual boot if you want two separate Linux installations with different passwords. Even then, you may well be able to implement your desired security policy by issuing separate accounts or by creating separate virtualized containers, each with its own root users.

To run Linux on Linux, you may not even need virtualization: you can run programs from another installation with chroot. With Ubuntu or another Debian-based distribution as the master OS, schroot makes this very easy. If you use schroot with a different secondary distribution, you'll probably need to install it separately, so on a separate volume. If the secondary distribution is Debian-based and you never need to boot it, you can install it in a subdirectory with debootstrap. See my schroot guide.

Ubuntu/Xubuntu dual installation

If you want to try out both Ubuntu and Xubuntu, you don't need all this rigmarole. Xubuntu and Ubuntu are the same distribution with different default packages. Install Ubuntu from any variant and make sure both the ubuntu-desktop and xubuntu-desktop packages are installed. Select your preferred environment when you log in, and you will be using either Ubuntu/Unity aka Ubuntu or Ubuntu/XFCE aka Xubuntu.

  • Well I kind of do need a dual boot. What I am actually wanting to do, is create a dual boot of backbox for infosec work and xunbuntu for daily work, with a common /home directory structure. I would like to use one password and whole disk encryption. – Tek Tengu Mar 11 '13 at 00:46
  • Actually your response got me thinking... Would using laying down Xubuntu as a base OS that uses whole disk encryption, then use Xen to bare metal virtualize BackBox be possible. I have never used Xen , and my concern with your suggestion of virtualization is that I give up too much "umph" (processing power) when I virtualize one or the other. However using something like Xen that is native virtualization might be an alternative. Thoughts? Any good pointers on how this could be done with whole disk encryption? – Tek Tengu Mar 12 '13 at 11:03
  • @TekTengu Install both and run one of them in a schroot. There's no special precaution to take at install time except for reserving a logical volume for the other distro when you install the first one (using the single encrypted volume method in my answer). There's no loss of computing power, no inconvenience from dual boot, and the two system installs are wholly separate. – Gilles 'SO- stop being evil' Mar 12 '13 at 17:58
  • The one thing I am still trying to figure out is how to order the installations to get them encrypted. I am thinking set up the partitions, and install the non-encrypted distro, then install the encrypted distro... but my concern is that the encryption process will destroy the previously installed distro. If the other way, how do I get the now encrypted disk un-encrypted, or given your schroot option (above) do I do something like copy or slipsteam the binaries to the partition? – Tek Tengu Mar 13 '13 at 10:00
  • @TekTengu What non-encrypted distro? You can encrypt everything except /boot, and you can have multiple filesystems in logical volumes inside the same encrypted volumes. I don't understand what difficulty you're perceiving. I suggest that you try (just make a basic installation of both distributions), and ask for help if you get stuck somewhere. – Gilles 'SO- stop being evil' Mar 13 '13 at 19:56
  • Well, I have tried and got stuck. Seems like debootstrap has some limitations. First off it depends on preconfigured "scripts" that are for fixed architectures. After looking at them, it leads me to the second issue which is that it also assumes a "http:|ftp:" oriented online repo approach. I am trying to install Xubuntu/Backbox. Because I like Xubuntu as a lighter weight ubuntu desktop (I hate the new gnome) and I need to use backbox from time to time (and backtrack has seemed to get wonky with the last few releases - although I might add it too later). – Tek Tengu Mar 23 '13 at 15:28
  • So I considered hacking the script, but I am not sure that would work either. Wondering if I should just go install Backbox and then grab the whole install and copy it over to my chroot directory? – Tek Tengu Mar 23 '13 at 15:29
0

I have recently installed another Ubuntu alongside the encrypted Ubuntu I already had on my computer. For most of it, I followed the instructions from Multiple Linux Distro Installs on a LUKS Encrypted Harddrive blog entry.

However, I wanted to keep the existing installation intact, but since resizing an existing LUKS container is far too difficult for me, and since I did not want to re-partition the whole disk, I ended up re-organizing instead the LVM volumes inside the existing LUKS container using a live-USB. This decision made me deviate from the instructions a little bit, as I kind of had to place the new /boot folder inside the LUKS container. It turned out to be simpler than expected, though.

So, still logged-in to the live-USB, I launched the installer and chose manual partitioning. I pointed "/" to a new logical volume, and let the installer place the new /boot inside the LUKS container by not pointing it to anywhere else. I also pointed swap to a new logical volume, although I am not sure if hibernate works with LUKS. For grub installation, I chose a target into which the installation surely fails. At end, I chose to "continue testing", and right after that, to continue without grub installation.

Before rebooting after the installation, I copied /etc/crypttab from the first Ubuntu's root volume to the new root volume and ran update-initramfs -u with chroot. This is the crucial step.

After reboot, I logged into the first Ubuntu, edited /etc/default/grub to add GRUB_ENABLE_CRYPTODISK=y and to modify GRUB_CMDLINE_LINUX to contain "cryptdevice=/dev/sda5:sda5_crypt", ran update-grub and rebooted.

After reboot, once I had the new installation up and running, I added a key file to avoid having to type in the LUKS password twice at startup (because /boot is now encrypted). To add the keyfile, I followed nearly identical instructions from several sources. I believe Pavel Kogan's "Linux Mint encryption" blog entry must be the original source.

It all turned out to be much simpler than I had anticipated, although I did have to get over some idiotic obstacles on they way (such as the bug "value of GRUB_ENABLE_CRYPTODISK: util/grub-install.c instructs '1' but util/config.c expects 'y'").

AimoE
  • 81