Ubuntu Core is Canonical’s secure operating system for embedded devices. Software on Ubuntu Core is installed via Snaps. This post can help you:
-
Set up an Ubuntu Core virtual machine
-
Download and “try” a snap such that you can easily modify and debug it
-
Run graphical snaps (such as Flutter apps) on Ubuntu core
Create an Ubuntu Core VM
Download the Image
First, we’ll download and Ubuntu Core image. It’s currently easiest to get core18 working. In the most common case (running on an x86 computer) you’ll want to grab the ubuntu-core-18-amd64.img.xz
image.
Install qemu-virgil
In this post, we’ll be using qemu-virgil because it supports OpenGL. You may use a different VM system if the snap you’re debugging isn’t graphical.
$ sudo snap install qemu-virgil
$ sudo snap connect qemu-virgil:kvm
Prepare to SSH
The primary means of interacting with the VM will be SSH. In order to be able to SSH in, you’ll want to have a Launchpad account with a public SSH key attached. If you need to create a new SSH key, GitHub has a good tutorial.
Decompress the Image
You can do it from the command line or your archive manager.
$ unxz -k ~/Downloads/ubuntu-core-*.img.xz
$ mv ~/Downloads/ubuntu-core-*.img where/you/want/the/image/
The resulting image will be several GB, most of which is initially empty space inside your VM for data and software.
Start the VM
To start the VM, run the following with the last argument the actual path to the image you extracted:
$ qemu-virgil -enable-kvm -m 512 -device virtio-vga,virgl=on -display sdl,gl=on -netdev user,id=ethernet.0,hostfwd=tcp::10022-:22 -device rtl8139,netdev=ethernet.0 -soundhw ac97 ~/path/to/ubuntu-core-*.img
Troubleshooting (skip if the VM works)
If you get
Could not access KVM kernel module: Operation not permitted
qemu-system-x86_64: failed to initialize KVM: Operation not permitted
it probably means you forgot to connect qemu-virgil:kvm
(see above). I’ve also seen
qemu-system-x86_64: -soundhw ac97: Could not open '/media/wmww/Auxiliary/vm-disks/ubuntu-core-18-amd64.img': Permission denied
When the image was outside of my home directory. Moving it to be under home fixed this.
Set Up The VM
In the window that pops up, you will be prompted to set up the system. Use the default network configuration. When it asks for your email, make sure to put one that is attached to the Launchpad account that holds your public SSH keys, else you won’t be able to SSH in.
SSH Into The VM
It will tell you to SSH in with some specific IP address. This is not what you want to do, as this is an IP internal to qemu. Instead, we set up port forwarding on localhost - use this (with username changed with your actual username):
$ ssh -p 10022 username@localhost
You should now be inside your VM.
Debug a Snap
For starters, we’re going to download a simple, non-graphical snap: youtube-dl from the store (downloading, not directly installing).
Acquire the Snap
From the SSH session:
$ snap download youtube-dl
Alternatively you could transfer a snap built on the host into the VM. From the host you would run:
$ scp -P 10022 path/to/app.snap username@localhost:/home/username
Try a Snap
If we installed the snap normally, it’s contents would be read-only and we wouldn’t be able to experiment with it. Instead, we’re going to uncompress it’s contents into a directory called youtube-dl-root
:
$ unsquashfs -d youtube-dl-root ./youtube-dl*.snap
and “try” the snap from the new directory - this treats the folder as if it was a snap package:
$ snap try youtube-dl-root
$ youtube-dl --version
2021.01.16
Modify a Snap In Place
We can now make changes to the contents of squashfs-root
and have those immediately reflected (except those in meta/
, you’ll need to snap try
again for those to get picked up). For example:
$ cp ./youtube-dl-root/bin/youtube-dl ./youtube-dl-root/bin/youtube-dl.old
$ echo 'echo "Snap has been modified!"' > ./youtube-dl-root/bin/youtube-dl
$ youtube-dl --version
Snap has been modified!
How exactly you’ll need to modify your snap to debug whatever issue you’re facing is out of scope here. Depending on the type of snap and issue, you may need to change the code directly, swap in binaries or libraries you’ve built on the host system, or modify config files.
Access a Snap’s Environment
To get access to the environment a Snap runs in, run:
snap run --shell appname
You will then get a shell that has all the environment variables set (like $SNAP
).
Run a Graphical Snap
To run a snap with graphics, you’ll generally need two parts:
-
The app, which does the interesting things you care about
-
A display server, which on Ubuntu Core is generally Mir Kiosk
The app talks to the display server (generally over the Wayland protocol), and the display server puts the app on the screen.
Install Mir Kiosk
If we wanted to modify and debug Mir Kiosk we could download and try it, but we probably wont need to change it so we’ll install it normally.
$ snap install mir-kiosk
As soon as it’s installed it starts a daemon. You may notice an orange flash in the VM window, which indicates Mir Kiosk has started. At any time you can the Mir Kiosk daemon with:
$ snap set mir-kiosk daemon=false
And start it again with:
$ snap set mir-kiosk daemon=true
You know it works if you see an orange flash when you start it.
“Try” a Flutter Snap
Now we’ll download, unsquash and try a graphical snap built with Flutter. The commands should look similar to what we did with youtube-dl above:
$ snap download --edge flutter-gallery
$ unsquashfs -d flutter-gallery-root ./flutter-gallery*.snap
$ snap try flutter-gallery-root
Assuming the Mir Kiosk daemon is running, flutter-gallery should automatically start and you should be able to play with it.