Thanks again! Based on the above info I managed to tick off pretty much all my main requirements - primarily by editing files in the tree inside the image that was produced by ubuntu-image
. I imagine some of this is not-quite-best-practice, but I’ll share my approach here with the intent of maybe helping others and getting some feedback on what can be improved.
Thanks to @kyleN for providing some scripts that facilitate several of these steps, at GitHub - knitzsche/core-build-scripts
Network configuration
Simply placing a netplan file inside system-data/etc/netplan/
did the trick. It gets picked up on first boot, and the device for example successfully connects to WiFi.
By the way, I did not actually see what further benefit I would derive from using cloud-init, and did not end up using it here.
Creating a system user for SSH authentication
As suggested by @ogra, creating a system user assertion and then applying it by copying it to a USB stick that’s inserted during first boot (or at any time, really) allowed to me to get more or less what I need.
I created the assertion by following the steps in https://docs.ubuntu.com/core/en/guides/manage-devices/. The make-system-user
script used for that example sets up a user with password authentication instead of SSH key authentication, but that’s fine for now. Putting the model together manually (rather than using the helper script) clearly allows you to also supply a public key.
Question 1: Is it possible to incorporate a system user assertion into an image directly, rather than installing it from a USB stick?
Question 2: It’s not totally clear to me how the system-user assertion is actually used for SSO authentication, in a way that for example allows the downloading of private snaps. The created system user doesn’t appear to have access to private snaps published by the authority/brand that signed the assertion. But that’s not currently a high priority for us, so am happy to let it be for now.
Setting environment variables
Creating a system-data/etc/environment
file in the image got the job done just fine.
Auto-connection of interfaces
This was a relatively tough one; while there is concept for how this would be done, it’s not clear to me what the current stage of implementation is (Interface connection from gadget in firstboot). In the end I did something pretty ugly, which was to create a systemd service file that stipulates the execution of commands along the lines of /usr/bin/snap connect [<snap>:<plug>] [<snap>:<slot>]
, and activate it (i.e. create symlink to it under system-data/etc/systemd/system/multi-user.target.wants
on the image).
If anyone has any suggestions as to how to do this in a less ugly way, I’d love to hear them.
Bonus: display a message on boot screen
That doesn’t quite seem to do it. On my system I just get /etc/issue
followed by a plain login prompt:
Of course MOTD is displayed once I log in, but what I’d like to do is have the output of a particular bash script be shown on the bootup screen already. Something more like what is shown on boot once console-conf
is complete
…but with content that I define. Is this achievable? Am I missing something with respect to MOTD?