For a want of Boot, or: Secure Boot sucks, period.
Recently, I decided to level up a little in my game of running Linux on a computer with Windows from the USB by buying a full fledged external SSD instead of simple drives. I am no stranger to carrying an OS in my USB drive, as I'm a huge fan of live medium distros like Puppy Linux, and more recently decided to step things up a notch by carrying a frugal install of Alpine Linux in a USB drive.
This time, however, I decided to go much deeper: instead of a fragile flash drive, I'd be going with a full external drive, complete with all of the bells and whistles of a frugal installation in an internal hard drive - only it'd be booted via USB. I'm talking complete persistence, full disk encryption, full-fledged session management (sleep, hibernation, etc), and everything that goes together with your standard PC usage.
Except for one detail: the moment the machine power downs and I unplug the USB drive, it would transparently fall back to the internal Windows-run internal Hard Disk. Or the converse: hibernate on internal, wake up on external - transparently. Two OSes, two mediums, two worlds not intersecting save for the user.
This achievement, call it a computing utopia of sorts, however, turned out to be a real nightmare more akin to a war of attrition. After about a month or so of real efforts, I gave up on the utopia part of the mission and chose to go practical instead.
This post details the frustration of this ultimately pointless endeavor so that hopefully in the future something gets update here or there that solves it and we can try again. Or maybe that others reading this account will learn not to try this at home.
TL;DR: either switch off goddamn Secure Boot every time you want to run Linux from the USB port or run Fedora or Ubuntu from the external disk - but don't expect any support of disk session persistence in the form of hibernation.
The background, or: my utopic vision
The motivation to achieve this utopia was pretty simple: my work issued me a laptop with Windows 10, which I later found to come with an unlocked BIOS (thanks, Hacker mindset!) that allowed me to fiddle with the boot and security settings, and switch off things like Secure Boot.
My hacker instinct immediately honed in on this discovery, and I proceeded to test it out by booting my favorite live media from USB. Much to my expections, after I turned off Secure Boot, Linux booted fine from it. I was able to run LiveCDs from Ubuntu and Puppy Linux on it, and eventually settled for a semi-permanent solution using a frugal installation of Alpine Linux directly on a USB drive.
For a lightweight form of usage for just some light browsing and little session persistence, this turned out to work well. With time, though, going through the process of rebooting, changing BIOS settings, choosing to boot from USB media, and the reverse when going back to Windows every time started to become tiresome. Thus I started to look for something else a little more encompassing.
And then the friction started.
Friction, friction
Given the several differences in requirements from Windows and other Free Software OSes, I had several levels of friction in pursuit of this endeavour. Amongside hibernation problems, hwclock overriding, session persistence, and some Windows session woes, the undisputed biggest problem was no doubt Secure Boot. But let's step through them one by one, at a roughly increasing difficulty scale.
Hardware clock differences
The first and most obvious difference between switching Windows and Linux on boot is the hardware (CMOS) clock. Whereas Linux traditionally sets it up to UTC and calculates from there the current time in your timezone set under /etc/timezone
, Windows sets it up always to local time.
This means that when you switch between the two, depending on how much "knowledge" your distro has of this difference, you will likely suffer some skew between the two (unless you live in the UTC+0 timezone). Making matters worst, oftentimes a daemon like ntpd
will "correct" the damage by sourcing the appropriate time online and then "conveniently" adjusting the CMOS clock to UTC on your behalf without asking. As a result of this, when you end your session on Linux and go back to Windows, your time there will be skewed again and - unless you have administration access - you can't change it! Gotta reboot, go to BIOS and change it from there.
Thankfully, some noob-friendly distros like Fedora or Ubuntu recognize out of the box that the current time of the CMOS clock may be the local and used by an installation of Windows already, and keep it as it is for that matter. Alpine Linux, however, doesn't, so you have to do some ajustments in the OpenRC startup scripts to explicitly state that the CMOS clock is set to local time instead of UTC.
This isn't too bad, though. One file edited and your clock skew problems are solved forever. The other problems, on the other hand...
Who's got them keys?
Enter Secure Boot stage center, the prima donna of Microsoft's "security" concerns. believe if or not but for the longest of times, I didn't actually think it was that much of a problem. Like, sure, it limits severely what OSes you can run. Sure, the ones that work come only with systemd. But even then, the combination of Secure Boot with Linux can work decently enough for a casual computer user.
Enter this very project and now the whole thing is a downright disaster.
I don't want to carry something as large as Ubuntu or Fedora with me in an external-boot drive. I'm already limited by the bandwidth of USB and the disk space of the medium; let me use something lighter and faster, like Alpine. Actually, to hell with the "lighter and faster." Let me use whatever OS I want - this is true freedom! But woe are you if you want to boot some OSes together with Secure Boot.
The big TL;DR here is that you can't boot any OS whose Kernel hasn't been signed with a set of Secure Boot-approved keys, and this excludes the vast majority of Free Software OSes. So, what can you do?
The quick (and in hindsight, best and only) solution is to downright disable secure boot, and then run whatever OS you want in it. But carrying my faith on my project, I naively believed that there was still a way to coexist in this; Windows and Linux booting and working under the same Secure Boot environment.
So if you want to go that way, a few large, enterprise-backed Linux projects paid the piper to end up with a package known as shim
, which essentially allows the Linux OS to boot even under the Secure Boot environment. Unfortunately, this limits the choice to essentially only three distributions: Fedora, OpenSUSE or Ubuntu (and no, Ubuntu derivatives such as Xubuntu or Mint don't use shim
)
I chose Fedora both because of the shim
support and because I was already due to trying it out from a long time. State of the art software? Supporting revolutionary initiatives like like Pipewire or Wayland support? Sign me up, pal.
But then...
Can't hibernate in peace
Even though Fedora was outstanding in terms of usage and software availability, there was one key thing missing: a way to persist sessions across power downs (when I would unplug the external drive and go back to booting Windows). In other words, how do we hibernate the session to disk?
Fedora unfortunately failed me here because together with it's bleeding edge awesomness, it also comes with an interesting quirk: it uses ZRAM for swap instead of disk space. Sure, ZRAM might be more useful in terms of performance, but the problem is that you can't hibernate RAM into itself!
Alas, Fedora is out so this boils down the choice to Ubuntu only. Re-install the OS and we should be good to go. Let's check:
- Swap partition created (only 2GB? Hmmm)
- Swap file can be created and activated to house remainder of the session.
Guess we're good to go at last! So let's do some work, load some stuff into memory, and put the machine to hibernation.
$ loginctl hibernate
hibernate verb not supported.
Ok, this is a systemd machine after all.
$ systemctl hibernate
hibernate verb not supported.
What the hell? Searching around a little, I found a suggestion to use journalctl
instead to inspect the logs. Quirks of systemd, maybe? But let's see it. i
Alas, this is what is going on in the backstage (output of journalctl
), with some emphasis added by me:
Oct 07 18:47:10 zoomerboi su[4167]: pamunix(su-l:session): session opened for user root(uid=0) by vman(uid=1000) Oct 07 18:47:14 zoomerboi kernel: Lockdown: systemd-logind: hibernation is restricted; see man kernellockdown.7
Ok, getting closer. In fact, why not follow the log's advice and RTFM? See, after finding the manual page on kernel lockdown, we at last reach the crux of the matter:
On an EFI-enabled x86 or arm64 machine, lockdown will be automatically enabled if the system boots in EFI Secure Boot mode.
And just like that, everything becomes crystal clear. In other words, when you run with Secure Boot enabled, you can't hibernate to a swap partition that hasn't been signed for it.
Ok.
Hold up.
Calm down.
Deep breath.
Count until 10.
(...)
Nah, fuck it. It's a lost cause.
Conclusion
Fuck Secure Boot.
In short, if you want to use your computer in a happy and joyful manner, do yourself and your computer a favor and disable secure boot, as to never switch it back on again. And then use your computer however you want it. Otherwise, use either Fedora or Ubuntu with this restriction - but don't expect to have any sort of hibernation persistance there.
No ambitious software project is worth my sanity, so for now I'll do what works for me and switch Secure Boot on and off manually depending on what OS I'll use and be happy at that.
Some security, huh. All for a want of boot.
Have you ever dual booted Linux and Windows in a machine that has Secure Boot enabled? How was the experience and the overall usability of it? Let me know in Mastodon!
This post is number #37 of my #100DaysToOffload project. Follow my progress through Mastodon!
Last updated on 10/12/22