Ubuntu Core Create System User

I have been following the example on https://git.launchpad.net/cloud-init/commit?id=d8534561ba76db25b6fc0044eb1bfda63686e859 to make a system-user via cloud-init. I have been doing this on an Ubuntu Core Image that I am building. Unfortunately this seems to only work IF there is a stable connection (over ethernet). If there is no connection then, the “snap create-user” function will fail. Consequently the cloud-init will not run across a reboot.

I would like to see if any one had suggestions on how to retry to create this user using cloud-init or any other process. NOTE: I will be isolated from any USB/HDMI ports, so creating a system-user assertion via USB/keyboard will not be possible.

Here is my version of cloud-init that is in my gadget snapd:

#cloud-config
users:
  - name: Emilio Lopez
    snapuser: myemail@mydoamin.com
snappy:
    email: myemail@mydoamin.com
snap: 
  assertions: 
   - |
     type: system-user
     authority-id: MYSNAPCRAFTACCOUNTID
     revision: 4
     brand-id: MYSNAPCRAFTACCOUNTID
     email: myemail@mydoamin.com
     model: pc-amd64
     name: Emilio Lopez
     series:
       - 16
     since: 2018-06-28T18:23:05+00:00
     ssh-keys:
       - ssh-rsa MYSSHRSA
     until: 2019-06-28T18:23:05+00:00
     username: myusername
     sign-key-sha3-384: 8p-Dao4xKWSzd6bRhh6SmtxX4aFR0SuTSxurUA2m5MkW18JFapObBV7sxRbnagbL

     AcLBXAQAAQoABgUCWzpGHwAKCRAXkI1oKJIQorm6EACryO23AHIbH6Kg7oeKCXJUTCzOQRr0NSwf
     RCw5Z2cFwAXq+NHJxH99avPQy6UGdBpKfpZiiYw1myPO5hUhH4/flj8z16Q4prO5zVDQR6eUr+ry
     mkTQtj10yS29y8nEBHxW+7vdvKRbma65zTmYTKeCyj+z+CNbCZ++bTyD7RqpD9jVeqrDWbGZ5+oq
     gyca9aPRtDDL+52PWijDDNlZwVeqiPI1FPBOZbioiH4+qUh/V43dJG5tSzCSy63hIpSN71s/q0wF
     HPw+ECwhppPc2oX4sHpCqSNWf8fEKf0onDwwHGt4tuOjU62hYFmQcXW5IPv0Q/A4fmJ/Ul7qoLFo
     NEza/rn8UdlS1QGOEjxIljw5AGDdM10iWwJBORBtX+U23QhA5A4pV0Zl0XtJWEvy06jBJnETABoJ
     RZECfPjoUUF25No+ijo7lfDjBBhJCVobkY5VTRd0EknjTXs9tR8OA1P4rh5AlCbOYkecsvgt53eS
     sDg//5NPgJEf0k2lYrDRG9a6yCHgTR3gS59u83UmmseEm1FvWEc466O8k6uS1Po8lpwGsIiKfCFM
     0XBCOfGESBHoilLB7Vmg0E97CFZAlOocPJSYSLUVitlVM2/o3mWAQX/5rYiIv6tg4GNHcB63S8sD
     dvcAq9Pf9zjHOT+SJtZwa+cZZVn5T9i4CY7akm3YJw==
  commands: 
    0: "snap create-user --sudoer --known myemail@mydoamin.com"

Thanks!

Note that there is a native way to create system users in Ubuntu Core:

cloud-init, while it works for this too, is rather focused on automated cloud installs and adds some extra overhead. But if you have no access to the device at all it might be the best way (beyond simply dumping a user assertion into /writable/system-data/var/lib/snapd/seed/assertions during the flash process while you install the image to the system.

Also, adding the user creation to the gadget means indeed that all your installs have the same user.

I can place the assertion file into
/writable/system-data/var/lib/snapd/seed/assertions/my-system-user.assert

This is done after creating the image. I do this by mounting the image file, copying the file, then un-mounting.

However there is no luck on creating the user at boot time. Do I need to change the file extension?

I am also fine with having multiple installs with the same user.

i think the file ending needs to be fully written out as “blahblah.assertion” for snapd to pick it up from there.

Thanks ogra, you are correct it requires the extension *.assertion.

Also I found the solution to my issue. I simply created the assertion file, mount the *.img file, inject the assertion file, create a systemd-service that executes “create-user --sudoer --known”, then unmount the image.

When the ubuntu-core image boots, it will look for that assertion file and create the system-user.

Reference: https://github.com/snapcore/snapweb/blob/master/spread/image/create-image.sh

Hi lopezem - I’m struggling with a similar problem, wanting to tailor the generated core image with a specific system user and network config.
First starting with the system user, I created user assertion and copying it to the root directory of a USB memory stick, creates this user account accordingly.
If I inject the user assertion to “…/system-data/var/lib/snapd/seed/assertions/” and change the extension to “.assertion” it will have no effect - meaning there is no user created and I’m not able to login :(.
Anything I missed?

In general, what is the best way to tailor an image to specific purposes? While searching on the internet, the most common solution I came across is using the cloud.conf file … is this the preferred method?

Thanks
Andreas

Hi @andreas, I believe you are correct in creating the system user assertion. What you need to do, (instead of placing the assertion file into the root directory of the USB) is after creating the ubuntu core image, you must mount the image.

I would highly recommend following the reference link I provided in the previous post in github. In a nutshell the script does the following:

  1. Create a system-user assertion file.
  2. Create a systemd service script to add the user during run time. I recommend sending logs to dmesg for debugging purposes in addition to what is provided in the repo
  3. Create an ubuntu-core image file
  4. Mount the generated image file to /tmp
  5. Create the necessary directories for the assertion and systemd files/scripts
  6. Copy the assertion file and systemd service scripts
  7. Unmount the image file
  8. Flash the image file to a USB/SD card
  9. Boot the ubuntu core messages and monitor dmesg for debugging

P.S. I tried cloud-init functions. They kind of work but only for specific SSH keys, and it won’t really tie it to your ubuntu-one account.

Thanks @lopezem for the answer - I checked the reference on github and I didn’t like that it’s copying the systemd units from the core snap over, in order to add the “create-user” one time service (line 58-69).

It’s probably the best way to use a private snap package to do the initial setup of the system …

Thanks
Andreas

No problem, did you have success with this?