Skip to content

Instantly share code, notes, and snippets.

@jclec
Created January 24, 2025 02:36
Show Gist options
  • Select an option

  • Save jclec/e56aec0a0e02541685bf14404aef3a98 to your computer and use it in GitHub Desktop.

Select an option

Save jclec/e56aec0a0e02541685bf14404aef3a98 to your computer and use it in GitHub Desktop.
Dual boot windows + popOS on same drive with disk encryption

This guide uses windows 11 and popOS 22.04, but windows 10 and other popOS versions should also work. We assume that you already know how to install windows and flash popOS on a USB; this guide mainly covers the popOS and dual boot configuration parts.

Much of this guide is adapted from these two: https://ostechnix.com/dual-boot-windows-and-pop-os/ https://blog.stefandroid.com/2023/02/04/encrypted-disk-pop-os-install.html

1. With a fresh disk, install windows first (skip to next step if already installed)

Recommended to boot into a USB with windows ISO pre-installed, use windows' media creation tool for flashing the USB

Not strictly necessary but to make things easier, make sure the windows boot partition is the first one on the drive

There are plenty of tutorials on this and setting up disk encryption with BitLocker, so we'll skip over this part

2. Shrink windows partition to create empty space after for popOS

Recommended to have at least 128 GB, but the minimum is 16 GB to run popOS

You can use windows' disk management tool

3. Flash a USB with the popOS ISO and boot into it (the 1st partition).

You can use the same USB as before if you don't mind overwriting it. I used Popsicle USB Flasher for installing the ISO

4. Setup popOS partitions

a. Creating the partitions

Boot into the popOS USB and follow the installation wizard instructions up to the Install page.

install_page

Select Custom (Advanced) for partitioning, press the Modify Partitions... button to open GParted, select the target disk, and select the newly unallocated space, and create the following partitions in this order (unformatted):

  • /boot: 1 GiB (1024 MiB)
  • / (root): remaining space minus swap space
  • swap: 4 GiB (use a reasonable amount depending on your RAM)

Don't close GParted yet so you can easily refresh devices after the following steps.

b. Encrypting the non-swap partitions

Since popOS' custom installation doesn't offer disk encryption, we configure it manually here. Note that the boot partition should not be encrypted.

The commands we'll be using next require elevated privileges, so avoid typing sudo every time by opening terminal and entering an interactive sudo session:

sudo -i

Verify that the new partitions exist:

fdisk -l

In my case, they are on /dev/sda3, /dev/sda4, and /dev/sda5 (3rd, 4th, and 5th partitions on /dev/sda disk). We want to encrypt the root and swap partitions (NOT boot) so use those (/dev/sda4 and /dev/sda5) as <target device> in the following steps. You should replace <target device> with whatever your partition location is

Wipe each new partition of any residual filesystems to avoid collisions, especially if they have been used for an OS before:

wipefs -a <target device>
  • use -n flag to preview the actions taken without actually wiping

For each non-swap partition, format it with LUKS and initialize it for use by LVM (logical volume manager, i.e. device mapper) (here I am using device /dev/sda4 so I use crypt_sda4 as the container mapping name). Choose a strong password when prompted by cryptsetup:

cryptsetup luksFormat --type luks2 /dev/sda4
cryptsetup luksOpen /dev/sda4 crypt_sda4
pvcreate /dev/mapper/crypt_sda4

List all LVM physical volumes with pvs and check that it got created correctly:

$ pvs
  PV                     VG Fmt  Attr PSize   PFree
  /dev/mapper/crypt_sda4    lvm2 ---  240.00g 240.00g

Create a new LVM volume group (which I call vg01) for the new physical volume:

vgcreate vg01 /dev/mapper/crypt_sda4

List all LVM volume groups with vgdisplay (you can also use vgs for a shorter output) and check that it got created correctly:

$ vgdisplay
  --- Volume group ---
  VG Name               vg01
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               240.00 GiB
  PE Size               4.00 MiB
  Total PE              61488
  Alloc PE / Size       0 / 0
  Free  PE / Size       61488 / 240.00 GiB
  VG UUID               XXXXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXXXX

Last step is to create the logical volume (which I call lv00). The size has to be specified with the -L option which is 240 GB for this case (see “VG Size” above).

lvcreate -n lv00 -L 240G vg01
  • If you accidentally created a volume with the wrong size, remove it with lvremove /dev/vg01/lv00 and redo this step (with the correct size)

List all logical volumes with lvs and check that it got created correctly:

$ lvs
  LV   VG    Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv00 vg01 -wi-a----- 240.00g

Repeat the process for each non-swap (and non-boot) partition, changing the target device and incrementing the volume numbers by 1

c. Encrypting the swap partition

This process is similar to the previous step, but instead of using cryptsetup which would require us to either enter a password to also decrypt the swap partition every boot or set up automatic decryption with a keyfile, we manually configure it to automatically use a random key on every boot. Note that this method does not support suspend-to-disk (hibernation).

We use the PARTLABEL to reference the partition since it persists even if the partition layout changes (except if the partition itself is deleted), similar to using UUID (see Swap encryption - UUID and LABEL and the warning in the section before it). My swap partition is on /dev/sda5

Wipe any residual filesystems:

wipefs -a /dev/sda5

(Optional) Overwrite with random data:

dd if=/dev/urandom of=/dev/sda5 bs=10M

Once that’s done, verify that the PARTLABEL of the partition is swap :

$ blkid /dev/sda5
/dev/sda5: PARTLABEL="swap" PARTUUID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  • You can also see if it exists in ls /dev/disk/by-partlabel

Add the swap partition to your /etc/crypttab file:

cryptswap  PARTLABEL=swap  /dev/urandom  swap,cipher=aes-xts-plain64,size=512,sector-size=4096
  • The first field is the name of the new mapped device (i.e. /dev/mapper/cryptswap)
  • Second is the target device to encrypt where we refer to by PARTLABEL
  • Third is the keyfile where we use the built-in /dev/urandom/ for a new random key every boot
  • Fourth is for additional options: swap, AES with XTS mode, 512-bit key size, 4096-bit sector size

And then all we have to do is tell fstab to load it (/dev/mapper/cryptswap) by adding this to /etc/fstab:

/dev/mapper/cryptswap  none  swap  defaults  0  0

And we’re done, After we finish the installation and reboot in the next step, you will have an encrypted swap. You can exit the terminal and close GParted now.

5. Installing popOS

Now you’re ready for the installation of Pop_OS! (see official installation guide). Go back to the installation wizard, and select Custom (Advanced) for partitioning. Select the boot partition (/dev/sda3 for me) and use it as Boot (/boot/efi), and select the swap partition (/dev/sda5 for me) and use it as Swap.

Select the root partition (/dev/sda4 for me) and enter the encryption password when prompted. You can leave the device name as cryptdata. Select the logical volume that pops up within the encrypted partition (LVM vg01 for me) as the destination for the OS installation, and use it as Root (/).

  • Note: If you don't see that the root partition is encrypted with LUKS, try refreshing devices by entering GParted with Modify partitions... -> GParted -> Refresh Devices (or press ctrl+R), then close GParted

Finish the installation as usual, and you’re done! Pop_OS! will ask you for your disk password on every boot.

6. Post-installation

Once booted, you can see with mount that the mapped volume /dev/mapper/vg01-lv00 is mounted and encrypted, rather than the /dev/sda4 partition directly:

$ mount | grep /dev/
...
/dev/mapper/vg01-lv00 on / type ext4 (rw,noatime,errors=remount-ro)
...

$ sudo cryptsetup status cryptdata
/dev/mapper/cryptdata is active and is in use.
  type:    LUKS
  cipher:  aes-xts-plain64
  keysize: 512 bits
  key location: keyring
  device:  /dev/sda4
  sector size:  4096
  offset:  32768 sectors
  size:    268402688 sectors
  mode     read/write

You can also check that swap is active and encrypted, notably not on /dev/sda5 but the mapped devices /dev/mapper/cryptswap and /dev/dm-2:

$ swapon --show
NAME       TYPE       SIZE USED PRIO
/dev/dm-2  partition    4G   0B   -2
/dev/zram0 partition 15.6G   0B 1000

$ sudo cryptsetup status cryptswap
/dev/mapper/cryptswap is active and is in use.
  type:    PLAIN
  cipher:  aes-xts-plain64
  keysize: 512 bits
  key location: dm-crypt
  device:  /dev/sda5
  sector size:  512
  offset:  1024 sectors
  size:    8387584 sectors
  mode     read/write

Configure bootloader

Currently the windows and popOS bootloaders are separated. We can configure the computer to use popOS' bootloader (systemd-boot) by default and include windows for a better dual boot experience.

(Optional) Change the wait time before booting to the default OS by adding these lines to /boot/efi/loader/loader.conf. This will make the bootloader wait 5 seconds before automatically booting into the default OS.

timeout 5
entries 1

Use os-prober to get windows' boot manager:

$ sudo apt update
$ sudo apt install os-prober -y
$ sudo os-prober
/dev/sda1@/efi/Microsoft/Boot/bootmgfw.efi:Windows Boot Manager:Windows:efi

In my case it is on /dev/sda1, but use whatever it shows for you.

Mount the windows boot partition:

sudo mount /dev/sda1 /mnt
  • You can see the windows files under /Microsoft from ls /mnt/EFI

Copy the windows boot manager into popOS' boot loader:

sudo cp -ax /mnt/EFI/Microsoft /boot/efi/EFI
  • Note that we technically now have 2 windows boot managers on the drive, but this is fine because we configured the systemd bootloader to only use the copied one. If somehow the copied windows boot manager gets corrupted, we can also go back to the original one as backup.

Now reboot and you should see Windows Boot Manager under Pop!_OS in the systemd boot loader. You can specify a default by selecting an OS and pressing d on your keyboard.

If you are booting into windows without first seeing the systemd bootloader (and having an option to select popOS), then make sure in the BIOS boot menu that popOS is the primary boot drive and try rebooting again.

References:

https://ostechnix.com/dual-boot-windows-and-pop-os/
https://blog.stefandroid.com/2023/02/04/encrypted-disk-pop-os-install.html
https://gitlab.com/cryptsetup/cryptsetup/-/wikis/FrequentlyAskedQuestions
https://wiki.archlinux.org/title/Dm-crypt/Swap_encryption

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment