Introducing pibootctl

Mon 27 April 2020
by Dave Jones

For the last few months I’ve been working on a little tool called pibootctl. The hope was to include that in the Focal release, but it couldn’t quite make the cut while so much work was going on with the boot sequence. Still, it’s available from a PPA (ppa:waveform/pibootctl) now for those that wish to try it out, and the documentation is online.

This is the first in a short series of posts explaining some of the background behind the tool, and what its future (hopefully!) is.

So what is it?

It’s a command line tool for managing the Pi’s boot configuration.

So what is it?

It’s a utility for saving, restoring, and editing the various text files on the boot partition.

So what is it?

It’s a less friendly raspi-config … which doesn’t do networking either.

Only Joking!

Well, sort of. To be clear: it’s not intended to be a replacement for the excellent raspi-config tool, however I do intend it to form part of the underlying kit for something vaguely similar.

Why?!

Or more precisely “why not just use or port raspi-config?”. I’ve been asked this pretty frequently so it’s probably best to have somewhere I can point to with all my arguments in a row, so here goes …

Firstly, let’s be clear: raspi-confgi is great. It does exactly what it says on the tin in a friendly, user-accessible way, and Ubuntu certainly needs it, or something very much like it. So let’s begin with why we can’t “just use it”:

  • Ubuntu Server is pretty tightly wedded to netplan for its networking configuration. Whether that’s via the subiquity installer on regular server images, or via cloud-init on our cloud and Pi images.
  • Raspbian is more traditional in its networking approach, and raspi-config knows nothing about netplan. Now, that’s not to say it won’t work: it will set up your WPA config, but it won’t keep the netplan configuration in sync so the next time you run netplan apply it’s overwritten. Not an ideal user experience.

Well, that doesn’t sound so complex? We could patch raspi-config to affect the netplan configuration instead couldn’t we?

Yes we could, but now we’re carrying a delta to the upstream raspi-config tool. Either someone needs to maintain that delta as raspi-config evolves, or we need to get that delta applied upstream. The former is undesirable, and the latter is highly unlikely to happen (unless Raspbian wants to switch over to using netplan).

Besides, it’s not the only problem to overcome:

  • Ubuntu’s boot sequence on the Pi is in some ways more complex and in some ways simpler than Raspbian’s, but either way it’s pretty different. One notable facet is that our “config.txt” file includes other files by default.
  • Unfortunately, raspi-config doesn’t handle includes in the boot configuration, either for parsing or writing. In the face of includes, it either doesn’t know the state of existing settings (from includes), or will fail to notice if its written settings are overridden in later includes.

Solving this means writing a fairly comprehensive parser for the “config.txt” file (and its includes) and some logic to compare a “desired” configuration to the “effective” configuration after writing changes to determine whether settings have been overridden in later included files.

Funnily enough, that’s exactly what pibootctl does!

Ah ha! Could pibootctl be used by raspi-config to fix these issues? Potentially; I’ve ensured there’s absolutely nothing Ubuntu-specific in the tool, and it’s pure Python so there’s nothing preventing it from running on architectures we don’t support like the Pi Zero, but we’re getting ahead of ourselves.

Let’s finish off the issues with porting raspi-config:

  • Setting up the boot options for desktop or CLI: we don’t include a desktop on our images, so that’s out (or at the very least, becomes conditional).
  • Setting up auto-login and splash-screen. We don’t have those either (on classic, and there’s … difficulties with adding a splash screen that are sufficiently intricate I won’t bore you with them here).
  • VNC. Raspbian includes the extremely slick (but proprietary) Real-VNC, which we don’t have on Ubuntu. Side note: personally, the one feature I’d really like to see ported to one of the open source VNC implementations is dispmanx capture so that things like the camera preview can pass over VNC, as on Real-VNC.
  • Remote GPIO. Nope, we haven’t got pigpio into the archive yet either.
  • Read-only FS via overlay. Again, there’s … intricate issues here.

You get the picture. Even if we did port raspi-config, tweak it to use netplan, and slot in pibootctl to handle the configuration re-writing, we’d still wind up with something inferior. Something the user would fire up and immediately notice several options missing. Something that, even if we included the VNC option, would work quite as well as on Raspbian.

Not an ideal result, and we’d still be carrying a fat delta which would require on-going maintenance every time upstream changed.

Addendum

There’s a flip-side to the above. While there’s several things we’d need to drop from a ported raspi-config, there’s also plenty of stuff raspi-config doesn’t do that we could trivially add given the capabilities of the underlying tools on Ubuntu:

  • With netplan, we could have full Ethernet configuration options, IPv4 and IPv6 settings, and more.
  • We tend to favour non-password SSH configurations; should we not add facilities to import a user’s SSH keys?
  • There’s some facilities of pibootctl (which we’ll be seeing in forthcoming posts) that’d be interesting to include too!

So … how then?

That’s enough argument about why porting raspi-config over to Ubuntu is not as trivial as most think (or in some cases even desirable). But it’s obvious to everyone (even me!) that we do need something user friendly for Pi configuration in Ubuntu.

This is something I’ll be working on this cycle, building on top of the tools we’ve got in Ubuntu. Which brings us (finally!) back to pibootctl. When I was looking at the tools we’ve got to play with for system configuration on Ubuntu, which I could build upon for a raspi-config-esque tool, one major piece of the jigsaw was missing: something to deal with “config.txt”.

Not terribly surprising given it’s entirely specific to the Pi but we did need something to fill that gap. Initially, I’d considered grabbing bits from raspi-config but when I checked it there were a couple of problems:

Firstly, it uses lua for re-writing the configuration. Nothing expressly wrong with that, but lua isn’t in “main” on Ubuntu and anything included by default on our images (as such a raspi-config-esque tool eventually would) is meant to be in “main” (not “universe”).

Moving stuff to main involves a pretty thorough review process and wasn’t something I thought we could realistically do for a full-blown programming language when it was only going to be used for a single thing. That already necessitated re-writing a chunk of raspi-config with something in “main”, most likely python.

It can’t handle configurations using includes, and for better or worse I’d already moved us over to a configuration that used them (in Eoan). Moving back would be a nightmare of detection and manipulation logic in some package’s post-inst scripts (more complex than moving to the split configuration in the first place and I remember how nasty that was). Not to mention, I’m still of the opinion that the split configuration brings certain benefits (though that’s involved enough that it should probably be its own post).

Not now?

It feels like I’ve been wittering on for way too long in this post, so I’m going to stop here, and leave the first play-through for next time! In the meantime, anyone that wants to have a play, go have a look at the PPA or the documentation.