First-boot / device initialization UX

This is a longer post on user experience issues I’m struggling with during first-boot / initialization of a RasPi-based Ubuntu Core appliance. We have a gadget image which is distributed as software-only, i.e. our (non-technical) users flash the image themselves – so a clean first-boot experience is absolutely necessary. The software is a kiosk-style application where users are not expected to connect input devices.

With this thread, I’d like to:

  • Validate my assumptions about snapd/device workflows – please do tell me if I missed something from the docs!
  • Maybe gather workarounds from more experienced developers
  • Provide feedback for first-boot / initialization improvements to Ubuntu Core / snapd developers

I have described my current workflow in this thread regarding snap refreshes. Basically, I’m flashing a fresh image from ubuntu-image onto an SD card, wait for the seeding to finish and then resize + grab an image from the SD card to distribute.

This is time-consuming and I run into all sorts of trouble: For example, snapd force-refreshes all snaps right after a user has set up the image for internet access (see the other thread for reasons). This can result in minutes of blank screens/error messages, sudden reboots or incomplete setups. Less than ideal … I’ve implemented a “snap is updating” message for my own snap via pre/post-refresh hooks, but I couldn’t find a way to be notified about core/snapd updates from within my snap.

I guess I could mitigate this with a system refresh.hold setting in my gadget snap, but even then
a) I’d have to rebuild the image at least every 59 days
b) as far as I understand, users won’t get any snap updates until the hold period is over.
Smaller hold period means earlier update but more frequent rebuilds, so I’m between a rock and a hard stone :slightly_frowning_face:

Another option would be to just distribute the “fresh” image directly from ubuntu-image. This mitigates the refresh problem since I could just recreate this image every night to ensure the latest snaps are seeded. But as outlined in this post, the first boot then takes around 10-15 minutes during which the user sees either a blank screen or an error message if interfaces for my snap haven’t been set up yet. For comparison, the pre-booted image takes around 45 sec. My gadget (fork of the reference pi-gadget) uses psplash to show a custom boot logo, but that is hidden as soon as mir-kiosk is seeded. Plus, I don’t know how to switch from a one-time “preparing device” logo to the regular boot splash.

Is there any way how I can

  1. detect from within a snap if the seeding process is still running? snap get system seed.loaded is unavailable from snapctl. As long as snaps/hooks install in run mode, I guess UC20 install mode doesn’t help me either.
  2. prevent snap services from starting up until seeding is finished? Specifically, mir-kiosk starts right after installation, which results in a blank screen until my wpe-webkit-mir-kiosk is installed.
  3. superimpose a huge “DO NOT TOUCH, STILL WORKING” screen during seeding so that impatient users do not pull the plug :sweat_smile:

Maybe something along the lines of this systemd service:

pinging @ogra @ijohnson @mvo @cjp256 – and thanks in advance for all helpful comments!