Current State of Surface-Series Devices
Yes, now Ubuntu 22.04 also supported! Which means you can install Linux on the Surface devices and even in the latest surface book 2 with the NVIDIA 1050/1060! This guide will go step by step on how you can install Ubuntu 22.04 with LUKS (encrypted) alongside Windows 10! 🙂
Of course although most of the things work, some features are still under development. The procedure is pretty simple, even if you choose to encrypt the hard disk!
The showcase!
Here is Ubuntu 22.04 running on the new Surface Book 2. Since I use it as a portable workstation, the Surface is running the Yolo classifier (CUDA, cudnn) in ROS – all in a docker container – while playing a 1440p video on youtube! 🙂
Yolo(CUDA)&ROS in docker + 1440p Youtube
Make space for Ubuntu – shrink disk
Go to Disk Manager and right-click on the disk and choose Shrink
Windows 10 Disk Manager
If you don’t have much space, you’ll have to follow these instructions to use some of the swap space.
Prepare Ubuntu Live USB
- To create a Live USB in Windows, follow these instructions.
- For any linux environment just run:
sudo dd bs=4M if=ubuntu-22.04.2-desktop-amd64.iso of=/dev/sdxxx conv=fdatasync
where /dev/sdxxx points to the USB drive.
(Optional): Disable Secure Boot and Bitlocker
Well, although you should be fine with the Secure Boot enabled, it saves a lot of headaches if you disable it! Trust me! 🙂
- Here is how to disable Secure Boot. Once here perform also Step 4! Change boot-order to boot from USB.
- Here is how to disable Bitlocker.
Change boot-order to boot from USB
- Make sure the Surface Pro device is turned off.
- Attach a bootable USB storage device.
- Hold the volume-down button.
- Press and release the power button.
- When the Surface logo appears, release the volume-down button.
- Go to “Boot Configuration” and move the USB to the top of the list.
- Reboot
Surface UEFI Configuration Screen
Install Ubuntu on LUKS (using LVM)
Choose “Try Ubuntu”
Just boot into Live Ubuntu.
Create two new partitions
Start “gparted” and create two new partitions:
- The “boot” partition, 1GB and formatted as ext3. In this example: /dev/nvme0n1p5
- The LVM partition, which will host the rest, unformatted. In this example: /dev/nvme0n1p6
Create the LUKS container
Now we are going to encrypt the partition /dev/nvme0n1p6 . Run the following
sudo cryptsetup luksFormat /dev/nvme0n1p6
sudo cryptsetup luksOpen /dev/nvme0n1p6 CryptDisk
Create the LVM physical volume
We are going to a create volume group and three logical volumes. These will serve as root, home and swap. The space you allocate for each logical volume is up to you. Most of the space should go to home and remember that if you want to use hibernation, swap should be at least the amount of physical RAM.
sudo pvcreate /dev/mapper/CryptDisk && \
sudo vgcreate vg /dev/mapper/CryptDisk && \
sudo lvcreate -n root -L 150g vg && \
sudo lvcreate -n home -L 289g vg && \
sudo lvcreate -n swap -L 16g vg
Create the filesystems
sudo mkfs.ext4 /dev/mapper/vg-root && \
sudo mkfs.ext4 /dev/mapper/vg-home && \
sudo mkswap /dev/mapper/vg-swap
Install Ubuntu
No need to reboot or anything, just use the icon on the Ubuntu’s desktop to start the installation.
Installation type: Something else
At this step of the installation procedure you need to select “Something else” such that we can select the appropriate logical volumes.
Map Logical Volumes
Here you need to map vg-root
, vg-home
and vg-swap
and of course /boot
. An example of vg-home
:
Don’t reboot once finished!
Once the graphical installer is finished, select “continue testing” and open a terminal.
Get the UUID of the LUKS partition
We need to get the UUID of the LUKS partition – /dev/nvme0n1p6 – which are gonna use a lot later. Thus, open a new tab in the terminal and run:
sudo blkid /dev/nvme0n1p6
which gives:
/dev/nvme0n1p6: UUID="eb7c0bb0-b0f6-4e9a-999c-26ac5bd826d8" [etc]
Chroot into newly installed Ubuntu
Before chroot we need to mount the appropriate devices to the appropriate locations in /mnt
:
sudo mount /dev/mapper/vg-root /mnt && \
sudo mount /dev/mapper/vg-home /mnt/home && \
sudo mount /dev/nvme0n1p5 /mnt/boot
sudo mount --bind /dev /mnt/dev && \
sudo chroot /mnt
Now inside chroot
mount -t proc proc /proc && \
mount -t sysfs sys /sys && \
mount -t devpts devpts /dev/pts
Update Initial Ramdisk
Now use the UUID (switch tab and get it) and create the following two files.
First create /etc/crypttab
echo "CryptDisk UUID=eb7c0bb0-b0f6-4e9a-999c-26ac5bd826d8 none luks,retry=1" >> /etc/crypttab
then create /etc/initramfs-tools/conf.d/cryptroot
echo "CRYPTROOT=target=CryptDisk,source=/dev/disk/by-uuid/eb7c0bb0-b0f6-4e9a-999c-26ac5bd826d8" >> /etc/initramfs-tools/conf.d/cryptroot
and update the initial ramdisk:
update-initramfs -k all -c
You might get some firmware warnings, but that’s OK 🙂
Update GRUB
Next we need to update the default configuration of GRUB (/etc/default/grub
):
Find GRUB_CMDLINE_LINUX=""
and change it with:
GRUB_CMDLINE_LINUX="cryptopts=target=CryptDisk,source=/dev/disk/by-uuid/eb7c0bb0-b0f6-4e9a-999c-26ac5bd826d8"
and update grub:
update-grub
You might get some warnings/errors because of the USB stick (sda) but it is nothing to worry about!
Reboot!
Installation finished! Now reboot to the newly installed Ubuntu! Oh some heads up! There is a high chance that your keyboard will not work. No panic! We will fix that later! However you need to be able to unlock the drive, thus go get an external keyboard – just in case!
Install linux-image-surface
kernel
With this patched kernel all your problems (well almost all) will disappear! Thanks jakeday and now qzed!! Let’s begin!
First you need to import the keys we use to sign packages.
wget -qO - https://raw.githubusercontent.com/linux-surface/linux-surface/master/pkg/keys/surface.asc \
| gpg --dearmor | sudo dd of=/etc/apt/trusted.gpg.d/linux-surface.gpg
After this you can add the repository configuration and update APT.
echo "deb [arch=amd64] https://pkg.surfacelinux.com/debian release main" \
| sudo tee /etc/apt/sources.list.d/linux-surface.list
Now you can install the linux-surface kernel and its dependencies.
sudo apt update && \
sudo apt install linux-image-surface linux-headers-surface libwacom-surface iptsd
Post installation
You should install CPU microcode firmware for the latest CPU updates.
sudo apt install intel-microcode
Install libwacom-surface for better stylus and touch support e.g. in Gnome
sudo apt install libwacom-surface
Camera support
Therer is camera support, but keep in mind it is still work in progress. To enable camera support first install the required dependencies:
sudo apt install \
build-essential meson ninja-build pkg-config libgnutls28-dev openssl \
python3-pip python3-yaml python3-ply python3-jinja2 \
qtbase5-dev libqt5core5a libqt5gui5 libqt5widgets5 qttools5-dev-tools \
libtiff-dev libevent-dev libyaml-dev \
gstreamer1.0-tools libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
And now obtain and build libcamera:
git clone https://git.libcamera.org/libcamera/libcamera.git && \
cd libcamera
Configure libcamera minimally for the Surface:
meson build -Dpipelines=uvcvideo,vimc,ipu3 -Dipas=vimc,ipu3 -Dprefix=/usr -Dgstreamer=enabled -Dv4l2=true -Dbuildtype=release && \
ninja -C build && \
sudo ninja -C build install
Ensure your user account has permissions:
sudo usermod -aG video $USER && \
newgrp video
Test with ‘cam’:
cam --list
and running qcam should (all being well) get you a view of the video capture.
qcam
Install NVIDIA Drivers
Not to scare you… NVIDIA drivers work fine! There is however one caveat: When on battery, the performance level of the GPU is restricted currently to zero. This results in a laggy desktop environment – especially if the resolution is configured at 4K. Check this issue report in the jakeday/linux-surface repository. This means that the GPU-frequency is restricted to low values. It seems it is currently a design choice by the contributors of the jakeday kernel in order to optimize the power consumption.
There are two workarounds currently:
- Use 1080p resolution and avoid heavy duty GPU-tasks while on battery
- Don’t use the NVIDIA GPU or dGPU! Use the Intel one and only use the dGPU when needed (optimus + bbswitch)
I followed the second path my self! I use the Intel GPU as the main one, for anything graphical and the NVIDIA to do my CUDA stuff by utilizing Optimus and bbswitch!
Custom resolution
By default – at least in my case – there is only the option: to select 4K as your resolution. For me, that was causing at least 2 issues:
- Overheating
- Some Apps were not designed for 4K like MATLAB
So, to fix this, you only need to add a custom resolution – like 1080p – via xrandr in Ubuntu.