Ubuntu Dual Boot on Dell XPS 15 9570
My main computer is a Dell XPS 15 9570. Hardware spec highlights:
- Intel® Core™ i9-8950HK CPU with 12 threads @ 2.90 GHz (it can cheat so much with the calculations that it can run at up to 4.80 GHz)
- 32 GB DDR4 2666 MHz RAM
- NVIDIA® GeForce® GTX 1050Ti main graphics card with 4 GB GDDR5
- Intel i915 graphics for battery saving
- 1 TB M.2 2280 PCIe SSD
- 15.6" InfinityEdge (real thin borders) non-reflective IPS display @ 1920x1080 pixels
It is a monster of a machine, but of course it suffers from Windows 10 as most machines do when you buy them. It’s OK though, Windows 10 is good for gaming, and for running Citrix to work remote. I enjoy the former, and need the latter every once in a while.
At home I connect to a Dell TB16 docking station with a Dell P2418D display. You’re supposed to just plug in one cable from the docking station, and then you’re good, but even on Windows that is unreliable, useless on Linux, so I have my USB peripherals plugged in via a USB hub that I also need to connect to the laptop when “docking.”
My first choice in operating systems is OpenBSD, but the first hurdle was that the “Killer” wifi does not have an OpenBSD driver. It is easy and cheap to change the wifi card, so I opted for an Intel® 8265 card,
iwm(4) on OpenBSD, and at least that worked. Still, the graphics performance was atrocious, and suspend/resume didn’t work, it just sucked.
So I gave up and went the Linux route, and settled on Ubuntu. It’s the boring choice, in a good way. Like buying a Mac or something. It gets the job done, and there’s plenty of Ubuntu specific hits on your favourite search engine when you need to solve a problem.
First step was making a clean Windows 10 install. I downloaded a fresh image from Microsoft and wrote it to a USB stick. You need to do that with the tool they make available, you can’t just dd(1) it to the USB stick like with all other installation ISOs. I know, because I tried, and it sucked.
I gave Windows 10 200 GB at the start of the disk, and let the installer do its thing. It is real easy, and on this particular machine everything just works, Microsoft has done a great job with their installer. I will not bore neither you, nor yours truly, with the details of it, there are plenty of installation instructions you can follow if you need it.
After you have installed Windows and turned BitLocker on, make sure you have your BitLocker recovery key ready, because you will need it later, after ubuntu has fiddled with the EFI partition.
The interesting part is now, of course …
It is easy running Windows 10 with BitLocker disk encryption. It is also easy to run Ubuntu with LUKS disk encryption, but it is not easy to have them co-exist, the Ubuntu installer simply does not let you set it up when you want to dual boot.
But it can be done.
I used another Linux machine to create the installer. You can use Rufus for ISO writing on Windows, but I have no idea how to check SHA256 checksums and all that on Windows. Surely it can be done, but I don’t know how. I just know exactly how on Linux and BSD, so that’s what I do.
SHA256 files, along with the
ubuntu-18.10-desktop-amd64.iso ISO from your closest mirror. I had to rename
SHA256SUMS.asc to make GnuPG 2 want to check it. I was very surprised to find a UNIX native program that care about file name extensions.
% gpg --verify SHA256SUMS.asc gpg: assuming signed data in 'SHA256SUMS' gpg: Signature made Thu 18 Oct 2018 02:16:16 PM CEST gpg: using DSA key 46181433FBB75451 gpg: Good signature from "Ubuntu CD Image Automatic Signing Key <email@example.com>" [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: C598 6B4F 1257 FFA8 6632 CBA7 4618 1433 FBB7 5451 gpg: Signature made Thu 18 Oct 2018 02:16:16 PM CEST gpg: using RSA key D94AA3F0EFE21092 gpg: Good signature from "Ubuntu CD Image Automatic Signing Key (2012) <firstname.lastname@example.org>" [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 8439 38DF 228D 22F7 B374 2BC0 D94A A3F0 EFE2 1092
SHA256SUMS is good, then check the ISO image:
% sha256sum -c SHA256SUMS ubuntu-18.10-desktop-amd64.iso: OK sha256sum: ubuntu-18.10-live-server-amd64.iso: No such file or directory ubuntu-18.10-live-server-amd64.iso: FAILED open or read sha256sum: WARNING: 1 listed file could not be read
Don’t worry about the
ubuntu-18.10-live-server-amd64.iso error, the thing that matters is that
ubuntu-18.10-desktop-amd64.iso is OK, this is what we are now going to write to the USB stick.
lsblk and note the block devices. Then insert the USB stick, and run
lsblk again. Notice the new device? In my case the USB stick shows up as
sda1, but on your machine it may be under another name. Be 100% certain that you have the right device name to write to, lest you accidentally write the image to your boot disk (please don’t do that).
% sudo dd if=ubuntu-18.10-desktop-amd64.iso of=/dev/sda1 bs=4M 476+1 records in 476+1 records out 1999503360 bytes (2.0 GB, 1.9 GiB) copied, 464.829 s, 4.3 MB/s
That’s it. You now have a verified Ubuntu USB stick installer.
Now go and boot from it, tap F12 to get to the choice of boot device. When presented with the menu, choose “Try Ubuntu without installing” so we can then run the installer manually, instead of being forced into it, and more easily open the terminal that we will need later.
The installation of Ubuntu is as easy as Windows 10, DistroTube has a good look at it. Just go through it normally, until you get to the “Installation type” screen, where the option to “Erase disk and install Ubuntu” is selected by default. Don’t do that, you want to keep Windows around. Chose “Something else”, but do not continue yet.
This is where the fun begins, and I make myself a liar, when I said that it is easy. First, open a terminal (click the lower left corner icon, scroll down to find the terminal).
Become root and find out how the disk is laid out.
% sudo -s # Become root. # fdisk -l /dev/nvme0n1 Disk /dev/nvme0n1: 953.9 GiB, 1024209543168 bytes, 2000409264 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: 7277CBA5-F303-4D56-BBAF-5D33787BFA11 Device Start End Sectors Size Type /dev/nvme0n1p1 2048 1023999 1021952 499M Windows recovery environment /dev/nvme0n1p2 1024000 1228799 204800 100M EFI System /dev/nvme0n1p3 1228800 1261567 32768 16M Microsoft reserved /dev/nvme0n1p4 1261568 459718438 458456871 218.6G Microsoft basic data /dev/nvme0n1p5 459718656 461375487 1656832 809M Windows recovery environment
This is the partitions a normal Windows 10 installation has set up. Leave them alone.
Be mindful that the disk in your system may be named differently, and please don’t just cut and paste blindly. Think, carefully, first. Disk partitioning gymnastics aren’t difficult, but the consequences of mistakes can be quite time consuming to recover from. Because you do have a backup of the things you want to keep, right?
Create partitions for Ubuntu with
cfdisk(1), whatever you prefer. Create a
/boot partition of at least 100 MB with “Linux filesystem” type, and set the rest of the disk aside for a big “Linux LVM” partition. Like this:
Device Start End Sectors Size Type /dev/nvme0n1p1 2048 1023999 1021952 499M Windows recovery environment /dev/nvme0n1p2 1024000 1228799 204800 100M EFI System /dev/nvme0n1p3 1228800 1261567 32768 16M Microsoft reserved /dev/nvme0n1p4 1261568 459718438 458456871 218.6G Microsoft basic data /dev/nvme0n1p5 459718656 461375487 1656832 809M Windows recovery environment /dev/nvme0n1p6 461375488 462501887 1126400 550M Linux filesystem /dev/nvme0n1p7 462501888 2000409230 1537907343 733.3G Linux LVM
ext4 filesystem on the
# mkfs.ext4 /dev/nvme0n1p6
Sanitize the soon to be encrypted part of the disk with
dd if=/dev/urandom of=/dev/nvme0n1p7 first. This takes a long while, and can be skipped, but I think it is worth doing this properly.
At this point you can run
cryptsetup benchmark and see what encryption algorithms perform best on your machine. I my case it was the default
aes-xts, with 256 bit key, so I choose that. If you have really secret stuff you need encrypted you may want to choose differently.
Encrypt the partition with
cryptsetup -s 256 -y luksFormat /dev/nvme0n1p7. Read the man page for options to choose other algorithms. You will be prompted for a passphrase, and you will remember this passphrase, as long as you need access to the contents of the disk. This is Unix, there’s no recovery key like for BitLocker.
Next we need to open the encrypted partition, and then get to work and create a Linux LVM volume group with some logical volumes.
cryptsetup luksOpen /dev/nvme0n1p7 crypt pvcreate /dev/mapper/crypt vgcreate cryptvg /dev/mapper/crypt lvcreate -L 40G -n root cryptvg # 40 GB / lvcreate -L 20G -n var cryptvg # 20 GB /var lvcreate -L 33G -n swap cryptvg # 33 GB swap lvcreate -l 100%FREE -n home cryptvg # The rest for /home vgscan --mknodes vgchange -ay mkswap /dev/cryptvg/swap
/home partitions are optional, you can run everything just fine off one
/ partition, but I am a bit old skool and like to have at least a separate
/home, and a separate
/var partition does not hurt either.
Leave the terminal running for now, as you return to the installer.
In partitioning, select “Something else.” and click next. Identify the newly created partitions, choose mount points (you can see the names we gave them, so they’re easily identified) and format them as you want (I use XFS).
Finish the installation, it takes a few minutes, BUT DO NOT REBOOT when it is done. Seriously. The installer has finished, but the system is actually in a non-bootable state, and we need to create e new initrd that can boot the encrypted partition.
Go back to the terminal.
First we need to get the installed system isolated in a
# mount /dev/mapper/cryptvg-root /mnt # mount /dev/nvme0n1p6 /mnt/boot # mount /dev/mapper/cryptvg-var /mnt/var # mount /dev/mapper/cryptvg-home /mnt/home # mount --bind /dev /mnt/dev # chroot /mnt
We’re now in the
# mount -t proc proc /proc # mount -t sysfs sys /sys # mount -t devpts devpts /dev/pts
Find the UUID of the LUKS partition:
# blkid /dev/nvme0n1p7 /dev/nvme0n1p7: _UUID="03b8aeb0-b3ca-4082-a7f7-02e895d46853"_ TYPE="crypto_LUKS" PARTUUID="9ea40832-237c-3149-9101-15ff743ea6a6"
Write the UUID of the LUKS partition in
/etc/crypttab like this:
# <target name> <source device> <key files> <options> crypt UUID=03b8aeb0-b3ca-4082-a7f7-02e895d46853 none luks,tries=0
update-initramfs -k all -c to create a crypto savvy initrd.
Now you can, finally, reboot.
When booting you should be prompted for a passphrase. That one you’re not allowed to forget.
After you have logged in, open a terminal and check that everything is OK with
sudo mount, and swap with
swapon -s, then update everything with
sudo apt -y update && sudo apt -y upgrade. If the update includes a new kernel, reboot for good measure.
/tmp as a
tmpfs in memory (for speed and assured deletion upon shutdown). After mounting
# /tmp is in 2 GB RAM tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,mode=1777,size=2048M 0 0
Make sure you have the
universe repository added:
# add-apt-repository -y universe # apt -y update # apt -y full-upgrade
Get the latest version of the TLP - Linux Advanced Power Management tools:
# add-apt-repository -y ppa:linrunner/tlp # apt -y update # apt -y install thermald tlp tlp-rdw powertop
Fix Sleep/Wake BlueTooth bug by setting
/etc/default/tlp and run
systemctl restart tlp.
Get the, at the moment of writing, latest NVIDIA driver from the main Ubuntu 18.10 repo:
apt -y install nvidia-driver-390
apt -y install ubuntu-restricted-extras va-driver-all vainfo libva2 gstreamer1.0-libav gstreamer1.0-vaapi
For the highest quality audio, which may impact battery life a bit: In
/etc/pulse/daemon.conf uncomment and set the following lines:
daemonize = no high-priority = yes realtime-priority = 9 resample-method = soxr-vhq enable-lfe-remixing = yes flat-volumes = no rlimit-rtprio = 9 default-sample-format = float32le default-sample-rate = 48000 alternate-sample-rate = 44100 default-sample-channels = 2 default-channel-map = front-left,front-right default-fragments = 2 default-fragment-size-msec = 125 deferred-volume-safety-margin-usec = 1
Get the latest pulseaudio:
# add-apt-repository ppa:eh5/pulseaudio-a2dp # apt-get update # apt-get install libavcodec-dev libldac pulseaudio-module-bluetooth
Get the microcode for the Intel i915 graphics card:
apt -y install intel-microcode
Set options for the i915 module:
# echo "options i915 enable_psr=0 enable_fbc=1 enable_guc=3 disable_power_well=0 fastboot=1" > /etc/modprobe.d/i915.conf
dell-smm-hwmon is in
fgrep dell-smm-hwmon /etc/modules
If not there, add it:
echo dell-smm-hwmon >> /etc/modules and then run
Switch to Intel graphics card, and check that it worked:
# prime-select intel # prime-select query
/etc/default/grub and change
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi_rev_override=1 acpi_osi=Linux nouveau.modeset=0 pcie_aspm=force drm.vblankoffdelay=1 scsi_mod.use_blk_mq=1 nouveau.runpm=0 mem_sleep_default=deep"
Reboot, and check that everything works, suspend, resume, etc.