It's Pi all the way down... - cloud-inithttps://waldorf.waveform.org.uk/2023-08-16T23:05:20+01:00The Ubuntu Desktop2023-08-09T00:00:00+01:002023-08-09T09:31:21+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-09:/2023/the-ubuntu-desktop.html<p class="first last">Comparing the official desktop with the cloud-init baked flavours</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.</p>
<p>In this post, we’ll be comparing the official Ubuntu desktop release with all
the flavours we’ve been baking from <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configurations, on a
Raspberry Pi.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#ubuntu" id="id2">Ubuntu</a></li>
<li><a class="reference internal" href="#sort-it-out" id="id3">Sort it out!</a></li>
<li><a class="reference internal" href="#popping-and-locking" id="id4">Popping and locking</a></li>
<li><a class="reference internal" href="#verdict" id="id5">Verdict</a></li>
</ul>
</div>
<div class="section" id="ubuntu">
<h2><a class="toc-backref" href="#contents">Ubuntu</a></h2>
<p>Finally we come to the comparison with the official desktop. Obviously I don’t
need to include any <tt class="docutils literal"><span class="pre">cloud-init</span></tt> bits here because … you just install the
desktop image on your card and that’s it.</p>
<img alt="A screenshot of the classic Ubuntu GNOME-based desktop. The bar at the left contains (from top to bottom) the quick-launch icons (Firefox, Thunderbird, the file-browser, etc.), the icons of launched applications, and the 9-grid of the start button at the bottom. Across the top of the screen is another bar displaying "Activities" (effectively another start button), the current date and time, and finally the system tray. In the main portion of the screen can be seen Firefox show a Raspberry Pi page, part of an integrated component's PDF datasheet in evince, top running in the terminal, a file-browser in the background, and totem failing to play a video." src="https://waldorf.waveform.org.uk/images/desktops-lunar-ubuntu.png" />
<p>The official desktop has a few other simplicity tricks up its sleeve too: no
need to explicitly select a Wayland-based desktop, you get one by default. The
first-time setup wizard also handles configuring things like the keyboard
layout and initial user without having to deal with <span class="caps">YAML</span>. So … points for simplicity?</p>
<p>The default applications are a mix of the brilliant (the aforementioned
<a class="reference external" href="https://wiki.gnome.org/Apps/Rhythmbox">Rhythmbox</a>) and the … not so brilliant. In the screenshot above you can see
<a class="reference external" href="https://gitlab.gnome.org/GNOME/totem">Totem</a> failing to play anything (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/totem/+bug/1998782"><span class="caps">LP</span>: #1998782</a> is the Ubuntu bug, but the
<a class="reference external" href="https://gitlab.gnome.org/GNOME/totem/-/issues/523">upstream bug</a> has more
details), so it was back to <tt class="docutils literal">sudo apt install vlc</tt>. The incorrect audio
selection bug (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/pipewire/+bug/1993347"><span class="caps">LP</span>: #1993347</a>) also popped up but is trivial as ever to deal with.</p>
<p>Everything else is mostly fine: good terminal, fine web-browser, stuff opens
happily even on unmounted network shares, though (as noted before) dragging
files from an archive to extract them doesn’t work (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/file-roller/+bug/1923033"><span class="caps">LP</span>: #1923033</a>). Though
this is ultimately due to the Wayland transition, it’s notable that it <em>does</em>
work in Kubuntu, even when running Plasma under Wayland.</p>
<p>One other difference worth noting is that on this distribution I stuck with
using the snap version of Firefox because we may as well do a comparison of
stuff “as it ships” here (which we can’t really do with the other flavours).
Despite being a snap, the Wayland support works (once the
<tt class="docutils literal">MOZ_ENABLE_WAYLAND=1</tt> setting is exported), and since <a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/evince/+bug/1794064"><span class="caps">LP</span>: #1974064</a> was
fixed <a class="footnote-reference" href="#redo2" id="id1">[1]</a> opening links from a standalone <span class="caps">PDF</span> reader works too.</p>
<p>Speaking of Wayland, all the desktop animations are generally smooth and don’t
lag. With the exception of the start menu.</p>
<p>Oh dear, it’s rant time …</p>
</div>
<div class="section" id="sort-it-out">
<h2><a class="toc-backref" href="#contents">Sort it out!</a></h2>
<p>The full-screen zoom-out animation is just too large to do smoothly even under
Wayland (sometimes it manages it after a few attempts). However, this doesn’t
bother me too much because, once it’s deigned to appear, I can never find stuff
in it anyway.</p>
<p>Some flavours have a categorical start menu: Lubuntu, Xubuntu, Kubuntu, and
Studio. It’s a bit dated, but it works: find the category you want, scroll
through the alphabetical list, and pick the application you want. Others take a
more smart-phone-y approach and just have a big alphabetical list of everything
installed to scroll through: Budgie, Unity … <span class="caps">GNOME</span>? <span class="caps">GNOME</span> has one big list. But
it’s not alphabetical:</p>
<img alt="A screenshot of the first page of GNOME's application launcher. Below two mini desktops at the top centre, is a large 6x4 grid of application icons filling the rest of the screen. The icons at first glance appear to be in alphabetical order starting with "Additional Drivers, "AisleRiot Solitaire", "Calendar", "GVim", "Videos", but then "Language Support", "Calculator", "LibreOffice", "Document Scanner", and so on. Two dots at the bottom indicate there are two pages of applications, and we are on the first." src="https://waldorf.waveform.org.uk/images/gnome-start-1.png" />
<p>It’s not in most-recently-used order either. I have fired up Videos here, but
not GVim for instance. Maybe something weird like installation order? Let’s
install something and see. I’ve picked <span class="caps">GIMP</span> which, after installation, appears
at the <em>end</em> of the list on the second screen, after all the other apparently
alphabetically arranged items:</p>
<img alt="Another screenshot of GNOME's application launcher, showing the second page. This page is alphabetically ordered left-to-right, top-to-bottom, but for the final entry: the freshly installed "GNU Image Manipulation Program" which appears after "Vim"." src="https://waldorf.waveform.org.uk/images/gnome-start-2.png" />
<p>But, if we logout and login again, our start menu has re-arranged and now <span class="caps">GIMP</span>
is <em>before</em> GVim, in apparently alphabetical order. But no! “Cheese” is now
before “Additional Drivers” although prior to the reboot it came later in the list!</p>
<img alt="Back to the first page of GNOME's application launcher. Once again, a 6x4 grid of large launch icons, but in a completely different order to before. Now the list starts "Videos", "Calculator", "Document Scanner", "Settings", "System Monitor", "Terminal", "Utilities", "Cheese", "Additional Drivers", "AisleRiot Solitaire", "Calendar", "GNU Image Manipulation Program", etc." src="https://waldorf.waveform.org.uk/images/gnome-start-3.png" />
<p>Okay, I give up. I’ve no idea what the order is here. Maybe it’s “whatever you
want it to be”? You can re-order things manually by dragging them around, or
drag them over each other to form groups (such as the pre-grouped “Utilities”).
But this means that if I want a sensible layout (which the default … isn’t), I
have to laboriously drag things around until they’re “just so”. I have to put
work in (something no other flavour has demanded). Or if you just like them
alphabetical then simply … erm … <a class="reference external" href="https://www.omgubuntu.co.uk/2022/01/gnome-shell-alphabetical-app-grid-extension">install an extension</a>?</p>
<p>In essence the starter is a strange mash-up of “smart-phone home screen” and
“smart-phone all-applications list”, made all the more smart-phone-y by
scrolling sideways because … well, just because. The thing is … this isn’t a
bug. This is genuinely <span class="caps">GNOME</span>’s idea of “how a start menu should work”!</p>
<p>The mitigation to this is that most flavours these days, including <span class="caps">GNOME</span> (but
even some which favour a categorised menu like Kubuntu) allow you to <em>search</em>
by just opening the start menu, typing a few letters of what you want, then
hitting Enter when it’s the first in the list. This is how I tend to use the
start menu on <span class="caps">GNOME</span> because it’s the only way it makes any sense. But, for this
purpose I don’t <em>care</em> about the icons, and that in turns means I don’t care
about <em>giant full-screen zooming animations</em> that lag the entire menu.</p>
<p>Okay, rant over.</p>
</div>
<div class="section" id="popping-and-locking">
<h2><a class="toc-backref" href="#contents">Popping and locking</a></h2>
<p>Oh, and the screen-saver? Blanks and locks the screen, but fails to suspend the
monitor. I’ve dug into this before (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1998716"><span class="caps">LP</span>: #1998716</a>) and all I came away with
was a new-found appreciation for how <a class="reference external" href="https://www.jwz.org/xscreensaver/toolkits.html">bloody complicated</a> something as
apparently simple as a screen-saver is, once you begin to understand all that
it does.</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>It’s not lightweight, but it is pretty, reasonably responsive, with a decent
selection of apps, and despite a few Wayland transition issues (like drag and
drop) it’s mostly functional … except for that start menu. Still, it can’t be
<em>that</em> bad as it has been my main desktop for the last few years.</p>
<p>The problem is … now I’ve used Kubuntu …</p>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="redo2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>during the writing of this series in fact — this is another bit
I’ve had to go back and re-write!</td></tr>
</tbody>
</table>
</div>
The Ubuntu Studio2023-08-08T00:00:00+01:002023-08-09T09:26:15+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-08:/2023/the-ubuntu-studio.html<p class="first last">Baking an Ubuntu Studio Lunar desktop with cloud-init</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.
Skip <a class="reference internal" href="#down-here">down here</a> for the configurations used.</p>
<p>In this post, we’ll be looking at creating an Ubuntu Studio desktop with a
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, on a Raspberry Pi.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#ubuntu-studio" id="id2">Ubuntu Studio</a></li>
<li><a class="reference internal" href="#verdict" id="id3">Verdict</a></li>
<li><a class="reference internal" href="#configuration" id="id4">Configuration</a></li>
</ul>
</div>
<div class="section" id="ubuntu-studio">
<h2><a class="toc-backref" href="#contents">Ubuntu Studio</a></h2>
<p>Originally, this was not a flavour I was planning to cover. After all Ubuntu
Studio is intended for multimedia creation which is some of the heaviest-duty
work you can put any computer through. However, I was also aware they’d
recently switched to Plasma (from <span class="caps">KDE</span>) as a basis, and that meant Wayland was
supported. After Kubuntu’s striking performance, I was intrigued to see how (or
if!) it’d work on a Pi.</p>
<p>For Ubuntu Studio, the <tt class="docutils literal">packages</tt> section in <tt class="docutils literal"><span class="pre">user-data</span></tt> contains an
apparent multitude of packages:</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-desktop</span><span class="w"></span>
</span><span id="line-3"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-audio</span><span class="w"></span>
</span><span id="line-4"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-graphics</span><span class="w"></span>
</span><span id="line-5"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-photography</span><span class="w"></span>
</span><span id="line-6"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-video</span><span class="w"></span>
</span><span id="line-7"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-publishing</span><span class="w"></span>
</span><span id="line-8"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-9"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
<p>The various <tt class="docutils literal"><span class="pre">ubuntustudio-*</span></tt> packages <em>other</em> than <tt class="docutils literal"><span class="pre">ubuntustudio-desktop</span></tt>
are all optional depending on what you want to use. For example, if you’re only
interested in audio work, leave out the graphics, photography, video, and
publishing meta-packages. I would recommend leaving out video because doing
video-editing on a Pi is … “optimistic” to say the least. However, one oddity
of Ubuntu Studio is that it does “assume” a certain set of installed packages
in the default quick launcher. If you exclude certain meta-packages you may
find a number of blank “?” icons in the quick launch bar because of “missing”
applications. You can un-pin these items without consequence.</p>
<p>One other note on default applications: Ubuntu Studio typically ships with
<a class="reference external" href="https://freeshow.app/">FreeShow</a> (which seems to be a dead link at the time of writing) from the
corresponding <a class="reference external" href="https://snapcraft.io/freeshow">snap</a>. Unfortunately we can’t
include that here as it’s another snap that’s only built for <tt class="docutils literal">amd64</tt>.</p>
<p>There’s plenty in these meta-packages that won’t work on a Pi even if it will
install without complaint. For instance, <a class="reference external" href="https://obsproject.com/"><span class="caps">OBS</span> Studio</a> and <a class="reference external" href="https://www.blender.org/">Blender</a> both
require a <span class="caps">GPU</span> with OpenGL 3.3 support (the Pi’s only supports up to 2.1). You
can attempt to override this with <tt class="docutils literal">MESA_GL_VERSION_OVERRIDE=3.3</tt> in your
environment, but don’t expect much in the way of performance (and also don’t be
surprised if several things, like the surfaces in the Blender preview, don’t
display at all, assuming you’re patient enough to wait for it to start).</p>
<p>That said, we should talk about the performance because, once again, we’re
dealing with a Plasma desktop running under Wayland (assuming you selected the
Wayland option on the login screen, which I <em>highly</em> recommend). And, once
again, the performance (for a Pi) is great. Despite it being an environment
replete with little <span class="caps">UI</span> animations, they all seem to play smoothly. The
interface never feels laggy in responding to clicks or movements. Sure, there’s
some delay when launching things but that’s not the desktop interface; that’s
the <span class="caps">SD</span> card.</p>
<img alt="A screenshot of the Ubuntu Studio desktop. In contrast to Kubuntu, the application bar is at the top (reminiscent of Xubuntu). Next to the start menu button is a large array of quick-launch icons for myriad applications (Ardour, Krita, GIMP, kdenlive, etc.) and finally at the far right is the system tray. Below the top bar are a variety of Studio's more unique applications: MuseScore showing a few bars of the opening of Scott Joplin's The Entertainer, LMMS showing a (rather bad) recording of a few opening bars of Scott Joplin's The Entertainer, htop running in a terminal, a scribble in Krita that makes XKCD look like high art, and the KDE settings application atop everything showing a summary of the system's hardware." src="https://waldorf.waveform.org.uk/images/desktops-lunar-studio.png" />
<p>In use Ubuntu Studio is a bit different. For starters, it was the only flavour
here to correctly select the <span class="caps">HDMI</span> audio output by default. Perhaps this is
something to do with the rather more complex audio stack? This is no more than
a guess on my part, however.</p>
<p>Studio is <em>by far</em> the largest of the flavours here. With all the meta-packages
included above it weighs in at a positively obese <span class="caps">17GB</span> on the <span class="caps">SD</span> card, so don’t
even think about trying this on anything less than a <span class="caps">32GB</span> card (unless you
leave out some meta-packages). Speaking of storage, the partitions on the <span class="caps">SD</span>
card showed up as removable in the file browser (same as in Kubuntu).</p>
<p>As on Kubuntu, the terminal was the the typically excellent and feature-full
<a class="reference external" href="https://konsole.kde.org/">Konsole</a>, and the file-browser is again <a class="reference external" href="https://apps.kde.org/en-gb/dolphin/">Dolphin</a>. Still, it feels a bit
churlish to look at my usual set of applications for Ubuntu Studio. No-one’s
going to be installing Studio just to <em>play</em> music or fiddle with the terminal;
it’s a flavour for <em>creators</em>. So I scoured the house for all the interesting
gear I could find to plug in and see how things went …</p>
<p>First off, given we’re dealing with a novel display stack (Wayland), how about
trying to colour-calibrate the monitor? I dug out my trusty old <a class="reference external" href="https://github.com/hughski/colorhug2-firmware">ColorHug2</a>
and strapped it to the screen, fired up <a class="reference external" href="https://displaycal.net/">DisplayCAL</a> and got to work. No
issues generating the profile: hardware was recognized, the screen-saver was
suppressed for the duration of calibration, and although the calculations took
a while (it is a Pi), it was ultimately successful at generating a profile.
Unfortunately, I couldn’t get the profile to install at the end of it
(complaints about a timeout, though after a bit of digging I think there’s
something else going on). Nor, for that matter, did the swapped-red-and-blue
test profile appear to work, so there’s something else missing here. Oh well.</p>
<p>What about drawing? I helped myself to the ancient Wacom Intuos 3 tablet
attached to my other half’s Mac Mini, fired up <a class="reference external" href="https://krita.org/en/">Krita</a> and drew some bits that
6 year-old me would’ve been truly proud of. Ahem. Needless to say, the tablet
Just Worked, including all the fun configuration options for optional hot-keys,
pressure response curves and tool switching depending on the pen tip. I can’t
say this is terribly surprising, though, as it’s always worked on every Linux
system I’ve tried it on for the last 10 years or so.</p>
<p>How about music composition? I nicked my daughter’s Yamaha keyboarad, found the
one remaining <span class="caps">USB</span>-B cable in the house (that wasn’t busy serving a <span class="caps">UPS</span>), and
hooked it up as a <span class="caps">MIDI</span> source. After failing to figure out <a class="reference external" href="https://ardour.org/">Ardour</a>, I managed
to rekindle some of my <a class="reference external" href="https://lmms.io/"><span class="caps">LMMS</span></a> skills and, with some awkward fumbling around
the sound output configuration, got it recording from (and playing back
through) the keyboard. My formerly formidable piano skills have sadly
bit-rotted over the last 30 years. But I still managed to record a passable
rendition of the opening of Scott Joplin’s The Entertainer … treble only, at a
positively sedate 45bpm, then the bass line on a separate track, then sped it
all up to 70 to pretend I could still play.</p>
<p>On the publishing side of things I gave the excellent <a class="reference external" href="https://musescore.org/en">MuseScore</a> a whirl,
including the keyboard as <span class="caps">MIDI</span> input. It performed happily and I managed to
crank out a vaguely acceptable score for the first bit of The Entertainer again
<a class="footnote-reference" href="#wysiwyg-music" id="id1">[1]</a>. Printing remotely worked happily, as did scanning (once I’d
configured <a class="reference external" href="http://www.sane-project.org/"><span class="caps">SANE</span></a> to look on the right host for the scanner).</p>
<p>I gave the video editing and rendering bits a brief try, but they were pretty
much as one would expect: basically unusable without much beefier hardware.</p>
<p>Finally, I tried out <a class="reference external" href="https://www.scribus.net/">Scribus</a> as well and was rather surprised to find it
very “laggy” when dragging things out on the canvas. I pondered if it’s one of
the applications currently suffering from Wayland transition issues and ran it
instead with <tt class="docutils literal">QT_QPA_PLATFORM=xcb</tt> and that <em>largely</em> fixed things. Still, I
didn’t dig any further (as I’d already burned far too much time playing with
this flavour).</p>
<p>But now for the <em>burning</em> question: what about the screen-saver?</p>
<p>It managed to lock the screen (no suspend), and then crashed. It didn’t crash
back to the desktop (good marks for security), but also didn’t display a
“here’s how to get out of this” message like Kubuntu. I managed to manually use
the <tt class="docutils literal">loginctl</tt> trick from Kubuntu to figure out an unlock from another
console, but I can imagine an ordinary user resorting to the three-finger
shuffle here. Ouch.</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>This isn’t your regular flavour, and it’s certain overkill for many. But if
you’re the creative type it may well be the flavour for you. Provided your
expectations of the platform are reasonable (this is not the box for
<a class="reference external" href="https://www.blender.org/">Blender</a>, <a class="reference external" href="https://obsproject.com/"><span class="caps">OBS</span> Studio</a>, or <a class="reference external" href="https://kdenlive.org/en/">kdenlive</a>) it’s useable for basic music
creation, composition, writing or art.</p>
<p>Some things aren’t responsive in all circumstances (when drawing with a tablet
you have to be a bit careful of what’s visible vs the complexity of the
brushes), but with a bit of patience and effort it works! Studio also has a
really nice menu detailing where to get further help, from documentation to
community support.</p>
<p>It looks like there’s still some kinks to work out (particularly around the
Wayland transition) but yet again I’m very impressed by a <span class="caps">KDE</span>-based flavour.</p>
</div>
<div class="section" id="configuration">
<span id="down-here"></span><h2><a class="toc-backref" href="#contents">Configuration</a></h2>
<p>For Ubuntu Studio, the configurations I used were as follows. For the boot
configuration, highlighted lines are those changed from the lunar defaults:</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>For the kernel command line, the entire file must consist of a <em>single line of
text</em> so I would suggest simply copying this wholesale:</p>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>For the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, the highlighted lines are those that you
may wish to change after copying the content. As mentioned above, you may wish
to trim the list of meta-packages highlighted:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">studio-pi</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="linenos">11</span>
</span><span id="line-12"><span class="linenos">12</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-13"><span class="hll"><span class="linenos">13</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-14"><span class="linenos">14</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-15"><span class="hll"><span class="linenos">15</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-17"><span class="linenos">17</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-18"><span class="linenos">18</span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span>
</span><span id="line-34"><span class="linenos">34</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-37"><span class="hll"><span class="linenos">37</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span>
</span><span id="line-43"><span class="linenos">43</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span>
</span><span id="line-47"><span class="linenos">47</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-48"><span class="linenos">48</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-desktop</span><span class="w"></span>
</span><span id="line-49"><span class="hll"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-audio</span><span class="w"></span>
</span></span><span id="line-50"><span class="hll"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-graphics</span><span class="w"></span>
</span></span><span id="line-51"><span class="hll"><span class="linenos">51</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-photography</span><span class="w"></span>
</span></span><span id="line-52"><span class="hll"><span class="linenos">52</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-video</span><span class="w"></span>
</span></span><span id="line-53"><span class="hll"><span class="linenos">53</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntustudio-publishing</span><span class="w"></span>
</span></span><span id="line-54"><span class="linenos">54</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-55"><span class="linenos">55</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Finally, the networking configuration. I used Ethernet for my experiments, and
given the number of packages that need installing I’d generally recommend that
too. Please see the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> for important information on adjusting the
network configuration to Network Manager post installation:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos">2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos">3</span><span class="w"> </span><span class="nt">ethernets</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos">4</span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="linenos">5</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-6"><span class="linenos">6</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span></pre></div>
</div>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="wysiwyg-music" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>Hang on, if you’re so gung-ho about hating <a class="reference external" href="https://en.wikipedia.org/wiki/WYSIWYG"><span class="caps">WYSIWYG</span></a>,
shouldn’t you be using <a class="reference external" href="http://lilypond.org/text-input.html">LilyPond</a> here? Yes, but that’s not part of the
Ubuntu Studio audio seed :)</td></tr>
</tbody>
</table>
</div>
The Kubuntu Flavour2023-08-05T00:00:00+01:002023-08-09T09:26:15+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-05:/2023/the-kubuntu-flavour.html<p class="first last">Baking a Kubuntu Lunar desktop with cloud-init</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.
Skip <a class="reference internal" href="#down-here">down here</a> for the configurations used.</p>
<p>In this post, we’ll be looking at creating a Kubuntu desktop with a
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, on a Raspberry Pi.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#kubuntu" id="id3">Kubuntu</a></li>
<li><a class="reference internal" href="#verdict" id="id4">Verdict</a></li>
<li><a class="reference internal" href="#configuration" id="id5">Configuration</a></li>
</ul>
</div>
<div class="section" id="kubuntu">
<h2><a class="toc-backref" href="#contents">Kubuntu</a></h2>
<p>Kubuntu is the <span class="caps">KDE</span>-based spin of Ubuntu. For those unfamiliar, <span class="caps">KDE</span> is the other
“big” desktop player besides <span class="caps">GNOME</span>, and is based on the Qt toolkit. <span class="caps">KDE</span>’s
always had a more “traditional” feel in its desktop (almost staid, some might
say). The start bar (with a classical categorised start menu) goes at the
bottom, followed by the application switcher, and system tray. Applications all
have a reasonably common look and feel, and all applications have every
configuration option you could ever hope for scattered throughout their
numerous pages of preferences.</p>
<p>This is in fairly stark contrast to <span class="caps">GNOME</span> which, of late, has been more
experimental and has pursued a deliberate path of “making it simple”. To put it
another way, if you sat your elderly mother in front of a modern <span class="caps">GNOME</span> system,
it might take them a while to figure out how to get going. But on <span class="caps">KDE</span>, they’d
be up and running right out the gate <a class="footnote-reference" href="#simple" id="id1">[1]</a>.</p>
<img alt="A screenshot of the Kubuntu desktop. The bar at the bottom contains the Kubuntu logo at the far left, showing the opened start menu above it (with categories on the left and applications on the right). Further along the bottom bar are the quick-launch icons, then the icons of open applications, then finally the system tray on the far right. Within the desktop can be seen (from front to back), the media player showing an episode from the BBC's Hitchhikers Guide to the Galaxy TV adaptation (detailing Ford Prefect), the Dolphin file-browser, Firefox showing a page from the OwnCloud website, and in the background a PDF of a Raspberry Pi datasheet." src="https://waldorf.waveform.org.uk/images/desktops-lunar-kubuntu.png" />
<p>The last time I tried Kubuntu on a Pi, it was <em>laughably</em> slow, and I was
expecting no different this time. I could not have been more wrong …</p>
<p>Kubuntu is notably the only other desktop environment here that supports
Wayland out of the box. It defaults to X11, but you can easily select “Desktop
Session: Plasma (Wayland)” from the bottom of the <span class="caps">KDM</span> login page, and this
selection will persist for future logins. Speaking of logins, there’s a
bizarrely long delay before the desktop shows up after login. This appears
peculiar to <span class="caps">KDE</span> but if you put up with it, the wait is worthwhile!</p>
<p>When running under Wayland, the environment is buttery-smooth. All the little
animations from the fade-in of the desktop, to the opening slide of the start
menu proceed without jitters or jerks. Don’t expect any speed up in opening
large applications. This is still a Pi, and I’m running these experiments off
<span class="caps">SD</span> cards which top out at 20Mb/s transfer on a Pi 4. Nonetheless, I was
astonished to find that the desktop I expected to be the heavy-weight laggard
was up there with the best of them in responsiveness!</p>
<p>The bundled applications largely work well. The file browser is the capable
<a class="reference external" href="https://apps.kde.org/en-gb/dolphin/">Dolphin</a> which was happy browsing and opening things from unmounted network
shares, and has a nifty “multiple-selection” feature (look for the “plus” when
hovering over items). One oddity is that, as under Lubuntu, it considered the
partitions on the <span class="caps">SD</span> card “removable” (though it mercifully didn’t offer an
eject button for the root partition). One other thing it notably managed was to
extract files from an archive with drag’n’drop. This has been <a class="reference external" href="https://gitlab.gnome.org/GNOME/file-roller/-/issues/4">broken on
<span class="caps">GNOME</span></a> (and thus Ubuntu, <a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/file-roller/+bug/1923033"><span class="caps">LP</span>: #1923033</a>) for <em>years</em> now.</p>
<p>As before, the default audio output is incorrectly selected, but again that’s a
trivial work-around. Video playback is handled by the <a class="reference external" href="https://apps.kde.org/en-gb/haruna/">Haruna</a> media player.
Unfortunately this wasn’t happy playing things from unmounted network shares
(despite them being accessible from the Open File menu). Otherwise, it proved
one of the more capable bundled players, handling chapter markers and subtitles
with aplomb. The bundled music player is <a class="reference external" href="https://apps.kde.org/en-gb/elisa/">Elisa</a> which is a simple,
attractive, and intuitive affair, but sadly doesn’t support playing (or
indexing) anything other than a mounted file-system.</p>
<p>Firefox worked well, but now we finally come to something I alluded to at the
start. When installed as a snap it doesn’t seem able to use the “full” Wayland
mode (reverting to XWayland protocol instead). This is the reason for
installing the deb, and also the reason for me re-writing a whole pile of stuff
here <a class="footnote-reference" href="#redo1" id="id2">[2]</a>!</p>
<p>The screen-saver works … then sometimes crashes. At this point I was getting
rather used to flakiness in screen-savers but what surprised me was that,
having crashed, it brought up a nice and detailed set of instructions on
securely unlocking the desktop from another terminal. This … seems like an improvement?</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>What a difference from last time!</p>
<p>Great performance (after a slow initial login), combined with <span class="caps">KDE</span>’s legendary
configurability. Some reliability issues still (screen-saver, not-so-removable
storage!), but this is a genuinely useful desktop on a Pi now.</p>
<p>There’s also a ton of nice little <span class="caps">UI</span> tweaks that made it genuinely pleasant to
use for several days. The start menu encapsulates all styles (categorical, one
big list, and searchable), the system tray has myriad capabilities that make it
far more useful than most (e.g. selecting the audio output, or bluetooth
devices straight from the tray widgets without launching other things).</p>
</div>
<div class="section" id="configuration">
<span id="down-here"></span><h2><a class="toc-backref" href="#contents">Configuration</a></h2>
<p>For Kubuntu, the configurations I used were as follows. For the boot
configuration, highlighted lines are those changed from the lunar defaults:</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>For the kernel command line, the entire file must consist of a <em>single line of
text</em> so I would suggest simply copying this wholesale:</p>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>For the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, the highlighted lines are those that you
may wish to change after copying the content:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">kubuntu-pi</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="linenos">11</span>
</span><span id="line-12"><span class="linenos">12</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-13"><span class="hll"><span class="linenos">13</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-14"><span class="linenos">14</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-15"><span class="hll"><span class="linenos">15</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-17"><span class="linenos">17</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-18"><span class="linenos">18</span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span>
</span><span id="line-34"><span class="linenos">34</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-37"><span class="hll"><span class="linenos">37</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span>
</span><span id="line-43"><span class="linenos">43</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span>
</span><span id="line-47"><span class="linenos">47</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-48"><span class="linenos">48</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">kubuntu-desktop</span><span class="w"></span>
</span><span id="line-49"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-50"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Finally, the networking configuration. I used Ethernet for my experiments, and
given the number of packages that need installing I’d generally recommend that
too. Please see the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> for important information on adjusting the
network configuration to Network Manager post installation:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos">2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos">3</span><span class="w"> </span><span class="nt">ethernets</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos">4</span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="linenos">5</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-6"><span class="linenos">6</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span></pre></div>
</div>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="simple" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>I leave it for the reader to judge what this implies about <span class="caps">GNOME</span>’s
drive for simplicity …</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="redo1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>I’d started off this series doing everything “by the book” with
Firefox from a snap, then after discovering that only the deb-based install
supported this, wound up re-doing everything partly to ensure all the
flavours had the best performance I could give them (full Wayland support if
available without too much hacking), and secondly that they were on a level
playing field (all snaps or all debs for Firefox).</td></tr>
</tbody>
</table>
</div>
The Ubuntu Unity Flavour2023-08-04T00:00:00+01:002023-07-31T01:03:05+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-04:/2023/the-ubuntu-unity-flavour.html<p class="first last">Baking an Ubuntu Unity Lunar desktop with cloud-init</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.
Skip <a class="reference internal" href="#down-here">down here</a> for the configurations used.</p>
<p>In this post, we’ll be looking at creating an Ubuntu Unity desktop with a
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, on a Raspberry Pi.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#ubuntu-unity" id="id1">Ubuntu Unity</a></li>
<li><a class="reference internal" href="#verdict" id="id2">Verdict</a></li>
<li><a class="reference internal" href="#configuration" id="id3">Configuration</a></li>
</ul>
</div>
<div class="section" id="ubuntu-unity">
<h2><a class="toc-backref" href="#contents">Ubuntu Unity</a></h2>
<p>A blast from the past! This was one I didn’t manage to test last time, but I’ve
a major soft spot for good ol’ <a class="reference external" href="https://ubuntuunity.org/">Unity</a>, having spent many years with it as my
desktop on the <span class="caps">PC</span> back in the pre-Bionic days. So let’s give it a spin on the Pi!</p>
<p>For those unfamiliar with Unity, it has some quite different ideas of its own:
the start menu and quick launcher are on the left of the screen (rather than
the traditional top or bottom). If I recall correctly (and I’m sure someone
will correct me in the comments if I’m not) this was because most screens have
a wide-screen aspect ratio, so if you’re going to “waste” space with
non-application stuff, better to do it horizontally than vertically (which
sounds pretty reasonable to me).</p>
<p>In later iterations, and indeed in Unity 7 that we’re using here, it also
borrows a few tid-bits from MacOS X: the window icons (minimize, maximize,
close) are on the top left, and application menus appear in the bar at the top
of the window rather than within the application window. Again, I <em>think</em> I’m
right in stating this was (at least partially) in aid of not wasting vertical real-estate.</p>
<img alt="A screenshot of the Ubuntu Unity desktop. The quick-launch icons are on the left of the screen below the Ubuntu icon at the top left. At the very top is the grey bar which switches to the application menu when hovered. It also contains the system tray icons at the top right. Within the desktop can be seen Firefox, behind a file-browser, Rhythmbox, VLC playing an old episode of "Spaced", and htop running in a terminal window." src="https://waldorf.waveform.org.uk/images/desktops-lunar-unity.png" />
<p>The selection of bundled applications was excellent. <a class="reference external" href="https://www.videolan.org/"><span class="caps">VLC</span></a> for video playing,
and <a class="reference external" href="https://wiki.gnome.org/Apps/Rhythmbox">Rhythmbox</a> for music. Couldn’t ask for better. The file browser is
the excellent <a class="reference external" href="https://github.com/linuxmint/nemo">Nemo</a> from the Cinnamon desktop. Everything was generally
reliable and worked … eventually.</p>
<p>Unfortunately, this brings us to the first major issue: performance. As with
all the alternative desktops so far there’s no Wayland support yet, but even
discounting that performance was <em>painfully</em> slow. I did note that, as under
Budgie, <tt class="docutils literal"><span class="pre">cups-browsed</span></tt> was eating 100% of a <span class="caps">CPU</span> core again. But even after
killing that, things still felt very sluggish, especially after the snappy
responses of Lubuntu and Xubuntu.</p>
<p>Integration was also spotty. The menus for <em>most</em> things appeared in the top
bar. But not Firefox (arguably the most important application on the desktop).
One might argue that Firefox doesn’t have a menu bar any-more, that it’s
succumbed to the modern obsession with hiding everything behind a “burger”
button but the menus are still there: hit Alt+F and you’ll see (in fact several
of the menus aren’t available from the “burger” button, which is probably why).</p>
<p>However, the screen-saver? Works! This is the only other flavour to, out of the
box, reliably suspend my monitor and lock the desktop with no crashes (Lubuntu
being the other).</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>I’d <em>really</em> love to recommend Unity. Its interface ideas may be novel and
quite different to most other flavours, but they make a good deal of sense (far
more than <span class="caps">GNOME</span>’s do, to me anyway). However, while the reliability is great,
the performance just isn’t good enough for use on a small platform.</p>
<p>The theme (whether light or dark) made it rather hard to distinguish window
edges of inactive applications. Looking at the screenshot above, can you see
where the file-browser ends, and the music player or the browser begins? There
are also some strange edges to menu corners as if the environment wanted to
draw shadows there, but forgot:</p>
<img alt="A close up screen-grab of an open menu under Ubuntu Unity. The menu itself appears in a shade of grey almost indistinguishable from the white of the web-page beneath it. However, the bottom left and right corners of the menu are shaded distinctly darker, as if intended to blend with some shadow rendered around the whole menu, but which is not present." src="https://waldorf.waveform.org.uk/images/desktops-lunar-unity-menu.png" />
<p>This all gave me an impression that things were not rendering “as intended”. Is
there meant to be a shadow border around windows?</p>
</div>
<div class="section" id="configuration">
<span id="down-here"></span><h2><a class="toc-backref" href="#contents">Configuration</a></h2>
<p>For Ubuntu Unity, the configurations I used were as follows. For the boot
configuration, highlighted lines are those changed from the lunar defaults:</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>For the kernel command line, the entire file must consist of a <em>single line of
text</em> so I would suggest simply copying this wholesale:</p>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>For the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, the highlighted lines are those that you
may wish to change after copying the content:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">unity-pi</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="linenos">11</span>
</span><span id="line-12"><span class="linenos">12</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-13"><span class="hll"><span class="linenos">13</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-14"><span class="linenos">14</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-15"><span class="hll"><span class="linenos">15</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-17"><span class="linenos">17</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-18"><span class="linenos">18</span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span>
</span><span id="line-34"><span class="linenos">34</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-37"><span class="hll"><span class="linenos">37</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span>
</span><span id="line-43"><span class="linenos">43</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span>
</span><span id="line-47"><span class="linenos">47</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-48"><span class="linenos">48</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-unity-desktop</span><span class="w"></span>
</span><span id="line-49"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-50"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Finally, the networking configuration. I used Ethernet for my experiments, and
given the number of packages that need installing I’d generally recommend that
too. Please see the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> for important information on adjusting the
network configuration to Network Manager post installation:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos">2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos">3</span><span class="w"> </span><span class="nt">ethernets</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos">4</span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="linenos">5</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-6"><span class="linenos">6</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span></pre></div>
</div>
</div>
The Ubuntu Budgie Flavour2023-08-03T00:00:00+01:002023-07-31T01:17:42+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-03:/2023/the-ubuntu-budgie-flavour.html<p class="first last">Baking an Ubuntu Budgie for Pi desktop with cloud-init</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.
Skip <a class="reference internal" href="#down-here">down here</a> for the configurations used.</p>
<p>In this post, we’ll be looking at creating an Ubuntu Budgie desktop (with
Pi-specific customizations!) with a <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#ubuntu-budgie" id="id2">Ubuntu Budgie</a></li>
<li><a class="reference internal" href="#verdict" id="id3">Verdict</a></li>
<li><a class="reference internal" href="#configuration" id="id4">Configuration</a></li>
</ul>
</div>
<div class="section" id="ubuntu-budgie">
<h2><a class="toc-backref" href="#contents">Ubuntu Budgie</a></h2>
<p>The Budgie desktop is (was?) based on <span class="caps">GNOME</span> but with a more “traditional”
desktop feel. The Ubuntu Budgie remix is styled with a brief nod towards MacOS
X with a Dock-like launcher (<a class="reference external" href="https://launchpad.net/plank">Plank</a>) centred at the bottom of the screen.
However, that’s as far as the Mac-allusions go. There’s no application menu in
the bar at the top, and the window icons are at the top-right instead of top-left.</p>
<img alt="A screenshot of the Ubuntu Budgie desktop. Under the dark top bar containing the start-menu button, clock, and system tray, a variety of applications are shown including "top" running under the Tilix terminal, The Cult's "Sonic Template" album in the Lollypop music player, an episode of "Hey Duggee" playing in the Parole video player, and Firefox in the background showing a news article. At the bottom center of the screen is the MacOS X Dock-like application showing the icons of all the running applications, and a few others for quick launch." src="https://waldorf.waveform.org.uk/images/desktops-lunar-budgie.png" />
<p>Despite the <span class="caps">GNOME</span> heritage, there’s no Wayland support yet (although a bit of
googling does suggest that it’s a high priority for the next release). On first
login, I did need to select “Budgie Desktop” in the login manager (<span class="caps">GDM</span>) instead
of the “Ubuntu Desktop” default, which was a little odd, but it turned out
there was a reason for that which we’ll come back to later …</p>
<p>The specific package used to install the Ubuntu Budgie remix
(<tt class="docutils literal"><span class="pre">ubuntu-budgie-desktop-raspi</span></tt>) also includes a nice little Pi-specific
customization tool that launches on first login. However, I think some of its
options may be redundant at this point (for instance, when using the “full” <span class="caps">KMS</span>
overlay there’s no need to specify a <span class="caps">GPU</span> memory size, even if you are using a
camera via the newer libcamera stack).</p>
<p>Most of the terminals in the various flavours are much of a muchness; all
support multiple tabs, all have scroll-back, and all are essentially decent at
their job. However, Budgie’s pick for a terminal (<a class="reference external" href="https://gnunn1.github.io/tilix-web/">Tilix</a>) stands out as being
the only <span class="caps">GTK</span>-based terminal to support tiled panes, that I’m aware of
<a class="footnote-reference" href="#tiling" id="id1">[1]</a>. Last time I tried it (in 2020) the terminal (which may or may not
have been Tilix, I can’t recall) crashed pretty reliably, but this time around
it was solid as any of the rest, and a stand-out feature of the environment.</p>
<p>Budgie seems to have a bit of a thing about tiling generally. The desktop’s got
corner tiling by default (useful on a big monitor), but also has some
fascinating shortcuts for ⅖-⅗ tiling, custom (shortcut activated) layouts,
and arrangement of windows in arbitrarily sized grids. On my little monitor, I
don’t really need anything more than side-by-side tiling but I can imagine this
being <em>very</em> handy on <a class="reference external" href="https://waldorf.waveform.org.uk/2023/4k-60hz-on-a-pi.html">large-scale high-<span class="caps">DPI</span> monitors</a>.</p>
<p>Sadly, the reliability of the console wasn’t reflected elsewhere. Things felt a
bit sluggish at times and eventually I figured out <tt class="docutils literal"><span class="pre">cups-browsed</span></tt> was sitting
around eating 100% of one of the <span class="caps">CPU</span> cores. This <em>might</em> be a known issue (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/cups-browsed/+bug/2018504"><span class="caps">LP</span>:
#2018504</a>), but that’s marked “fix released” on Lunar and this was running on
a fully up-to-date system. I’ll need to try and reproduce it to see if that bug
needs more attention.</p>
<p>Video playback also proved tricky to test; Budgie bundles the same default
video player as Xubuntu, <a class="reference external" href="https://docs.xfce.org/apps/parole/start">Parole</a>, but this crashed the Budgie window manager
process on the couple of occasions I tried it (it happily kept on playing the
video, but the desktop behind flickered out of existence and then restarted!).
The bundled Music player is <a class="reference external" href="https://wiki.gnome.org/Apps/Lollypop">Lollypop</a> and, while it seems a capable player,
it didn’t seem to have any support for any of the music sharing protocols
supported on the home server, so I wound up mounting an <span class="caps">NFS</span> share for the
purposes of testing. This worked, but it struggled a bit with the sheer
quantity of albums, eating a good half a gig of <span class="caps">RAM</span> by the time it was done
indexing. The audio output default also needed adjusting (as on the other desktops).</p>
<p>And the screen-saver? Didn’t appear to do anything at all at first (screen
never blanked, no suspend, no lock). This turned out to be <a class="reference external" href="https://discourse.ubuntubudgie.org/t/lock-screen-no-longer-works-after-22-04-upgrade/6194/5">an issue</a>
with <tt class="docutils literal"><span class="pre">gnome-shell-common</span></tt> being installed. With that package purged (and …
<tt class="docutils literal"><span class="pre">ubuntu-budgie-desktop</span></tt> along with it!), the screen-saver managed to lock the
desktop correctly, but still failed to suspend the monitor (same as the
official <span class="caps">GNOME</span> desktop). Interestingly, this also uninstalled the <span class="caps">GDM3</span> login
greeter, and replaced it with the <a class="reference external" href="https://github.com/linuxmint/slick-greeter">slick greeter</a> (familiar to users of
Unity), which resolved having to select “Budgie Desktop” at login.</p>
<p>Still, this begs the question why <tt class="docutils literal"><span class="pre">gnome-shell-common</span></tt> is a transitive
dependency of <tt class="docutils literal"><span class="pre">ubuntu-budgie-desktop</span></tt> (purging it does remove the
meta-package)? Is there a reason for this, or is it a bug?</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>It’s attractive (nice start menu!), reasonably responsive for a modern desktop,
and has some novel applications (nice to see some Pi specific customizations).
However, it needs a bit of tweaking out of the box for better reliability. I
don’t like removing seeds that supposedly define the system!</p>
<p>The tiling capabilities look very interesting for those on large monitors, though.</p>
</div>
<div class="section" id="configuration">
<span id="down-here"></span><h2><a class="toc-backref" href="#contents">Configuration</a></h2>
<p>For Ubuntu Budgie, the configurations I used were as follows. For the boot
configuration, highlighted lines are those changed from the lunar defaults:</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>For the kernel command line, the entire file must consist of a <em>single line of
text</em> so I would suggest simply copying this wholesale:</p>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>For the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, the highlighted lines are those that you
may wish to change after copying the content:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">budgie-pi</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="linenos">11</span>
</span><span id="line-12"><span class="linenos">12</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-13"><span class="hll"><span class="linenos">13</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-14"><span class="linenos">14</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-15"><span class="hll"><span class="linenos">15</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-17"><span class="linenos">17</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-18"><span class="linenos">18</span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span>
</span><span id="line-34"><span class="linenos">34</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-37"><span class="hll"><span class="linenos">37</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span>
</span><span id="line-43"><span class="linenos">43</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span>
</span><span id="line-47"><span class="linenos">47</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-48"><span class="linenos">48</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-budgie-desktop-raspi</span><span class="w"></span>
</span><span id="line-49"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-50"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Finally, the networking configuration. I used Ethernet for my experiments, and
given the number of packages that need installing I’d generally recommend that
too. Please see the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> for important information on adjusting the
network configuration to Network Manager post installation:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos">2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos">3</span><span class="w"> </span><span class="nt">ethernets</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos">4</span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="linenos">5</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-6"><span class="linenos">6</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span></pre></div>
</div>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="tiling" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>I specify <span class="caps">GTK</span>-based because that tittering you can hear is from
<span class="caps">KDE</span>’s <a class="reference external" href="https://konsole.kde.org/">Konsole</a> users, who’ve had this feature for yonks.</td></tr>
</tbody>
</table>
</div>
The Xubuntu Flavour2023-08-02T00:00:00+01:002023-08-16T23:05:20+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-02:/2023/the-xubuntu-flavour.html<p class="first last">Baking a Lubuntu Lunar desktop with cloud-init</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.
Skip <a class="reference internal" href="#down-here">down here</a> for the configurations used.</p>
<p>In this post, we’ll be looking at creating a Xubuntu desktop with a
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, on a Raspberry Pi.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#xubuntu" id="id3">Xubuntu</a></li>
<li><a class="reference internal" href="#verdict" id="id4">Verdict</a></li>
<li><a class="reference internal" href="#configuration" id="id5">Configuration</a></li>
</ul>
</div>
<div class="section" id="xubuntu">
<h2><a class="toc-backref" href="#contents">Xubuntu</a></h2>
<p>Xubuntu is another lightweight flavour of Ubuntu (similar to Lubuntu in this
respect), but based on <span class="caps">XFCE</span> (a <span class="caps">GTK</span> based environment). Subjectively, I couldn’t
discern much difference in performance between Lubuntu and Xubuntu. Other than
the positioning of the application bar at the top of the screen (compared to
Lubuntu’s traditional bottom placement), things felt pretty similar.</p>
<img alt="A screenshot of the Xubuntu desktop. A small panel sits at the top of the screen showing (from left to right) the small applications menu button, the window switcher, and the small icons in the system tray, followed by the clock. Below are numerous overlapping windows including a PDF showing a Raspberry Pi datasheet, "htop" running in a terminal, "Hey Arnold!" playing in a video player, a file browser, one of Simon Tatham's logic puzzles, and Firefox showing the prior blog post." src="https://waldorf.waveform.org.uk/images/desktops-lunar-xubuntu.png" />
<p>On the functionality side of things, the incorrect audio output appeared as in
Lubuntu, but was trivial to work around. Out of the box, music playback from
the network worked thanks to the inclusion of the excellent <a class="reference external" href="https://wiki.gnome.org/Apps/Rhythmbox">Rhythmbox</a>
<a class="footnote-reference" href="#rhythm" id="id1">[1]</a>. Video playback worked well with the <a class="reference external" href="https://docs.xfce.org/apps/parole/start">Parole</a> player, but
unfortunately it didn’t seem able to playback from an <span class="caps">SMB</span> network share unless
it was mounted.</p>
<p>This is one of those “integration” things; the file browser (<a class="reference external" href="https://docs.xfce.org/xfce/thunar/start">Thunar</a>), and
most file-open dialogs, will happily browse to an <span class="caps">SMB</span> share and will <em>appear</em>
to open the file. But then an error appears or, worse, nothing happens. Of
course, the solution in this case is simple: <tt class="docutils literal">sudo apt install vlc</tt> and it
Just Works.</p>
<p>On the subject of bugs, remember I mentioned screen-savers? The lock-screen
would happily kick in and blank the monitor, but wouldn’t suspend it
(presumably <a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1998716"><span class="caps">LP</span>: #1998716</a> again?). However, attempting to unlock (wiggling
the mouse or hitting a key to bring up the login screen) gave the poor thing
conniptions. The password prompt would briefly flicker into life, then the
screen would blank again. Then flicker into life, then blank. Password entry
wouldn’t work while all this was going on (something crashing?). After this
happened several (4 or 5?) times, it seemed to get a grip on itself and allow
login once more, but it’s rather broken! I’ll try and find some time to dig out
some more useful info for a bug report (like whether this is specific to my monitor).</p>
<p>Everything else was pretty much as expected: I could read PDFs, print things,
open links, browse the web, manipulate the file-system, use the terminal, all
without issue, and all reasonably smoothly.</p>
<p>One amusing stand-out I did notice: the choice of bundled desktop games! On
most desktops, this is pretty bland fare. Some variation of Klondike solitaire,
maybe a Minesweeper clone, perhaps a Sudoku implementation. But not here! No,
Xubuntu bundles one single game package <a class="footnote-reference" href="#other-games" id="id2">[2]</a>, but it’s packed with
more fiendishly fun entertainment than all the other default desktop gaming
packages put together: <a class="reference external" href="https://www.chiark.greenend.org.uk/~sgtatham/puzzles/">Simon Tatham’s Puzzles</a> (if you haven’t played these
before, you owe it to yourself to <tt class="docutils literal">sudo apt install <span class="pre">sgt-launcher</span></tt> and give
them a whirl).</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>It’s pretty (rather more so that Lubuntu in my opinion), lightweight,
responsive and reasonably functional. However, it’s got a few more bugs than
Lubuntu (the screen-saver particularly) so given the choice I’d probably go
with Lubuntu for a light-weight choice. Still … a <em>brilliant</em> selection of games!</p>
</div>
<div class="section" id="configuration">
<span id="down-here"></span><h2><a class="toc-backref" href="#contents">Configuration</a></h2>
<p>For Xubuntu, the configurations I used were as follows. For the boot
configuration, highlighted lines are those changed from the lunar defaults:</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>For the kernel command line, the entire file must consist of a <em>single line of
text</em> so I would suggest simply copying this wholesale:</p>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>For the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, the highlighted lines are those that you
may wish to change after copying the content:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">xubuntu-pi</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="linenos">11</span>
</span><span id="line-12"><span class="linenos">12</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-13"><span class="hll"><span class="linenos">13</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-14"><span class="linenos">14</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-15"><span class="hll"><span class="linenos">15</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-17"><span class="linenos">17</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-18"><span class="linenos">18</span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span>
</span><span id="line-34"><span class="linenos">34</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-37"><span class="hll"><span class="linenos">37</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span>
</span><span id="line-43"><span class="linenos">43</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span>
</span><span id="line-47"><span class="linenos">47</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-48"><span class="linenos">48</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">xubuntu-desktop</span><span class="w"></span>
</span><span id="line-49"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-50"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Finally, the networking configuration. I used Ethernet for my experiments, and
given the number of packages that need installing I’d generally recommend that
too. Please see the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> for important information on adjusting the
network configuration to Network Manager post installation:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos">2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos">3</span><span class="w"> </span><span class="nt">ethernets</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos">4</span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="linenos">5</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-6"><span class="linenos">6</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span></pre></div>
</div>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="rhythm" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>Rhythmbox is probably my favourite part of the entire <span class="caps">GNOME</span>
project. It’s genuinely superb: supports every protocol and format I’ve ever
needed (and several I haven’t), has a <span class="caps">UI</span> that’s minimal but fantastically
functional, and most of all <em>fast</em>. Want to navigate your way through ~8000
songs spread over ~500 albums? No problem, even on a Pi! It’s one of the
four applications that I reliably fire up every single day.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="other-games" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>That I could see; <a class="reference external" href="https://git.launchpad.net/~xubuntu-dev/ubuntu-seeds/+git/xubuntu/tree/desktop#n101">the seed</a>
seems to suggest it ships the <span class="caps">GNOME</span> implementations of Mines and Sudoku too
but they didn’t appear in the start menu.</td></tr>
</tbody>
</table>
</div>
The Lubuntu Flavour2023-08-01T00:00:00+01:002023-07-31T00:43:43+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-08-01:/2023/the-lubuntu-flavour.html<p class="first last">Baking a Lubuntu Lunar desktop with cloud-init</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> which links to all the other flavour posts.
Skip <a class="reference internal" href="#down-here">down here</a> for the configurations used.</p>
<p>In this post, we’ll be looking at creating a Lubuntu desktop with a
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, on a Raspberry Pi.</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#lubuntu" id="id1">Lubuntu</a></li>
<li><a class="reference internal" href="#verdict" id="id2">Verdict</a></li>
<li><a class="reference internal" href="#configuration" id="id3">Configuration</a></li>
</ul>
</div>
<div class="section" id="lubuntu">
<h2><a class="toc-backref" href="#contents">Lubuntu</a></h2>
<p>Lubuntu is a lightweight flavour of Ubuntu, based on LXQt (which is the desktop
environment that RaspiOS is based upon too). It’s certainly the lightest in
terms of resource usage from all the desktops I’m comparing, and one of the
most responsive too.</p>
<img alt="A screenshot of the Lubuntu desktop. A small panel sits at the bottom of the screen showing (from left to right) the small applications menu button (adorned with a bird), the numbers 1 through 4 for the desktop switcher, some quick-launch icons for the file-manager and firefox, the window switcher, and the small icons in the system tray, followed by the clock. Above are numerous overlapping windows including a PDF showing a section of the FreeRTOS manual datasheet, "htop" running in a terminal, "Sintel" playing in VLC, a file browser, and Firefox showing the Lubuntu homepage." src="https://waldorf.waveform.org.uk/images/desktops-lunar-lubuntu.png" />
<p>It’s a bit prettier than when I last saw it 3 years ago, but still doesn’t have
the polish of the “full” desktop suites like <span class="caps">GNOME</span> or <span class="caps">KDE</span>. The interface feels
very responsive but it’s notable that there’s no Wayland support yet so the
performance of graphically heavy things is not entirely smooth.</p>
<p>One issue immediately jumped out, which was the incorrect selection of the
default audio output (the 3.5mm jack output which wasn’t connected, instead of
<span class="caps">HDMI</span>). This is a known issue (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/pipewire/+bug/1993347"><span class="caps">LP</span>: #1993347</a>), and one that occurs on almost
every other flavour too. Thankfully it’s a trivial work-around (just pick the
<span class="caps">HDMI</span> output instead) and the selection persists across reboots, so it’s a
one-time fix.</p>
<p>The applications on Lubuntu are understandably minimal, but surprisingly good!
Most desktop environments try and bundle “native” applications for specific
purposes, like a video player. By “native” I mean applications that stick
strictly within that desktop’s base toolkit (whether that’s <span class="caps">GTK</span> or Qt, and
their corresponding media bits), so that the distribution of that desktop
doesn’t bloat itself out with additional libraries (or whole frameworks) for a
single application. This means you’ll see things like the <a class="reference external" href="https://docs.xfce.org/apps/parole/start">Parole</a> or <a class="reference external" href="https://gitlab.gnome.org/GNOME/totem">Totem</a>
video players … right before you open a command line, <tt class="docutils literal">sudo apt install vlc</tt>,
and never look back.</p>
<p>Lubuntu, by contrast, just installs <a class="reference external" href="https://www.videolan.org/"><span class="caps">VLC</span></a> saving you a whole step! That said,
<span class="caps">VLC</span> is all you get for media playback here and, capable though <span class="caps">VLC</span> is with
music, it’s not set up as an album browser. I’m too used to having something to
do just that. The distro seed giveth, and the distro seed … leaveth stuff out.</p>
<p>There were a couple of minor oddities. The two partitions on the <span class="caps">SD</span> card show
up as “removable” (which they fairly obviously … aren’t) on the system tray
widget. After one system upgrade and a reboot, the wallpaper disappeared
inexplicably. However, the screen-saver worked perfectly. Locked the screen and
put the monitor in power-saving mode. Why do I mention this? Firstly, I’ve had
a long-standing issue with the official <span class="caps">GNOME</span> desktop not putting my monitor
into power-saving mode (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1998716"><span class="caps">LP</span>: #1998716</a>). Secondly … screen-saver breakage
became a bit of a theme the further I went on with this series …</p>
<p>Otherwise, things mostly worked well. The included file browser is <a class="reference external" href="https://wiki.archlinux.org/title/PCManFM">PCManFM</a>,
which is capable (and fast!). It’ll also be familiar to users of RaspiOS as
it’s the default file browser there too. No issues opening things, including
over unmounted network shares, no problems printing or scanning over the
network, and Firefox worked as normal.</p>
</div>
<div class="section" id="verdict">
<h2><a class="toc-backref" href="#contents">Verdict</a></h2>
<p>It’s not the prettiest, but it is lightweight, responsive, and has a nice
choice of default apps. In practice it feels functional enough that I’d be
happy to use it as my desktop, but I’d definitely miss the ability to easily
“tile” applications (maybe there’s a shortcut for this that I didn’t find!).</p>
</div>
<div class="section" id="configuration">
<span id="down-here"></span><h2><a class="toc-backref" href="#contents">Configuration</a></h2>
<p>For Lubuntu, the configurations I used were as follows. For the boot
configuration, highlighted lines are those changed from the lunar defaults:</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>For the kernel command line, the entire file must consist of a <em>single line of
text</em> so I would suggest simply copying this wholesale:</p>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>For the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration, the highlighted lines are those that you
may wish to change after copying the content:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lubuntu-pi</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="linenos">11</span>
</span><span id="line-12"><span class="linenos">12</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-13"><span class="hll"><span class="linenos">13</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-14"><span class="linenos">14</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-15"><span class="hll"><span class="linenos">15</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-17"><span class="linenos">17</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-18"><span class="linenos">18</span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span>
</span><span id="line-34"><span class="linenos">34</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-37"><span class="hll"><span class="linenos">37</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span>
</span><span id="line-43"><span class="linenos">43</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span>
</span><span id="line-47"><span class="linenos">47</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-48"><span class="linenos">48</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lubuntu-desktop</span><span class="w"></span>
</span><span id="line-49"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-50"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Finally, the networking configuration. I used Ethernet for my experiments, and
given the number of packages that need installing I’d generally recommend that
too. Please see the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/we-serve-all-flavours.html">intro post</a> for important information on adjusting the
network configuration to Network Manager post installation:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos">2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos">3</span><span class="w"> </span><span class="nt">ethernets</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos">4</span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="linenos">5</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-6"><span class="linenos">6</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span></pre></div>
</div>
</div>
We Serve All Flavours!2023-07-31T00:00:00+01:002023-08-09T09:31:45+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-07-31:/2023/we-serve-all-flavours.html<p class="first last">More tricks with cloud-init for baking ready-made desktops, and the
index for the forthcoming look at each of the Ubuntu flavours</p>
<p><strong>See Also</strong>: The <a class="reference external" href="https://waldorf.waveform.org.uk/2023/desktop-on-a-stick.html">prior post</a> in which we learned about the wonders of
automated configuration with <tt class="docutils literal"><span class="pre">cloud-init</span></tt>.</p>
<p>It’s that time of the decade, again: desktop round-up time! As of writing this
introductory paragraph, I’ve now finished poking, prodding, and reviewing each
of the Ubuntu flavours. However, the article turned into yet another
small-novella sized piece and the only sensible way I can think to publish this
is by making this one an introductory piece, with a few final <tt class="docutils literal"><span class="pre">cloud-init</span></tt>
hints, and an index to the other articles which will be published once a day
over the coming week (and a bit).</p>
<p>My apologies, dear reader, for keeping you on tenterhooks again …</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#adding-sprinkles" id="id4">Adding Sprinkles</a></li>
<li><a class="reference internal" href="#flakes" id="id5">99 Flakes</a></li>
<li><a class="reference internal" href="#the-taste-test" id="id6">The Taste Test</a></li>
<li><a class="reference internal" href="#the-flavours" id="id7">The Flavours</a></li>
</ul>
</div>
<div class="section" id="adding-sprinkles">
<h2><a class="toc-backref" href="#contents">Adding Sprinkles</a></h2>
<p>In the interests of “integration”, and because I wish to demonstrate yet more
capabilities of <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/">cloud-init</a>, I’m going to pre-emptively work around a
long-standing bug (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/evince/+bug/1794064"><span class="caps">LP</span>: #1974064</a>) which I frequently run into, preventing
links in PDFs from opening in the browser. But only if that browser is a snap …
as Firefox is. Furthermore (without giving too much away from future posts in
this series) there still appear to be some integration issues between the
snapped Firefox and Wayland based environments in some of the desktops. So, in
the interests of a level playing field for everyone we’re going to get
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> to install Firefox from a deb on first boot.</p>
<p>We need to add an <tt class="docutils literal">apt</tt> source (the Firefox stable <span class="caps">PPA</span>), and add some
configuration to pin its items higher than the archive’s. Thankfully, this is
pretty simple to derive from all <a class="reference external" href="https://askubuntu.com/a/1404401">those</a>
<a class="reference external" href="https://www.omgubuntu.co.uk/2022/04/how-to-install-firefox-deb-apt-ubuntu-22-04">guides</a>
out there showing how to do this on an already running system:</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-3"><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-5">
</span><span id="line-6"><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-7"><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-8"><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-9"><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-10"><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-11"><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-12">
</span><span id="line-13"><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-14"><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-15"><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span></pre></div>
<p>Now we can ditch that weird <tt class="docutils literal">snap</tt> section in our configuration, and just
stick <tt class="docutils literal">firefox</tt> in the list of packages to install.</p>
<p>One other tip I’m going to add here, but which I won’t be adding to the
experimental configurations as published, because the <em>vast</em> majority of people
won’t want this, is configuration for an <tt class="docutils literal">apt</tt> proxy (specifically
<a class="reference external" href="https://wiki.debian.org/AptCacherNg">apt-cacher-ng</a>). To be clear, for most people I don’t recommend running this
(a couple of times a month it sends my server into a bit of a tizz and needs
kicking), but if you’re going to be repeatedly installing the same large
packages (as I frequently do for packaging work, or in this case when
installing several desktop packages which have similar bases) it can save a
huge amount of time and bandwidth. Anyway, this is what the relevant snippet
looks like:</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="w"> </span><span class="nt">conf</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-3"><span class="w"> </span><span class="no">Acquire::http { Proxy "http://myproxy.local:3142"; }</span><span class="w"></span>
</span></pre></div>
<p>Obviously, replace <tt class="docutils literal">myproxy.local</tt> with the address of your local proxy.</p>
<p>Below is the full configuration we’ll be using (minus the apt-cacher
configuration), with a fairly obvious placeholder for the desktop package. I’ll
publish full configurations (including the <tt class="docutils literal">config.txt</tt>, <tt class="docutils literal">cmdline.txt</tt>, and
<tt class="docutils literal"><span class="pre">network-config</span></tt>, largely derived from the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/desktop-on-a-stick.html">prior post</a>) in each section in
case you want to play along at home. Just place these on the boot partition of
an Ubuntu Server for Pi (23.04 or later) card <a class="footnote-reference" href="#arch" id="id1">[1]</a> and adjust the
highlighted lines to your tastes:</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">miss-piggy</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="hll"><span class="linenos">11</span><span class="w"> </span><span class="nt">options</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ctrl:nocaps</span><span class="w"></span>
</span></span><span id="line-12"><span class="linenos">12</span>
</span><span id="line-13"><span class="linenos">13</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-14"><span class="hll"><span class="linenos">14</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-15"><span class="linenos">15</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-17"><span class="hll"><span class="linenos">17</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">raspberry</span><span class="w"></span>
</span></span><span id="line-18"><span class="linenos">18</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span>
</span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-21"><span class="hll"><span class="linenos">21</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-22"><span class="linenos">22</span>
</span><span id="line-23"><span class="linenos">23</span><span class="nt">apt</span><span class="p">:</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">mozillateam</span><span class="p">:</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">'ppa:mozillateam/ppa'</span><span class="w"></span>
</span><span id="line-27"><span class="linenos">27</span>
</span><span id="line-28"><span class="linenos">28</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-29"><span class="linenos">29</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/apt/preferences.d/firefox</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="w"> </span><span class="no">Pin: release o=LP-PPA-mozillateam</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="w"> </span><span class="no">Pin-Priority: 501</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span>
</span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="no">Package: firefox*</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span><span class="w"> </span><span class="no">Pin: release o=Ubuntu</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="w"> </span><span class="no">Pin-Priority: -1</span><span class="w"></span>
</span><span id="line-38"><span class="hll"><span class="linenos">38</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-40"><span class="linenos">40</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span>
</span><span id="line-44"><span class="linenos">44</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-45"><span class="linenos">45</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-46"><span class="linenos">46</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-47"><span class="linenos">47</span>
</span><span id="line-48"><span class="linenos">48</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-49"><span class="hll"><span class="linenos">49</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">YOUR-DESKTOP-PACKAGE-HERE</span><span class="w"></span>
</span></span><span id="line-50"><span class="linenos">50</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-51"><span class="linenos">51</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>Bear in mind your first boot is going to install a <em>lot</em> of things, and it will
take <em>at least</em> an hour (more like an hour and a half) even on a good
A1-compliant <span class="caps">SD</span> card.</p>
</div>
<div class="section" id="flakes">
<h2><a class="toc-backref" href="#contents">99 Flakes</a></h2>
<p>One wrinkle I forgot to mention in the <a class="reference external" href="https://waldorf.waveform.org.uk/2023/desktop-on-a-stick.html">prior post</a> is that of networking. The
server images we’re basing this on use <a class="reference external" href="https://netplan.io/">netplan</a>, and start off by having it
“render” the network configuration via <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.network.html">networkd</a> (part of systemd).</p>
<p>However, every Ubuntu desktop flavour ultimately winds up using <a class="reference external" href="https://networkmanager.dev/">Network
Manager</a> for its network configuration. While <a class="reference external" href="https://netplan.io/">netplan</a> is <em>capable</em> of
rendering a configuration via Network Manager, that’s probably <em>not</em> what you
ultimately want as your network configuration wouldn’t be editable via the
Network Manager <span class="caps">GUI</span> (only the netplan <span class="caps">YAML</span> configuration files).</p>
<p>Why not change the initial netplan configuration to render through Network
Manager instead? This won’t work because at first boot, the card is just Ubuntu
Server for Pi and doesn’t contain Network Manager. That only gets installed
along with the chosen desktop flavour, but <em>that</em> act requires a network to
already be configured. Dependency cycles!</p>
<p>The fix is simple enough. Once the desktop has booted, and you’re all snugly
logged in for the first time, run the following to delete the generated netplan
configuration and re-apply the (now empty) settings:</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="gp">$ </span>sudo rm /etc/netplan/50-cloud-init.yaml
</span><span id="line-2"><span class="gp">$ </span>sudo netplan apply
</span></pre></div>
<p>At this point networkd will stop “managing” the interfaces and Network Manager
will take them over. In the case of a simple <span class="caps">DHCP</span>-based Ethernet connection, it
should reconfigure automatically and you’ll be back up and running in seconds.
However, if you performed your initial set up over WiFi you’ll now need to go
into the <span class="caps">GUI</span> network settings for your flavour (wherever that is — it can
usually be found from the system-tray though) and re-enter your WiFi credentials.</p>
<p>This is one of the ways that this Frankenstein-like desktop setup differs from
the official desktop releases. There are a few others (dual seeds, user
creation differences, root-fs sizing, probably a few others that I’ve
forgotten!), and if anyone’s interested I can go through them, but this is the
only one that’s affected the use of the desktop during my explorations.</p>
</div>
<div class="section" id="the-taste-test">
<h2><a class="toc-backref" href="#contents">The Taste Test</a></h2>
<p>What should I look for in a desktop? I can’t define this universally, so I’ll
just go with what works for me. My personal workflow is probably a strange mix
of deeply anachronistic, and semi-modern. On the one hand, I spend the <em>vast</em>
majority of my time in a terminal window. On the other, I eschew office
applications in favour of doing office-y work in a web-browser. Google Sheets
for any spreadsheet work (though I have been known to dip into <a class="reference external" href="https://en.wikipedia.org/wiki/Sc_(spreadsheet_calculator)">sc</a> for
trivial bits), and when I absolutely <em>have</em> to touch a word-processor <a class="footnote-reference" href="#word" id="id2">[2]</a>,
Google Docs.</p>
<p>I could <em>almost</em> get away with working on a Chromebook, but not <em>quite</em>. If I
have PDFs to deal with (and between Canonical’s hiring push, and various
hardware data-sheets, I get through quite a few of these), I use an
honest-to-goodness standalone <span class="caps">PDF</span> reader, instead of the (usually horribly
slow) built-in <span class="caps">PDF</span> readers in browsers. Sometimes I even … brace yourself …
<em>print</em> them <a class="footnote-reference" href="#printing" id="id3">[3]</a>!</p>
<p>I also play most of my music, served from the home server, in a standalone
application, and the same goes for most films I watch (there are some good
web-based systems for this, but browsers are <em>heavy</em> and I work on a Pi so I
tend to try and limit my use of them to text-based duties). Most of my file
manipulation is done from the command line, but sometimes for simpler stuff
(especially involving external storage) I’ll resort to the file browser.</p>
<p>So, I’ll be looking for:</p>
<ul class="simple">
<li>A decent terminal — this is pretty much a given; it’d hardly be a Linux
distro without a decent terminal!</li>
<li>A decent browser — again, pretty much a given as we’ll be installing Firefox anyway.</li>
<li>Some decent media applications — music player, video player, a standalone <span class="caps">PDF</span>
viewer, preferably a good file browser for managing it all.</li>
<li>Integration — I want to be able to click a link from my terminal, or in a
<span class="caps">PDF</span>, and have it open in the web-browser. I’d like to be able to open files,
archives, and videos straight from the file-browser, even from network shares
(<em>ideally</em> without messing around with network mounts). The home server has
all sorts of services for this (<span class="caps">NFS</span>, <span class="caps">SMB</span>, <span class="caps">DLNA</span>, etc. all advertised over
avahi) so there should be plenty of opportunity here. I also want to be able
to print stuff without jumping through tons of hoops (again, the printers
here are network-accessible and advertised over avahi).</li>
<li>Performance — it’s a Pi, so I can’t expect the world here, but the video
player should handle 720p or 1080p sources in full-screen, smoothly. The
music player should play without stuttering, and generally things shouldn’t
feel (too) sluggish. The browser is an exception here: modern browsers are
ridiculously (over-)complex beasts and I’ll allow some lee-way for this.</li>
<li>Reliability — The more bugs I run into, the more points I’ll dock. Erm … are
we doing points? Well, any bugs I run into I’ll point out. And possibly
report, if I can figure out what to file ‘em against!</li>
</ul>
<p>Now, with all that extra gubbins out of the way, on with the tests!</p>
</div>
<div class="section" id="the-flavours">
<h2><a class="toc-backref" href="#contents">The Flavours</a></h2>
<p>These are the flavours I’m intending to cover, which will become links to the
relevant article:</p>
<ul class="simple">
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-lubuntu-flavour.html">Lubuntu</a> — the LXQt flavour</li>
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-xubuntu-flavour.html">Xubuntu</a> — the <span class="caps">XFCE</span> flavour</li>
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-ubuntu-budgie-flavour.html">Ubuntu Budgie</a> — the Budgie flavour</li>
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-ubuntu-unity-flavour.html">Ubuntu Unity</a> — the Unity flavour</li>
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-kubuntu-flavour.html">Kubuntu</a> — the <span class="caps">KDE</span> flavour</li>
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-ubuntu-studio.html">Ubuntu Studio</a> — the creator’s flavour</li>
<li><a class="reference external" href="https://waldorf.waveform.org.uk/2023/the-ubuntu-desktop.html">Ubuntu</a> — comparison to the official <span class="caps">GNOME</span>-based image</li>
</ul>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="arch" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>Side note: theoretically this should work on either armhf or arm64,
however I’m only testing arm64 here as it’s all we officially support on the
desktop images anyway.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="word" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>In case it’s not obvious, I am firmly of the opinion that <a class="reference external" href="https://en.wikipedia.org/wiki/WYSIWYG"><span class="caps">WYSIWYG</span></a>
is the work of the devil, and the One True Way is that of the markup
language, beautifully processed by 100% natural, hand-crafted,
hypo-allergenic, non-genetically modified, organically-certified algorithms
into whatever output format you may prefer.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="printing" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td>I have rarely felt as old as I did a few weeks ago when a
younger colleague casually inquired, “does anyone still <em>have</em> a printer?”
Yes! In my utter extravagance I even have two. One of them does <em>colour</em>!</td></tr>
</tbody>
</table>
</div>
Desktop on a Stick2023-06-30T00:00:00+01:002023-07-22T16:03:00+01:00Dave Jonestag:waldorf.waveform.org.uk,2023-06-30:/2023/desktop-on-a-stick.html<p class="first last">Construct a variety of desktop flavours using cloud-init on the
Raspberry Pi</p>
<p><strong>Updated</strong> to include the per-release quirks channel for the snap.</p>
<p><strong><span class="caps">TL</span>;<span class="caps">DR</span></strong>: Skip <a class="reference internal" href="#down-here">down here</a> for the final configurations.</p>
<p>It’s that time of the decade, again: desktop round-up time! But thanks to
a genius notion from Oliver (one of our product managers), I’m going to be
doing it a bit differently. Previously, my procedure for checking out the
<a class="reference external" href="https://waldorf.waveform.org.uk/2020/ubuntu-desktops-on-the-pi.html">various Ubuntu desktops on a Raspberry Pi</a> looked something like this:</p>
<ol class="arabic simple">
<li>Flash a server image (go make coffee)</li>
<li>Boot the server image (twiddle thumbs for a minute or two while it sorts out
the first time setup)</li>
<li><tt class="docutils literal">apt install <span class="pre">lubuntu-desktop</span></tt> (go make more coffee)</li>
<li>Reboot, play with it a bit, install a bunch of stuff (yet more coffee)</li>
</ol>
<p>To avoid the inevitable caffeine poisoning that results from repeating this
procedure for Lubuntu, Xubuntu, Kubuntu, and Budgie, this time we’re going to
use … drum roll please …</p>
<object data="https://waldorf.waveform.org.uk/images/cloud-init.svg" style="width: 50%;" type="image/svg+xml">The (original) cloud-init logo with the words “cloud-init” adjacent.
The logo is the usual Ubuntu-orange circle, within which appears a
very geometrically simplified representation of the fingers of the
left hand. The index finger is extended and appears to be touching
the edge of a large white spark (which in no way suggests someone
electrocuting themselves by touching a live surface). Or it could
be a worm with a large anime hair-do. I’m not sure.</object>
<p>If that sounds like a bit of an anti-climax, that’s just because you haven’t
played with <tt class="docutils literal"><span class="pre">cloud-init</span></tt> enough. Yes, its one-shot nature makes it painful to
iterate when you get things wrong. Yes, the documentation is painfully obscure
in places. However, once you get a grip on it, it’s quite astonishingly
flexible. Hopefully, by reading this you can bypass some of that pain and start
from a more useful point!</p>
<p>But before we get to the fun bits, we need to get the basics done …</p>
<div class="section" id="ingredients">
<h2>Ingredients</h2>
<p>The first step is to get a Pi to test with. You’ll need a <a class="reference external" href="https://www.raspberrypi.com/products/raspberry-pi-4-model-b/">Pi 4</a>, <a class="reference external" href="https://www.raspberrypi.com/products/raspberry-pi-400/">Pi 400</a>,
or <a class="reference external" href="https://www.raspberrypi.com/products/compute-module-4/"><span class="caps">CM4</span></a> with at least <span class="caps">4GB</span> of <span class="caps">RAM</span>. At the time of writing, that’s a slightly
tricky proposition given the supply shortages. The vital <a class="reference external" href="https://rpilocator.com/">rpilocator</a> can help
here, but it would appear (at least <a class="reference external" href="https://www.youtube.com/watch?v=-_aL9V0JsQQ">according to Eben</a>, who probably knows
what he’s talking about!) that the shortage should begin to clear during the
second half of 2023.</p>
<p>The second step is to get an image we can play with. I’m going to be using the
recently released <a class="reference external" href="http://cdimage.ubuntu.com/releases/23.04/release/ubuntu-23.04-preinstalled-server-arm64+raspi.img.xz">Ubuntu 23.04 (Lunar Lobster) Server for Raspberry Pi
image</a>, specifically the arm64 variant. You can use <a class="reference external" href="https://www.raspberrypi.com/software/">rpi-imager</a> to flash
this to a spare <span class="caps">SD</span> card, or even <span class="caps">SSD</span> drive attached to a <span class="caps">USB</span> adapter.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">A word of caution: don’t try this with Jammy (22.04). There’s a reason I’m
using Lunar (23.04) for this experiment. If you don’t care about the
reasons, <a class="reference internal" href="#common-stuff">skip to the next section</a>. Otherwise, read on …</p>
</div>
<p>Historically, Ubuntu images (including the Ubuntu for Raspberry Pi images) have
been built with a system called <tt class="docutils literal"><span class="pre">livecd-rootfs</span></tt>. This could <em>charitably</em> be
described as a rough collection of dozens of hooks (and hacks) in the form of
shell scripts, all of them plastered onto the already crufty base of
<tt class="docutils literal"><span class="pre">livecd-rootfs</span></tt>, itself a gigantic mess of shell script.</p>
<p>The result is exactly the hellish nightmare of obscure regex-loaded nonsense
that you might imagine. Worse still, many of the hacks inject configuration
files into the resulting image that are <em>unowned</em>. That is to say, no Debian
package owns these injected files, and that causes all sorts of fun when it
comes to upgrades.</p>
<p>My friend William, before he left, made a valiant start on sorting out this
mess by re-writing the old <tt class="docutils literal"><span class="pre">ubuntu-image</span></tt> tool. In concert with this effort,
my small contribution was to start migrating hacks from <tt class="docutils literal"><span class="pre">livecd-rootfs</span></tt> into
the <tt class="docutils literal"><span class="pre">ubuntu-settings</span></tt> package so that in Lunar (and beyond), as much
configuration as possible would be directly under the control of the package
management system (this contribution made a screeching U-turn when, at the last
minute, it was decided we <em>were</em> going to use <tt class="docutils literal"><span class="pre">livecd-rootfs</span></tt> for lunar after
all, but that’s another story!).</p>
<p>This is one of the major reasons it’s now much simpler to spin up a desktop
image with <tt class="docutils literal"><span class="pre">cloud-init</span></tt>. Instead of having a write a ton of configuration to
add all the necessary tweaks <tt class="docutils literal"><span class="pre">livecd-rootfs</span></tt> used to do, we can just include
one extra package and (mostly) be done.</p>
</div>
<div class="section" id="preparing-your-kitchen">
<span id="common-stuff"></span><h2>Preparing your kitchen</h2>
<p>Once your <span class="caps">SD</span> card (or drive) is flashed, eject it, then re-insert it.
Regardless of the <span class="caps">OS</span> you’re using (Windows, Mac <span class="caps">OS</span>, Linux), you should see the
boot partition (labelled “system-boot”) appear <a class="footnote-reference" href="#linux-mount" id="id1">[1]</a>. We’re going to
be tweaking several configuration files, specifically:</p>
<ul class="simple">
<li><tt class="docutils literal">config.txt</tt> — this is the Pi bootloader configuration</li>
<li><tt class="docutils literal">cmdline.txt</tt> — this is the Linux kernel command line</li>
<li><tt class="docutils literal"><span class="pre">user-data</span></tt> — this is the main <tt class="docutils literal"><span class="pre">cloud-init</span></tt> configuration file</li>
<li><tt class="docutils literal"><span class="pre">network-config</span></tt> — this is the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> network configuration</li>
</ul>
<p>We’ll start with <tt class="docutils literal">config.txt</tt> because the changes here are universal: they’ll
be required no matter which desktop we’re intending to use:</p>
<ol class="arabic simple">
<li>Find the <tt class="docutils literal">enable_uart=1</tt> line (it’s on line 28 by default) and comment it
out by inserting <tt class="docutils literal">#</tt> at the start of the line. This simply disables the
serial console which isn’t <em>strictly</em> necessary, but if the serial console
is enabled, the Pi’s <span class="caps">GPU</span> clock is locked to low speed and obviously we want
the <span class="caps">GPU</span> clock to float higher for our desktop.</li>
<li>At the end of the file add <tt class="docutils literal"><span class="pre">dtoverlay=vc4-kms-v3d</span></tt> to load the “full”
<a class="reference external" href="https://en.wikipedia.org/wiki/Direct_Rendering_Manager#Kernel_mode_setting"><span class="caps">KMS</span></a> device-tree overlay (it should be in the <tt class="docutils literal">[all]</tt> section at the end
of the file)</li>
</ol>
<p>Next we need to tweak the kernel command line in <tt class="docutils literal">cmdline.txt</tt>. Again, all
the changes here are common to all desktops. This file consists of a single
line of text; don’t introduce any line breaks when editing it:</p>
<ol class="arabic simple">
<li>Delete <tt class="docutils literal">console=serial0,115200</tt> at the start. This just removes the <a class="reference external" href="https://en.wikipedia.org/wiki/Tty_(Unix)">tty</a>
associated with the serial console which we disabled above in
<tt class="docutils literal">config.txt</tt>.</li>
<li>Insert <tt class="docutils literal">zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd</tt> at the
start. This activates the <a class="reference external" href="https://waldorf.waveform.org.uk/2021/6-months-with-the-pi-desktop.html#swap-swap-glorious-zswap">zswap</a> system that we use on the desktop.</li>
</ol>
<p>These changes more or less boil down to the base differences between the Ubuntu
Pi server and desktop images. Most of the other differences (since Lunar, as
discussed above) come down to the selection of packages that are installed …</p>
</div>
<div class="section" id="picking-your-flavour">
<h2>Picking your flavour</h2>
<p>It’s time to learn what we can do with <tt class="docutils literal"><span class="pre">cloud-init</span></tt>. The most obvious thing
we want is to have a particular desktop package installed. This is pretty
simple, and achieved by adding the following block to the <tt class="docutils literal"><span class="pre">user-data</span></tt> file on
the boot partition:</p>
<pre class="code yaml literal-block">
<span class="nt">packages</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">lubuntu-desktop</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">ubuntu-raspi-settings-desktop</span>
</pre>
<p>This tells <tt class="docutils literal"><span class="pre">cloud-init</span></tt> that, on first boot, we want it to try and install
two extra packages:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">lubuntu-desktop</span></tt> is the basis of the Lubuntu desktop images; we’ll
substitute other desktop packages here later</li>
<li><tt class="docutils literal"><span class="pre">ubuntu-raspi-settings-desktop</span></tt> contains all the little tweaks for the Pi
desktop (ensuring there’s a swap-file, disabling suspend in Gnome, inserting
the correct modules for zswap into the initrd, setting appropriate
permissions for <span class="caps">I2C</span> and <span class="caps">SPI</span> interfaces, etc.)</li>
</ul>
<p>In addition to these we <em>should</em> also add the following settings (these aren’t
mandatory, but highly recommended):</p>
<pre class="code yaml literal-block">
<span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span>
</pre>
<p>The first line tells <tt class="docutils literal"><span class="pre">cloud-init</span></tt> we want it to run <tt class="docutils literal">apt update</tt> to refresh
the set of available packages. This is the most important line as, without it,
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> will likely fail at some point because the apt index shipped on
the image will be out of date. The next line demands that <tt class="docutils literal">apt upgrade</tt>
should be run to ensure all packages are up to date. The final line indicates
that, if any package indicates a reboot is required, we should carry one out
(this is absolutely the case when installing a desktop, as a display manager
will be installed at the very least).</p>
<p>Next, while some of the desktops available install a browser by default (by
depending on the Firefox apt package, which in turns installs the Firefox
snap), several don’t as their official images include the Firefox (or Chromium)
snap directly without the apt “wrapper”. To avoid winding up with a desktop
without a browser, we’ll add another section to install the Firefox snap explicitly:</p>
<pre class="code yaml literal-block">
<span class="nt">snap</span><span class="p">:</span><span class="w">
</span><span class="nt">commands</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">snap install --channel=latest/stable/ubuntu-23.04 firefox</span>
</pre>
<p>I’m not entirely sure why the <tt class="docutils literal">snap</tt> section is so different from
<tt class="docutils literal">packages</tt>, or why the full <tt class="docutils literal">snap install <package></tt> form is required.
It does appear from the documentation that the <tt class="docutils literal">snap.commands</tt> section simply
allows arbitrary commands to be specified (<tt class="docutils literal"><span class="pre">canonical-livepatch</span></tt> is included
in the examples), but in that case why call it a <tt class="docutils literal">snap</tt> section?</p>
<p>The exceedingly long channel name causes the snap to follow a <a class="reference external" href="https://snapcraft.io/docs/publish-to-a-branch">branch of a
channel</a> that may include per-release quirks. Or … something like that. I’m
still not clear on the whole “channel” concept in snaps.</p>
</div>
<div class="section" id="locale-ly-sourced">
<h2>Locale-ly sourced</h2>
<p>On the official Ubuntu Desktop for Raspberry Pi images, we have a first time
setup process <a class="footnote-reference" href="#oem-config" id="id2">[2]</a> which guides the user through locale selection and
initial user creation. We don’t have that here, so we’d better get
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> to handle that instead. Firstly the locale, timezone, and
keyboard settings:</p>
<pre class="code yaml literal-block">
<span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">en_GB.UTF-8</span><span class="w">
</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Europe/London</span><span class="w">
</span><span class="nt">keyboard</span><span class="p">:</span><span class="w">
</span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">pc105</span><span class="w">
</span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">gb</span><span class="w">
</span><span class="nt">options</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">ctrl:nocaps</span>
</pre>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">You may want to leave off that “options:” line. I include it to put Ctrl in
the right place (i.e. where Caps Lock is) and because I have no need of a
Caps Lock key.</p>
</div>
<p>To find out the valid values for these settings, you can use the following
commands on an existing Ubuntu desktop (I say desktop specifically because the
available locales on server installations tend to be extremely minimal)
<a class="footnote-reference" href="#no-systemd" id="id3">[3]</a>:</p>
<dl class="docutils">
<dt>locale:</dt>
<dd><tt class="docutils literal">localectl <span class="pre">list-locales</span></tt></dd>
<dt>timezone:</dt>
<dd><tt class="docutils literal">timedatectl <span class="pre">list-timezones</span></tt></dd>
<dt>keyboard:</dt>
<dd><dl class="first last docutils">
<dt>model:</dt>
<dd><tt class="docutils literal">localectl <span class="pre">list-x11-keymap-models</span></tt></dd>
<dt>layout:</dt>
<dd><tt class="docutils literal">localectl <span class="pre">list-x11-keymap-layouts</span></tt></dd>
<dt>variant:</dt>
<dd><tt class="docutils literal">localectl <span class="pre">list-x11-keymaps-variants</span> [layout]</tt></dd>
<dt>options:</dt>
<dd><tt class="docutils literal">localectl <span class="pre">list-x11-keymaps-option</span></tt></dd>
</dl>
</dd>
</dl>
</div>
<div class="section" id="adding-personality">
<h2>Adding personality</h2>
<p>Next we need to create, and customize, the initial user. By default,
<tt class="docutils literal"><span class="pre">cloud-init</span></tt> will create a user named <tt class="docutils literal">ubuntu</tt> with a locked password,
which also has password-less <tt class="docutils literal">sudo</tt> access, and a bunch of default group
memberships (for things like direct video and audio access, etc). The default
group memberships are fine, but I’d like a slightly more personalized username,
and one with password-required <tt class="docutils literal">sudo</tt> rights. This can be accomplished with
the following block:</p>
<pre class="code yaml literal-block">
<span class="nt">user</span><span class="p">:</span><span class="w">
</span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w">
</span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w">
</span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="s">"raspberry"</span><span class="w">
</span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w">
</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">lp:waveform</span>
</pre>
<p>This changes the default username to “dave”, and uses my name in the <tt class="docutils literal">gecos</tt>
field (which traditionally recorded a whole bunch of things like display name,
office number, telephone number, and so forth but these days tends to just be
used for the display name). The <tt class="docutils literal">sudo</tt> setting specifically lacks the
<tt class="docutils literal"><span class="caps">NOPASSWD</span></tt> flag, requiring a password for use. The <tt class="docutils literal">ssh_import_id</tt> setting
lists users from which to import public <span class="caps">SSH</span> keys (use “lp:” prefix for
Launchpad usernames, and “gh:” for Github).</p>
<p>The block also sets the initial password to the plain-text string “raspberry”
and ensures password login is possible (<tt class="docutils literal">lock_passwd</tt> is true by default
which means the only way to login is with <span class="caps">SSH</span> or another auxiliary mechanism,
but that’s not so useful on the desktop!). This is horribly insecure! We could
do something <em>slightly</em> more secure here by providing a hashed password
instead. First we’d run <tt class="docutils literal">mkpasswd</tt> to generate the hash:</p>
<pre class="code console literal-block">
<span class="gp">$ </span>mkpasswd --method<span class="o">=</span>SHA-512 --rounds<span class="o">=</span><span class="m">4096</span>
<span class="go">Password:
</span><span class="gp">$</span><span class="m">6</span><span class="nv">$rounds</span><span class="o">=</span><span class="m">4096</span><span class="nv">$JZRfK1tM</span>.xiWZtR5<span class="nv">$XpMvuj2reJr</span>.....lI0T4Z/
</pre>
<p>Then we would use this with <tt class="docutils literal">hashed_passwd</tt> instead of
<tt class="docutils literal">plain_text_passwd</tt>:</p>
<pre class="code yaml literal-block">
<span class="nt">user</span><span class="p">:</span><span class="w">
</span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w">
</span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w">
</span><span class="nt">hashed_passwd</span><span class="p">:</span><span class="w"> </span><span class="s">"$6$rounds=4096$JZRfK1tM.xiWZtR5$XpMvuj2reJr.....lI0T4Z/"</span><span class="w">
</span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w">
</span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">lp:waveform</span>
</pre>
<p>However, don’t be lulled into a false sense of security. As the <tt class="docutils literal"><span class="pre">cloud-init</span></tt>
documentation <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/reference/modules.html#users-and-groups">notes</a>:</p>
<blockquote>
While <tt class="docutils literal">hashed_password</tt> is better than <tt class="docutils literal">plain_text_passwd</tt>, using [a
password] in <tt class="docutils literal"><span class="pre">user-data</span></tt> represents a security risk as <tt class="docutils literal"><span class="pre">user-data</span></tt>
could be accessible by third-parties depending on your cloud platform</blockquote>
<p>To be clear: <tt class="docutils literal"><span class="pre">user-data</span></tt> is a world-readable file on the Ubuntu Pi images (it
has to be because it’s on a <span class="caps">FAT</span> partition). There is <em>no</em> absolutely secure
method of setting the password via <tt class="docutils literal"><span class="pre">cloud-init</span></tt> (at least on the Ubuntu Pi
images); the secure thing to do here is login and then <em>change your password</em>.
Consider this password initial and <em>temporary</em>.</p>
</div>
<div class="section" id="baking-in-hacks">
<h2>Baking in hacks</h2>
<p>Finishing off our <tt class="docutils literal"><span class="pre">user-data</span></tt> file we’re going to make one final rather hacky
(but useful) change. At the time of writing, Firefox starts under the XWayland
layer. This leads to rather poor performance under certain circumstances. To
force it to load under Wayland directly, we’d need to set the
<tt class="docutils literal">MOZ_ENABLE_WAYLAND</tt> environment variable. Ideally we would do this only in
our user’s environment, not system wide. This could be done by appending a line
to our user’s <tt class="docutils literal"><span class="pre">~/.profile</span></tt> script. However, this doesn’t exist initially (and
won’t until <tt class="docutils literal"><span class="pre">cloud-init</span></tt> creates our user). Thankfully, this presents no problem!</p>
<pre class="code yaml literal-block">
<span class="nt">write_files</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">/home/dave/.profile</span><span class="w">
</span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">|</span><span class="w">
</span><span class="no">export MOZ_ENABLE_WAYLAND=1</span>
</pre>
<p>The powerful (but obviously slightly dangerous) <tt class="docutils literal">write_files</tt> key allows us
to write to arbitrary files on first boot. Here we specify we’d like to write
to <tt class="docutils literal"><span class="pre">/home/dave/.profile</span></tt> (adjust for your custom username as necessary). We
also inform <tt class="docutils literal"><span class="pre">cloud-init</span></tt> that the write should be <em>deferred</em> which means this
will take place <em>after</em> user creation. Further, we specify that we wish to
append (not overwrite), and finally we provide the lines we’d like to append.</p>
</div>
<div class="section" id="going-shopping">
<h2>Going shopping</h2>
<p>Naturally, in order to obtain the packages we’ve requested we’re going to need
some network connectivity. If your Pi is going to be connected by Ethernet,
you’re good to go; the default configuration will just use your Ethernet
connection. However, if you’re going to be relying on WiFi instead we need to
be a bit of surgery in the last file we mentioned earlier, <tt class="docutils literal"><span class="pre">network-config</span></tt>.</p>
<p>Firstly we’ll delete the <tt class="docutils literal">ethernets</tt> section, then uncomment the <tt class="docutils literal">wifis</tt>
section and specify the local access point and password:</p>
<pre class="code yaml literal-block">
<span class="nt">network</span><span class="p">:</span><span class="w">
</span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">2</span><span class="w">
</span><span class="nt">wifis</span><span class="p">:</span><span class="w">
</span><span class="nt">wlan0</span><span class="p">:</span><span class="w">
</span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">access-points</span><span class="p">:</span><span class="w">
</span><span class="s">"my-wifi-ssid"</span><span class="p-Indicator">:</span><span class="w">
</span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="s">"my-wifi-password"</span>
</pre>
<p>It is also useful to specify the <tt class="docutils literal"><span class="pre">regulatory-domain</span></tt> here (note that this
needs to be specified under the <tt class="docutils literal">wlan0</tt> key, which is the reason for the
inclusion of the parent keys below):</p>
<pre class="code yaml literal-block">
<span class="nt">network</span><span class="p">:</span><span class="w">
</span><span class="nt">wifis</span><span class="p">:</span><span class="w">
</span><span class="nt">wlan0</span><span class="p">:</span><span class="w">
</span><span class="nt">regulatory-domain</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">GB</span>
</pre>
<p>The valid regulatory domains can be found in the <a class="reference external" href="https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt">Linux kernel source</a>
Specifically, the two-letter code after the “country” line, which are almost
entirely the <a class="reference external" href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2"><span class="caps">ISO</span>-3166 standard two-letter country codes</a>. The special “00”
domain (the “world regulatory domain”) is the default, but relying on this can
lead to poor WiFi performance, particularly in 5GHz setups where many channels
have restrictions in the world domain.</p>
</div>
<div class="section" id="the-first-byte-is-with-the-eye">
<span id="down-here"></span><h2>The first byte is with the eye</h2>
<p>At the end of all this tinkering, you should have files that look something
like the following on your boot partition (lines you may wish to pay specific
attention to are highlighted):</p>
<div class="topic">
<p class="topic-title">config.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="na">kernel</span><span class="o">=</span><span class="s">vmlinuz</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="na">cmdline</span><span class="o">=</span><span class="s">cmdline.txt</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="na">initramfs initrd.img followkernel</span><span class="w"></span>
</span><span id="line-5"><span class="linenos"> 5</span>
</span><span id="line-6"><span class="linenos"> 6</span><span class="k">[pi4]</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="na">max_framebuffers</span><span class="o">=</span><span class="s">2</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="na">arm_boost</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span>
</span><span id="line-10"><span class="linenos">10</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-11"><span class="linenos">11</span><span class="c1"># Enable the audio output, I2C and SPI interfaces on the GPIO header. As these</span><span class="w"></span>
</span><span id="line-12"><span class="linenos">12</span><span class="c1"># parameters related to the base device-tree they must appear *before* any</span><span class="w"></span>
</span><span id="line-13"><span class="linenos">13</span><span class="c1"># other dtoverlay= specification</span><span class="w"></span>
</span><span id="line-14"><span class="linenos">14</span><span class="na">dtparam</span><span class="o">=</span><span class="s">audio=on</span><span class="w"></span>
</span><span id="line-15"><span class="linenos">15</span><span class="na">dtparam</span><span class="o">=</span><span class="s">i2c_arm=on</span><span class="w"></span>
</span><span id="line-16"><span class="linenos">16</span><span class="na">dtparam</span><span class="o">=</span><span class="s">spi=on</span><span class="w"></span>
</span><span id="line-17"><span class="linenos">17</span>
</span><span id="line-18"><span class="linenos">18</span><span class="c1"># Comment out the following line if the edges of the desktop appear outside</span><span class="w"></span>
</span><span id="line-19"><span class="linenos">19</span><span class="c1"># the edges of your display</span><span class="w"></span>
</span><span id="line-20"><span class="linenos">20</span><span class="na">disable_overscan</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="c1"># If you have issues with audio, you may try uncommenting the following line</span><span class="w"></span>
</span><span id="line-23"><span class="linenos">23</span><span class="c1"># which forces the HDMI output into HDMI mode instead of DVI (which doesn't</span><span class="w"></span>
</span><span id="line-24"><span class="linenos">24</span><span class="c1"># support audio output)</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="c1">#hdmi_drive=2</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span>
</span><span id="line-27"><span class="linenos">27</span><span class="c1"># Enable the serial pins</span><span class="w"></span>
</span><span id="line-28"><span class="hll"><span class="linenos">28</span><span class="c1">#enable_uart=1</span><span class="w"></span>
</span></span><span id="line-29"><span class="linenos">29</span>
</span><span id="line-30"><span class="linenos">30</span><span class="c1"># Autoload overlays for any recognized cameras or displays that are attached</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="c1"># to the CSI/DSI ports. Please note this is for libcamera support, *not* for</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span><span class="c1"># the legacy camera stack</span><span class="w"></span>
</span><span id="line-33"><span class="linenos">33</span><span class="na">camera_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-34"><span class="linenos">34</span><span class="na">display_auto_detect</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-35"><span class="linenos">35</span>
</span><span id="line-36"><span class="linenos">36</span><span class="c1"># Config settings specific to arm64</span><span class="w"></span>
</span><span id="line-37"><span class="linenos">37</span><span class="na">arm_64bit</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span>
</span><span id="line-40"><span class="linenos">40</span><span class="k">[cm4]</span><span class="w"></span>
</span><span id="line-41"><span class="linenos">41</span><span class="c1"># Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into</span><span class="w"></span>
</span><span id="line-42"><span class="linenos">42</span><span class="c1"># such a board)</span><span class="w"></span>
</span><span id="line-43"><span class="linenos">43</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">dwc2,dr_mode=host</span><span class="w"></span>
</span><span id="line-44"><span class="linenos">44</span>
</span><span id="line-45"><span class="linenos">45</span><span class="k">[all]</span><span class="w"></span>
</span><span id="line-46"><span class="hll"><span class="linenos">46</span><span class="na">dtoverlay</span><span class="o">=</span><span class="s">vc4-kms-v3d</span><span class="w"></span>
</span></span></pre></div>
</div>
<div class="topic">
<p class="topic-title">cmdline.txt</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos">1</span>zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
</span></pre></div>
</div>
<p>Please note that <tt class="docutils literal">cmdline.txt</tt> must consist of a <em>single line of text</em>.
Ignore any wrapping of text above.</p>
<div class="topic">
<p class="topic-title">user-data</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="c1">#cloud-config</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span>
</span><span id="line-3"><span class="hll"><span class="linenos"> 3</span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lubuntu</span><span class="w"></span>
</span></span><span id="line-4"><span class="linenos"> 4</span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="nt">locale</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">en_GB.UTF-8</span><span class="w"></span>
</span></span><span id="line-6"><span class="hll"><span class="linenos"> 6</span><span class="nt">timezone</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Europe/London</span><span class="w"></span>
</span></span><span id="line-7"><span class="linenos"> 7</span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="nt">keyboard</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="linenos"> 9</span><span class="w"> </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pc105</span><span class="w"></span>
</span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gb</span><span class="w"></span>
</span></span><span id="line-11"><span class="hll"><span class="linenos">11</span><span class="w"> </span><span class="nt">options</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ctrl:nocaps</span><span class="w"></span>
</span></span><span id="line-12"><span class="linenos">12</span>
</span><span id="line-13"><span class="linenos">13</span><span class="nt">user</span><span class="p">:</span><span class="w"></span>
</span><span id="line-14"><span class="hll"><span class="linenos">14</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s">"dave"</span><span class="w"></span>
</span></span><span id="line-15"><span class="linenos">15</span><span class="w"> </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span><span class="w"></span>
</span><span id="line-16"><span class="hll"><span class="linenos">16</span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="s">"Dave</span><span class="nv"> </span><span class="s">Jones"</span><span class="w"></span>
</span></span><span id="line-17"><span class="hll"><span class="linenos">17</span><span class="w"> </span><span class="nt">plain_text_passwd</span><span class="p">:</span><span class="w"> </span><span class="s">"raspberry"</span><span class="w"></span>
</span></span><span id="line-18"><span class="linenos">18</span><span class="w"> </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="s">"ALL=(ALL:ALL)</span><span class="nv"> </span><span class="s">ALL"</span><span class="w"></span>
</span><span id="line-19"><span class="hll"><span class="linenos">19</span><span class="w"> </span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"></span>
</span></span><span id="line-20"><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lp:waveform</span><span class="w"></span>
</span></span><span id="line-21"><span class="linenos">21</span>
</span><span id="line-22"><span class="linenos">22</span><span class="nt">write_files</span><span class="p">:</span><span class="w"></span>
</span><span id="line-23"><span class="hll"><span class="linenos">23</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/home/dave/.profile</span><span class="w"></span>
</span></span><span id="line-24"><span class="linenos">24</span><span class="w"> </span><span class="nt">append</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-25"><span class="linenos">25</span><span class="w"> </span><span class="nt">defer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-26"><span class="linenos">26</span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span><span class="w"></span>
</span><span id="line-27"><span class="linenos">27</span><span class="w"> </span><span class="no">export MOZ_ENABLE_WAYLAND=1</span><span class="w"></span>
</span><span id="line-28"><span class="linenos">28</span>
</span><span id="line-29"><span class="linenos">29</span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-30"><span class="linenos">30</span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-31"><span class="linenos">31</span><span class="nt">package_reboot_if_required</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-32"><span class="linenos">32</span>
</span><span id="line-33"><span class="linenos">33</span><span class="nt">packages</span><span class="p">:</span><span class="w"></span>
</span><span id="line-34"><span class="hll"><span class="linenos">34</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">lubuntu-desktop</span><span class="w"></span>
</span></span><span id="line-35"><span class="linenos">35</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-raspi-settings-desktop</span><span class="w"></span>
</span><span id="line-36"><span class="linenos">36</span>
</span><span id="line-37"><span class="linenos">37</span><span class="nt">snap</span><span class="p">:</span><span class="w"></span>
</span><span id="line-38"><span class="linenos">38</span><span class="w"> </span><span class="nt">commands</span><span class="p">:</span><span class="w"></span>
</span><span id="line-39"><span class="linenos">39</span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">snap install firefox</span><span class="w"></span>
</span></pre></div>
</div>
<p>You may be wondering if the ordering of these blocks matters. The answer is
“no”. The ordering of actions in <tt class="docutils literal"><span class="pre">cloud-init</span></tt> does <em>not</em> depend on the
ordering of the configuration file (and nor should it). The system is intended
to be <a class="reference external" href="https://en.wikipedia.org/wiki/Declarative_programming">declarative</a>; we are describing the state we wish to attain, not how to
obtain it.</p>
<p>This is why the <tt class="docutils literal">write_files</tt> section has options like <tt class="docutils literal">defer</tt> which adjust
the timing of these actions. By default, <tt class="docutils literal">write_files</tt> entries will always
occur early on so that written files can be available to other actions.</p>
<div class="topic">
<p class="topic-title">network-config</p>
<div class="highlight"><pre><span></span><span id="line-1"><span class="linenos"> 1</span><span class="nt">network</span><span class="p">:</span><span class="w"></span>
</span><span id="line-2"><span class="linenos"> 2</span><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span><span class="w"></span>
</span><span id="line-3"><span class="linenos"> 3</span><span class="w"> </span><span class="nt">wifis</span><span class="p">:</span><span class="w"></span>
</span><span id="line-4"><span class="linenos"> 4</span><span class="w"> </span><span class="nt">wlan0</span><span class="p">:</span><span class="w"></span>
</span><span id="line-5"><span class="hll"><span class="linenos"> 5</span><span class="w"> </span><span class="nt">regulatory-domain</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">GB</span><span class="w"></span>
</span></span><span id="line-6"><span class="linenos"> 6</span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-7"><span class="linenos"> 7</span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</span><span id="line-8"><span class="linenos"> 8</span><span class="w"> </span><span class="nt">access-points</span><span class="p">:</span><span class="w"></span>
</span><span id="line-9"><span class="hll"><span class="linenos"> 9</span><span class="w"> </span><span class="s">"my-wifi-ssid"</span><span class="p p-Indicator">:</span><span class="w"></span>
</span></span><span id="line-10"><span class="hll"><span class="linenos">10</span><span class="w"> </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="s">"my-wifi-password"</span><span class="w"></span>
</span></span></pre></div>
</div>
<p>With all those written, safely eject your card (or <span class="caps">SSD</span> drive), plug it into
your Pi and let it boot. This will take a … very … very … long … time.
Installing an entire hierarchy of desktop packages in this manner is not a
quick process, and the first boot will probably take at least 1 hour (I didn’t
time every installation during this test, but the <tt class="docutils literal"><span class="pre">cloud-init</span></tt> logs for the
Lubuntu run indicated setup on the microSD card took roughly 1½ hours).</p>
<p>However, once it’s complete, it should automatically reboot and you should find
yourself at a shiny new graphical desktop login! There’s still some horror to
sort out here (in particular the clash of networking configuration stacks), but
we’ll deal with that next time when we’ll also take a look at comparing the
current crop of desktops on Ubuntu, and see what’s changed in the last few
years. We’ll also compare them to the official Gnome desktop, and learn a few
more <tt class="docutils literal"><span class="pre">cloud-init</span></tt> tricks …</p>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="linux-mount" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>If you’re using Linux, you’ll also see the root partition
(“writable”) appear, but you can ignore this</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="oem-config" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td><tt class="docutils literal"><span class="pre">oem-config</span></tt>, derived from the <tt class="docutils literal">ubiquity</tt> installer. There
are moves afoot to replace this at some point (given <tt class="docutils literal">ubiquity</tt> is being
replaced with <tt class="docutils literal">subiquity</tt>), but nothing concrete as yet</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="no-systemd" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td><p class="first">For those violently allergic to systemd, the equivalent commands the
listing locales, timezones, and keyboard settings are:</p>
<dl class="last docutils">
<dt>locale:</dt>
<dd><tt class="docutils literal">locale <span class="pre">-a</span></tt></dd>
<dt>timezone:</dt>
<dd><tt class="docutils literal">(cd /usr/share/zoneinfo/posix; find <span class="pre">-type</span> f <span class="pre">-or</span> <span class="pre">-type</span> l <span class="pre">-printf</span> '%P\n')</tt></dd>
<dt>keyboard:</dt>
<dd>Read various sections in <tt class="docutils literal">/usr/share/X11/xkb/rules/base.lst</tt></dd>
</dl>
</td></tr>
</tbody>
</table>
</div>
Package configuration2020-04-16T00:00:00+01:002023-06-30T01:02:44+01:00Dave Jonestag:waldorf.waveform.org.uk,2020-04-16:/2020/package-configuration.html<p class="first last">Installing packages on first boot</p>
<p>In the <a class="reference external" href="https://waldorf.waveform.org.uk/2020/network-configuration.html">previous post</a> we saw how to configure networking on first boot with
<a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a>. If your Pi has a reliable network connection during that first
boot (preferably Ethernet, given the current wifi issue described in <a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1870346"><span class="caps">LP</span>:
#1870346</a>) you can also opt to have cloud-init install whatever packages
you’re going to need (and configure them too!) so your system is completely
ready for you when you login.</p>
<div class="section" id="updates">
<h2>Updates</h2>
<p>First, it’s useful to learn how to get the local package index up to date
(especially if you’re dealing with an old image). This can be done by adding
the following line to the <tt class="docutils literal"><span class="pre">user-data</span></tt> file (that one again!) on the boot partition:</p>
<pre class="code yaml literal-block">
<span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span>
</pre>
<p>If you also want to upgrade the system to the latest version of all installed
packages on the initial boot, you can add:</p>
<pre class="code yaml literal-block">
<span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span>
</pre>
</div>
<div class="section" id="installation">
<h2>Installation</h2>
<p>As you can tell, on Ubuntu these effectively run the “apt update” and “apt
upgrade” commands, but cloud-init also <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/topics/availability.html">supports several other distros</a>, hence
the rather generic naming of these options. How about installing extra
packages? This is also simple to arrange:</p>
<pre class="code yaml literal-block">
<span class="c1"># Install some things that Dave probably ought to consider including on</span><span class="w">
</span><span class="c1"># the images by default...</span><span class="w">
</span><span class="nt">packages</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">pi-bluetooth</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">iw</span>
</pre>
<p>You can specify a particular version of a package by using a list, but this
generally isn’t a good idea (there’s no guarantee that version is going to be
available unless you’re installing from, say, a repo you control like a <span class="caps">PPA</span>):</p>
<pre class="code yaml literal-block">
<span class="nt">packages</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">nginx-light</span><span class="p-Indicator">,</span><span class="w"> </span><span class="nv">1.17.9-0ubuntu3</span><span class="p-Indicator">]</span>
</pre>
<p>Speaking of which: what if you want to include a <span class="caps">PPA</span> as a source?</p>
<pre class="code yaml literal-block">
<span class="nt">apt</span><span class="p">:</span><span class="w">
</span><span class="nt">sources</span><span class="p">:</span><span class="w">
</span><span class="nt">my-ppa</span><span class="p">:</span><span class="w">
</span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">"ppa:waveform/pibootctl"</span><span class="w"> </span><span class="c1"># quote the source</span>
</pre>
<p>This may seem like an overly convoluted series of structures (“source” within a
label within “sources” within “apt”) but the reason for this is that there are
a great many <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/topics/examples.html#additional-apt-configuration-and-repositories">options for apt</a>, and a number of different means for specifying
third party repos (including importing of signing keys, and templates for
deriving new repos from existing ones).</p>
</div>
<div class="section" id="configuration">
<h2>Configuration</h2>
<p>A couple more features are worth introducing in the context of installing
packages. Firstly, the ability to write arbitrary files. This is particularly
useful for providing configuration for packages you’ve installed:</p>
<pre class="code yaml literal-block">
<span class="nt">write_files</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">/etc/default/keyboard</span><span class="w">
</span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">|</span><span class="w">
</span><span class="no"># KEYBOARD CONFIGURATION FILE</span><span class="w">
</span><span class="no">XKBMODEL="pc105"</span><span class="w">
</span><span class="no">XKBLAYOUT="gb"</span><span class="w">
</span><span class="no">XKBVARIANT=""</span><span class="w">
</span><span class="no">XKBOPTIONS="ctrl: nocaps"</span><span class="w">
</span><span class="no">BACKSPACE="guess"</span>
</pre>
<p>And finally, the ultimate blunt tool of “runcmd” which effectively lets you run
arbitrary commands as root on the first boot; <em>use with caution</em>! In this case
we can use it to set the wireless regulatory domain:</p>
<pre class="code yaml literal-block">
<span class="nt">runcmd</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">iw reg set GB</span>
</pre>
</div>
<div class="section" id="putting-it-all-together">
<h2>Putting it all together</h2>
<p>Here’s a <tt class="docutils literal"><span class="pre">user-data</span></tt> file I use when testing Pi daily images. It sets up the
Pi so I can access it over <span class="caps">SSH</span>, importing my keys from GitHub, installs some
extra packages for WiFi and Bluetooth, configures the WiFi regulatory domain,
adds the <span class="caps">PPA</span> for <a class="reference external" href="https://pibootctl.readthedocs.io/">pibootctl</a> (a little project I’ve been working on for boot
configuration manipulation):</p>
<div class="topic">
<p class="topic-title">user-data</p>
<pre class="code yaml literal-block">
<span class="ln"> 1 </span><span class="c1">#cloud-config</span><span class="w">
</span><span class="ln"> 2 </span><span class="w">
</span><span class="ln"> 3 </span><span class="w"></span><span class="nt">chpasswd</span><span class="p">:</span><span class="w">
</span><span class="ln"> 4 </span><span class="w"> </span><span class="nt">expire</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln"> 5 </span><span class="w"> </span><span class="nt">list</span><span class="p">:</span><span class="w">
</span><span class="ln"> 6 </span><span class="w"> </span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">ubuntu:ubuntu</span><span class="w">
</span><span class="ln"> 7 </span><span class="w">
</span><span class="ln"> 8 </span><span class="w"></span><span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">pitest</span><span class="w">
</span><span class="ln"> 9 </span><span class="w">
</span><span class="ln">10 </span><span class="w"></span><span class="nt">apt</span><span class="p">:</span><span class="w">
</span><span class="ln">11 </span><span class="w"> </span><span class="nt">sources</span><span class="p">:</span><span class="w">
</span><span class="ln">12 </span><span class="w"> </span><span class="nt">my-ppa</span><span class="p">:</span><span class="w">
</span><span class="ln">13 </span><span class="w"> </span><span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="s">"ppa:waveform/pibootctl"</span><span class="w"> </span><span class="c1"># the quotes are mandatory</span><span class="w">
</span><span class="ln">14 </span><span class="w">
</span><span class="ln">15 </span><span class="w"></span><span class="nt">package_update</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="ln">16 </span><span class="w"></span><span class="nt">package_upgrade</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="ln">17 </span><span class="w"></span><span class="nt">packages</span><span class="p">:</span><span class="w">
</span><span class="ln">18 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">pi-bluetooth</span><span class="w">
</span><span class="ln">19 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">iw</span><span class="w">
</span><span class="ln">20 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">pibootctl</span><span class="w">
</span><span class="ln">21 </span><span class="w">
</span><span class="ln">22 </span><span class="w"></span><span class="nt">runcmd</span><span class="p">:</span><span class="w">
</span><span class="ln">23 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">iw reg set GB</span><span class="w">
</span><span class="ln">24 </span><span class="w">
</span><span class="ln">25 </span><span class="w"></span><span class="nt">ssh_pwauth</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln">26 </span><span class="w">
</span><span class="ln">27 </span><span class="w"></span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w">
</span><span class="ln">28 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">gh:waveform80</span><span class="w">
</span><span class="ln">29 </span><span class="w">
</span><span class="ln">30 </span><span class="w"></span><span class="nt">write_files</span><span class="p">:</span><span class="w">
</span><span class="ln">31 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">/etc/default/keyboard</span><span class="w">
</span><span class="ln">32 </span><span class="w"> </span><span class="nt">content</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">|</span><span class="w">
</span><span class="ln">33 </span><span class="w"> </span><span class="no"># KEYBOARD CONFIGURATION FILE</span><span class="w">
</span><span class="ln">34 </span><span class="w"> </span><span class="no">XKBMODEL="pc105"</span><span class="w">
</span><span class="ln">35 </span><span class="w"> </span><span class="no">XKBLAYOUT="gb"</span><span class="w">
</span><span class="ln">36 </span><span class="w"> </span><span class="no">XKBVARIANT=""</span><span class="w">
</span><span class="ln">37 </span><span class="w"> </span><span class="no">XKBOPTIONS="ctrl: nocaps"</span><span class="w">
</span><span class="ln">38 </span><span class="w"> </span><span class="no">BACKSPACE="guess"</span><span class="w">
</span><span class="ln">39 </span><span class="w">
</span><span class="ln">40 </span><span class="w"></span><span class="nt">runcmd</span><span class="p">:</span><span class="w">
</span><span class="ln">41 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">reboot</span>
</pre>
</div>
<p>At the moment this file lives on my desktop and, after flashing a fresh image,
the first thing I do is copy that file onto the boot partition, replacing the
existing <tt class="docutils literal"><span class="pre">user-data</span></tt>. Then I boot the Pi and leave it for a few minutes to
sort everything out!</p>
<p>Hopefully that gives you some ideas for playing with. And remember, you can
throw these same configurations at various cloud instances too (which can be
quite handy if you ever need to scale things up temporarily!)</p>
</div>
<div class="section" id="coming-up">
<h2>Coming Up</h2>
<p>Next I’m going to take a short break and see if I can set up some form of
comments here (probably via the lazy disqus route), and then I might delve into
a series on pibootctl or something.</p>
</div>
Network configuration2020-04-10T00:00:00+01:002023-06-30T01:02:44+01:00Dave Jonestag:waldorf.waveform.org.uk,2020-04-10:/2020/network-configuration.html<p class="first last">How cloud-init talks to netplan to configure the network</p>
<p>In the <a class="reference external" href="https://waldorf.waveform.org.uk/2020/setting-up-users.html">previous post</a> we saw how to configure multiple different users via
<tt class="docutils literal"><span class="pre">user-data</span></tt>, one of the <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> configuration files. This time, we’ll
turn our attention to <tt class="docutils literal"><span class="pre">network-config</span></tt> which is probably the most important
configuration file aside from <tt class="docutils literal"><span class="pre">user-data</span></tt> as it tells <a class="reference external" href="https://netplan.io/">Netplan</a> what to do
when setting up the network.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">What’s <a class="reference external" href="https://netplan.io/">Netplan</a>? It’s a tool used on Ubuntu used to present a common
interface to whatever happens to manage the network. For instance, on
desktops this is typically Network Manager, while servers tend to use
systemd’s networkd service. Netplan can “render” a configuration to work
with either of these systems.</p>
</div>
<div class="section" id="network-config">
<h2>network-config</h2>
<p>This file is basically just a typical <a class="reference external" href="https://netplan.io/reference">Netplan configuration</a> minus the root
“network:” value. By default it contains the following on the Pi images:</p>
<div class="topic">
<p class="topic-title">network-config</p>
<pre class="code yaml literal-block">
<span class="ln"> 1 </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">2</span><span class="w">
</span><span class="ln"> 2 </span><span class="w"></span><span class="nt">ethernets</span><span class="p">:</span><span class="w">
</span><span class="ln"> 3 </span><span class="w"> </span><span class="nt">eth0</span><span class="p">:</span><span class="w">
</span><span class="ln"> 4 </span><span class="w"> </span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="ln"> 5 </span><span class="w"> </span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="ln"> 6 </span><span class="w"></span><span class="c1">#wifis:</span><span class="w">
</span><span class="ln"> 7 </span><span class="w"></span><span class="c1"># wlan0:</span><span class="w">
</span><span class="ln"> 8 </span><span class="w"></span><span class="c1"># dhcp4: true</span><span class="w">
</span><span class="ln"> 9 </span><span class="w"></span><span class="c1"># optional: true</span><span class="w">
</span><span class="ln">10 </span><span class="w"></span><span class="c1"># access-points:</span><span class="w">
</span><span class="ln">11 </span><span class="w"></span><span class="c1"># myhomewifi:</span><span class="w">
</span><span class="ln">12 </span><span class="w"></span><span class="c1"># password: "S3kr1t"</span><span class="w">
</span><span class="ln">13 </span><span class="w"></span><span class="c1"># myworkwifi:</span><span class="w">
</span><span class="ln">14 </span><span class="w"></span><span class="c1"># password: "correct battery horse staple"</span><span class="w">
</span><span class="ln">15 </span><span class="w"></span><span class="c1"># workssid:</span><span class="w">
</span><span class="ln">16 </span><span class="w"></span><span class="c1"># auth:</span><span class="w">
</span><span class="ln">17 </span><span class="w"></span><span class="c1"># key-management: eap</span><span class="w">
</span><span class="ln">18 </span><span class="w"></span><span class="c1"># method: peap</span><span class="w">
</span><span class="ln">19 </span><span class="w"></span><span class="c1"># identity: "me@example.com"</span><span class="w">
</span><span class="ln">20 </span><span class="w"></span><span class="c1"># password: "passw0rd"</span><span class="w">
</span><span class="ln">21 </span><span class="w"></span><span class="c1"># ca-certificate: /etc/my_ca.pem</span>
</pre>
</div>
<p>On line 1, “version:” just declares the version of the Netplan schema that the
file conforms to (this should be “2”).</p>
<p>On line 2, the “ethernets:” value starts which sets up the “eth0” interface to
use <span class="caps">DHCP</span> for IPv4 (we haven’t specified anything for IPv6) and marks the
interface optional (indicating we shouldn’t wait for it to come up on boot,
just in case there’s no cable plugged in).</p>
<p>On line 6 onwards is a big “wifis:” section which is commented out (the “#”
prefix), and which contains several examples of common WiFi configurations.
We’ll explore this in the next section.</p>
<p>What should we do if we wanted to use a static <span class="caps">IP</span> configuration for eth0
instead of <span class="caps">DHCP</span>? The following is an example block which should be reasonably
obvious to anyone familiar with <span class="caps">IP</span> networking.</p>
<pre class="code yaml literal-block">
<span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">2</span><span class="w">
</span><span class="nt">ethernets</span><span class="p">:</span><span class="w">
</span><span class="nt">eth0</span><span class="p">:</span><span class="w">
</span><span class="nt">addresses</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">192.168.0.20/24</span><span class="w">
</span><span class="nt">gateway4</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">192.168.0.1</span><span class="w">
</span><span class="nt">nameservers</span><span class="p">:</span><span class="w">
</span><span class="nt">search</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">mydomain</span><span class="p-Indicator">]</span><span class="w">
</span><span class="nt">addresses</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">192.168.0.1</span><span class="p-Indicator">,</span><span class="w"> </span><span class="nv">8.8.8.8</span><span class="p-Indicator">]</span><span class="w">
</span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span>
</pre>
<p>It is important to remember that “addresses:” takes a <em>list</em> of addresses (as
an interface can have multiple).</p>
</div>
<div class="section" id="wifi-configuration">
<h2>wifi configuration</h2>
<p>This is much the same as ethernet (as you can probably see from the commented
out example in the default file). The only major difference is the extra
“access-points” sub-value. Under this, you can list all the wifi access points
you regularly connect to, and the credentials required for each.</p>
<p>For example, let’s assume your home router is called “<span class="caps">BT</span>-1234” with password “a
very long password”, but you also have an extender called “wifi_ex” which has
the (slightly less secure) password “passw0rd”. In this case you might use the
following configuration:</p>
<pre class="code yaml literal-block">
<span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">2</span><span class="w">
</span><span class="nt">wifis</span><span class="p">:</span><span class="w">
</span><span class="nt">wlan0</span><span class="p">:</span><span class="w">
</span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">access-points</span><span class="p">:</span><span class="w">
</span><span class="s">"BT-1234"</span><span class="p-Indicator">:</span><span class="w">
</span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="s">"a</span><span class="nv"> </span><span class="s">very</span><span class="nv"> </span><span class="s">long</span><span class="nv"> </span><span class="s">password"</span><span class="w">
</span><span class="s">"wifi_ex"</span><span class="p-Indicator">:</span><span class="w">
</span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="s">"passw0rd"</span><span class="w">
</span><span class="nt">ethernets</span><span class="p">:</span><span class="w">
</span><span class="nt">eth0</span><span class="p">:</span><span class="w">
</span><span class="nt">dhcp4</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">optional</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span>
</pre>
<p>Note that it doesn’t matter what order the top-level values appear in. I tend
to write “version” first, followed by “ethernets” but it really doesn’t matter.
The same goes for sub-values of values; place them in whatever order you want.</p>
</div>
<div class="section" id="later-changes">
<h2>Later changes</h2>
<p>What does cloud-init do with the <tt class="docutils literal"><span class="pre">network-config</span></tt> file? Roughly speaking, it
copies it (with an additional root “network:” value) to
<tt class="docutils literal"><span class="pre">/etc/netplan/50-cloud-init.yaml</span></tt> (the <a class="reference external" href="https://netplan.io/reference">Netplan configuration</a> consists of
all <a class="reference external" href="https://yaml.org/"><span class="caps">YAML</span></a> files under <tt class="docutils literal">/etc/netplan</tt>) and then applies it.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>Unfortunately, there’s currently a bug here. While cloud-init will happily
<em>copy</em> your WiFi configuration to Netplan, it won’t (currently) apply it
automatically. To do that, you need to reboot your Pi afterwards (or run
<tt class="docutils literal">sudo netplan apply</tt> from the command prompt, assuming you have a
keyboard attached).</p>
<p class="last">The issue is being tracked under <a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1870346"><span class="caps">LP</span>: #1870346</a> for those interested.</p>
</div>
<p>For users of <a class="reference external" href="https://www.raspberrypi.org/downloads/raspbian/">Raspbian</a> this probably feels similar to its facility of
<a class="reference external" href="https://www.raspberrypi.org/documentation/configuration/boot_folder.md">copying a file named wpa_supplicant.conf</a> on the boot partition. The main
difference is that this deals with all interfaces rather than just wifi.</p>
<p>Remember that <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> only deals with the very first boot. What happens
if you want to change your network configuration later? In this case simply
edit the file cloud-init created, <tt class="docutils literal"><span class="pre">/etc/netplan/50-cloud-init.yaml</span></tt>, and run
<tt class="docutils literal">sudo netplan apply</tt> (or reboot).</p>
</div>
<div class="section" id="back-to-user-data">
<h2>Back to user-data</h2>
<p>While we’re looking at network related stuff, there’s a couple of settings in
<tt class="docutils literal"><span class="pre">user-data</span></tt> we should cover. First is “hostname” which can be used to <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/topics/modules.html#set-hostname">set
the hostname</a> of a freshly minted machine. It’s as simple as specifying this
at the top level:</p>
<pre class="code yaml literal-block">
<span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">waldorf</span>
</pre>
<p>Whether this is honoured by the local <span class="caps">DNS</span> server will depend on its
configuration. If you use <a class="reference external" href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> as your local <span class="caps">DHCP</span>/<span class="caps">DNS</span> server (as I do)
then it should work just fine.</p>
<p>System time can often be an issue on Pis, which lack a <span class="caps">RTC</span>. <span class="caps">NTP</span> is the usual
solution to this for any Pi connected to a network. Often, the <span class="caps">DHCP</span> server will
supply the address of an <span class="caps">NTP</span> server, or the <span class="caps">NTP</span>’s default configuration will be
sufficient. However in some cases you may need to configure the <span class="caps">NTP</span> servers to
query manually. Again, you can use cloud-init to <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/topics/modules.html#ntp">set <span class="caps">NTP</span> up</a>:</p>
<pre class="code yaml literal-block">
<span class="nt">ntp</span><span class="p">:</span><span class="w">
</span><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">true</span><span class="w">
</span><span class="nt">servers</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">ntp.server.local</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">ntp.ubuntu.com</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">192.168.23.2</span>
</pre>
<p>Cloud-init knows how to configure a reasonable variety of <span class="caps">NTP</span> clients and can
adapt the configuration above to their particular format. But how to get such a
client installed on the very first boot? That’s a topic we’ll leave for next time…</p>
</div>
Setting up users2020-04-08T00:00:00+01:002022-10-20T15:44:59+01:00Dave Jonestag:waldorf.waveform.org.uk,2020-04-08:/2020/setting-up-users.html<p class="first last">A deeper look at user creation in cloud-init’s user-data file</p>
<p>In the <a class="reference external" href="https://waldorf.waveform.org.uk/2020/securing-your-ubuntu-pi.html">previous post</a> we had a quick look at the <tt class="docutils literal"><span class="pre">user-data</span></tt> configuration
file for <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a>. In this post, we’ll have a more extensive look at some
of the other options for configuring users in this file.</p>
<div class="section" id="different-passwords">
<h2>Different Passwords</h2>
<p>We’ve seen how <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> is told to set the initial user password, but
there’s a few more possibilities there we haven’t seen yet. Have a look at the
following example:</p>
<pre class="code yaml literal-block">
<span class="ln">1 </span><span class="nt">chpasswd</span><span class="p">:</span><span class="w">
</span><span class="ln">2 </span><span class="w"> </span><span class="nt">expire</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln">3 </span><span class="w"> </span><span class="nt">list</span><span class="p">:</span><span class="w">
</span><span class="ln">4 </span><span class="w"> </span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">ubuntu:ubuntu</span><span class="w">
</span><span class="ln">5 </span><span class="w"> </span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">root:$1$1dE3dcLz$8iWGkDxx9SCWdQfkPXbCE/</span><span class="w">
</span><span class="ln">6 </span><span class="w"> </span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">pi:RANDOM</span>
</pre>
<p>Here, as last time, “expire” is false so you won’t be prompted to change the
password on first login. We’ve also specified a password for a pre-existing
user (root, not that this is necessarily encouraged on a system with “sudo”).
Finally, the special value “<span class="caps">RANDOM</span>” tells <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> to generate a
completely random password for the “pi” user. This will be output on the
console, and in the <tt class="docutils literal"><span class="pre">/var/log/cloud-init-output.log</span></tt> file.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p>You may want to erase (or at least restrict access to) the
<tt class="docutils literal"><span class="pre">cloud-init-output.log</span></tt> file if you choose to use <span class="caps">RANDOM</span> passwords.</p>
<p class="last">It is also worth noting (as the <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> docs do) that providing
hashes of passwords is <em>not</em> necessarily secure. You may want to try
running the hash above through something like <a class="reference external" href="https://snapcraft.io/john-the-ripper">John the Ripper</a> to
convince yourself of this!</p>
</div>
</div>
<div class="section" id="different-users">
<h2>Different Users</h2>
<p>We’ve already seen how <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> creates a default “ubuntu” user, and for
many purposes that’s enough. What would you do if you wanted to create other
users besides this, and can we import different sets of <span class="caps">SSH</span> keys to each user?
Here’s another example <tt class="docutils literal"><span class="pre">user-data</span></tt>:</p>
<pre class="code yaml literal-block">
<span class="ln"> 1 </span><span class="nt">groups</span><span class="p">:</span><span class="w">
</span><span class="ln"> 2 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">robot</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">robot</span><span class="p-Indicator">]</span><span class="w">
</span><span class="ln"> 3 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">robotics</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">robot</span><span class="p-Indicator">]</span><span class="w">
</span><span class="ln"> 4 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">pi</span><span class="w">
</span><span class="ln"> 5 </span><span class="w">
</span><span class="ln"> 6 </span><span class="w"></span><span class="nt">users</span><span class="p">:</span><span class="w">
</span><span class="ln"> 7 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">default</span><span class="w">
</span><span class="ln"> 8 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">robot</span><span class="w">
</span><span class="ln"> 9 </span><span class="w"> </span><span class="nt">gecos</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Mr. Robot</span><span class="w">
</span><span class="ln">10 </span><span class="w"> </span><span class="nt">primary_group</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">robot</span><span class="w">
</span><span class="ln">11 </span><span class="w"> </span><span class="nt">groups</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">users</span><span class="p-Indicator">]</span><span class="w">
</span><span class="ln">12 </span><span class="w"> </span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">gh:example</span><span class="w">
</span><span class="ln">13 </span><span class="w"> </span><span class="nt">passwd</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">$5$hkui88$nvZgIle31cNpryjRfO9uArF7DYiBcWEnjqq7L1AQNN3</span>
</pre>
<p>The “groups” value lists the groups to create, and optionally the members they
should have. Here we set up three groups named “robot”, “robotics”, and “pi”.
The “robot” and “robotics” groups will each have a single member, the “robot”
user, while the “pi” group will start off with no members.</p>
<p>The “users” value lists all the users to create, along with their details. Here
we create two users: the default “ubuntu” user which is simply represented by
the “default” entry at the top. You can remove this if you don’t want the
default user.</p>
<p>Then there’s the aforementioned “robot” user. Various fields give this user an
initial password (in the form of a hash under “passwd”), tell the
<a class="reference external" href="https://launchpad.net/ssh-import-id">ssh-import-id</a> utility to import <span class="caps">SSH</span> keys from the “example” user on
<a class="reference external" href="https://github.com/">GitHub</a>, and additionally places the user in the “users” group.</p>
<p>There’s an absolute pile of options that be specified for users; have a look at
the <a class="reference external" href="https://cloudinit.readthedocs.io/en/latest/topics/modules.html#users-and-groups">Users and Groups</a> section of the cloud-init docs for more information.</p>
</div>
<div class="section" id="coming-up">
<h2>Coming Up</h2>
<p>Next, we’ll take a break from <tt class="docutils literal"><span class="pre">user-data</span></tt> to look at the other important
configuration file for <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a>: <tt class="docutils literal"><span class="pre">network-config</span></tt>.</p>
</div>
Securing your Ubuntu Pi2020-04-02T00:00:00+01:002021-10-15T22:43:12+01:00Dave Jonestag:waldorf.waveform.org.uk,2020-04-02:/2020/securing-your-ubuntu-pi.html<p class="first last">Using cloud-init configuration to secure your first boot.</p>
<p>One of the neat features of Raspbian is the ability to set up <span class="caps">SSH</span> out of the
box by placing an <a class="reference external" href="https://www.raspberrypi.org/documentation/configuration/boot_folder.md">ssh file on the boot partition</a>. This is a security feature
to ensure that your Pi isn’t booted up with <span class="caps">SSH</span> for remote access enabled, plus
a widely known default username and password (pi / raspberry) which has full
“sudo” rights before you’ve had a chance to <a class="reference external" href="https://www.raspberrypi.org/documentation/configuration/security.md">change it</a>.</p>
<p>On the surface, Ubuntu on the Pi has some similarities here, and some differences:</p>
<ul class="simple">
<li>As with Raspbian, there’s a default username and password (ubuntu / ubuntu).</li>
<li>As with Raspbian, the default user has full “sudo” rights.</li>
<li>Unlike Raspbian, <span class="caps">SSH</span> is enabled by default. This is an obvious security
problem given the above points.</li>
<li>To mitigate this, unlike Raspbian, Ubuntu forces you to change your password
on first login.</li>
</ul>
<p>Still, doesn’t this leave a (hopefully brief) period of time when your Pi is
potentially network connected, with an active <span class="caps">SSH</span> daemon, and a widely known
default username and password combination with full root access? Yes … it
does. Can we do better than this? Yes, with …</p>
<div class="section" id="cloud-init">
<h2>cloud-init</h2>
<p>First, we’ll see what I usually stick in the <tt class="docutils literal"><span class="pre">user-data</span></tt> configuration file
on a freshly flashed <span class="caps">SD</span> card, then we’ll dissect it to see what’s going on and
what else you can do with it!</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The file’s name is literally <tt class="docutils literal"><span class="pre">user-data</span></tt> with no extension. It’s
essentially a text file though, so feel free to open it in Notepad or any
other plain text editor.</p>
</div>
<p>This file is part of the configuration for <a class="reference external" href="https://cloudinit.readthedocs.io/">cloud-init</a> and you’ll find it on
the boot partition. This is the first partition on the card and, if you’re
sticking the card in a Windows or Mac <span class="caps">OS</span> X machine, the only partition that’ll
appear (because it’s formatted <span class="caps">FAT</span>).</p>
<p>Without further ado, here’s the <span class="caps">TL</span>;<span class="caps">DR</span> version:</p>
<pre class="code yaml literal-block">
<span class="ln"> 1 </span><span class="nt">ssh_pwauth</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln"> 2 </span><span class="w">
</span><span class="ln"> 3 </span><span class="w"></span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w">
</span><span class="ln"> 4 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">lp:waveform</span><span class="w">
</span><span class="ln"> 5 </span><span class="w">
</span><span class="ln"> 6 </span><span class="w"></span><span class="nt">chpasswd</span><span class="p">:</span><span class="w">
</span><span class="ln"> 7 </span><span class="w"> </span><span class="nt">expire</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln"> 8 </span><span class="w"> </span><span class="nt">list</span><span class="p">:</span><span class="w">
</span><span class="ln"> 9 </span><span class="w"> </span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">ubuntu:ubuntu</span>
</pre>
<p>What does all this <a class="reference external" href="https://yaml.org/"><span class="caps">YAML</span></a> mean?</p>
<p>Line 1 configures <span class="caps">SSH</span> to disable password authentication, so that’s our
security hole fixed (this happens before the default user is created). The
username and password may be well known but they’re now useless for remote
access. Well that was easy, all done and … oh, wait a minute. How should I
access the Pi remotely now?</p>
<p>Lines 3-4 take care of this. These tell cloud-init to use the incredibly useful
<a class="reference external" href="https://launchpad.net/ssh-import-id">ssh-import-id</a> utility to grab my public <span class="caps">SSH</span> keys from <a class="reference external" href="https://launchpad.net/">Launchpad</a> (that’s
the “lp:” prefix, you can also use “gh:” for <a class="reference external" href="https://github.com/">GitHub</a>) and install them as
authorized keys for all users that cloud-init creates.</p>
<p>Lines 6-9 tell cloud-init that the “ubuntu” user (which it will create by
default) should have the password “ubuntu” and that I don’t want it expired (so
it won’t prompt me to change it on first login). Half the time I’m dealing with
an ephemeral image I won’t be keeping around anyway, so I don’t much care about
changing the password, and on the occassions that I do want to keep the image,
I don’t want to be bugged about the password on that first login.</p>
<p>And that’s it! I boot my Pi for the first time (making sure it has an Ethernet
connection), wait a bit while cloud-init does its thing but, after about a
minute, my Pi has an “ubuntu” user I can access over <span class="caps">SSH</span> with public-key
authentication and no gaping security holes.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>cloud-init performs <em>initial</em> set up. That is to say, it only performs set
up on the very first boot. If you want to configure your Pi with cloud-init
you need to make changes to the configuration (detailed below) <em>before</em>
booting your Pi for the first time.</p>
<p>If you wish to re-run cloud-init at a later time, you can do so with the
following command but be aware that some settings may not work as expected
(because users will already have been created, files already written, etc. etc.):</p>
<pre class="code console literal-block">
<span class="gp">$ </span>sudo cloud-init clean --logs --reboot
</pre>
<p class="last">In general, consider this guide relevant for first boot situations <em>only</em>.</p>
</div>
</div>
<div class="section" id="yaml-refresher">
<h2><span class="caps">YAML</span> Refresher</h2>
<p>In case you’re wondering what the format of the file above is, it’s <a class="reference external" href="https://yaml.org/"><span class="caps">YAML</span></a>. It
may be useful to have a quick refresher course in <a class="reference external" href="https://yaml.org/"><span class="caps">YAML</span></a> as that’s what
<tt class="docutils literal"><span class="pre">user-data</span></tt> (and all the other cloud-init configuration files) are written
in. Here’s the file we saw above again, with some slight alterations for the
purposes of demonstration:</p>
<pre class="code yaml literal-block">
<span class="ln"> 1 </span><span class="nt">ssh_pwauth</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln"> 2 </span><span class="w">
</span><span class="ln"> 3 </span><span class="w"></span><span class="nt">ssh_import_id</span><span class="p">:</span><span class="w">
</span><span class="ln"> 4 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">lp:waveform</span><span class="w">
</span><span class="ln"> 5 </span><span class="w"></span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">gh:foobar</span><span class="w">
</span><span class="ln"> 6 </span><span class="w">
</span><span class="ln"> 7 </span><span class="w"></span><span class="nt">chpasswd</span><span class="p">:</span><span class="w">
</span><span class="ln"> 8 </span><span class="w"> </span><span class="nt">expire</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">false</span><span class="w">
</span><span class="ln"> 9 </span><span class="w"> </span><span class="nt">list</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">ubuntu</span><span class="p-Indicator">:</span><span class="nv">ubuntu</span><span class="p-Indicator">,</span><span class="w"> </span><span class="nv">pi</span><span class="p-Indicator">:</span><span class="nv">raspberry</span><span class="p-Indicator">]</span>
</pre>
<ul>
<li><p class="first">There are three top-level values: “ssh_pwauth”, “ssh_import_id”, and “chpasswd”</p>
</li>
<li><p class="first"><span class="dquo">“</span>ssh_pwauth” is a simple value set to “false”. In all cases, the name of a
value is written prior to a colon (“:”)</p>
</li>
<li><p class="first">Next “ssh_import_id” is a <em>list</em> value. There’s two ways of writing lists in
<a class="reference external" href="https://yaml.org/"><span class="caps">YAML</span></a> and this is the “long-hand” variant: “-” prefixed items, one per line
below the name of the value:</p>
<pre class="code yaml literal-block">
<span class="nt">mylist</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">Item 1</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">Item 2</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="l-Scalar-Plain">Item 3</span>
</pre>
</li>
<li><p class="first">The other way of writing lists is the “short-hand” variant: comma-separated
values enclosed in square brackets. The list above could equally well be
written like this:</p>
<pre class="code yaml literal-block">
<span class="nt">mylist</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">[</span><span class="nv">Item 1</span><span class="p-Indicator">,</span><span class="w"> </span><span class="nv">Item 2</span><span class="p-Indicator">,</span><span class="w"> </span><span class="nv">Item 3</span><span class="p-Indicator">]</span>
</pre>
</li>
<li><p class="first">Finally “chpasswd” is a compound value, containing two other values. This is
indicating by the indentation before the names of the two sub-values,
“expire” and “list”</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">You must <em>not</em> mix indentation styles from one line to the next (as in
Python). When editing this file you are strongly recommended to stick to
spaces for indentation; do <em>not</em> use the Tab key (unless you’re certain
your editor is configured to expand tabs to spaces)!</p>
</div>
</li>
<li><p class="first">As with lists, there’s a short-hand variant for compound values too:
command-separated elements enclosed in curly braces. The following two
declarations are equivalent in <a class="reference external" href="https://yaml.org/"><span class="caps">YAML</span></a>:</p>
<pre class="code yaml literal-block">
<span class="nt">character</span><span class="p">:</span><span class="w"> </span><span class="p-Indicator">{</span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="nv">Zaphod Beeblebrox</span><span class="p-Indicator">,</span><span class="nt"> age</span><span class="p">:</span><span class="w"> </span><span class="nv">42</span><span class="p-Indicator">}</span><span class="w">
</span><span class="nt">character</span><span class="p">:</span><span class="w">
</span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Zaphod Beeblebrox</span><span class="w">
</span><span class="nt">age</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">42</span>
</pre>
</li>
<li><p class="first">List items can be simple values, as we’ve seen above or they can be compound
values themselves. For example:</p>
<pre class="code yaml literal-block">
<span class="nt">characters</span><span class="p">:</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Oberon</span><span class="w">
</span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">King of the fairies</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Titania</span><span class="w">
</span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Queen of the fairies</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Bottom</span><span class="w">
</span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">a weaver</span><span class="w">
</span><span class="p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">Robin Goodfellow</span><span class="w">
</span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l-Scalar-Plain">a mischievous sprite</span>
</pre>
</li>
</ul>
</div>
<div class="section" id="coming-up">
<h2>Coming Up</h2>
<p>In the next post we’ll take a look in more detail at the <tt class="docutils literal"><span class="pre">user-data</span></tt> file and
see how to create multiple different users, assigning them different <span class="caps">SSH</span> keys.</p>
</div>