Building snaps within an isolated environment, such as LXD, has several advantages over a native build:

  • containers keep your host system clear of your new snap’s dependencies
  • your host system can’t expose conflicting libraries to your new snap build

Read on to discover how to build snaps with LXD.

Install LXD

Recent non-desktop versions of Ubuntu install LXD by default - you can check whether it is installed with the following command:

$ lxd version
3.7

The easiest way to add LXD to your system is via its snap:

$ sudo snap install lxd

Now initialise LXD with the following command, accepting all the default options unless you have specific requirements:

$ sudo lxd init

ⓘ If the system you are installing LXD onto is using a network with a 10.x.x.x subnet then network create may fail. Step through the following to resolve this.

Manually create a network on a 10.x.x.x subnet

If you try to run lxd init on a system that is connected to a network with a 10.x.x.x subnet, then the final step of the Iinit* may fail with the following error:

Error: Failed to create network 'lxdbr0': Failed to automatically find an unused IPv4 subnet, manual configuration required

To resolve this issue, you must manually create the network with the following command:

$ sudo lxc network create lxdbr0 ipv4.address=10.0.3.1/24 ipv4.nat=true

You can then re-run lxd init. When you are prompted to create a new network bridge you must respond no.

Would you like to create a new network bridge (yes/no) [default=yes]? no

Group permissions

If you want to build snaps as a non-root user, which is advised, then you need to add your user account to the lxd group:

$ sudo usermod -g lxd ${USER}

You now need to either restart your session, reboot your computer, or use newgrp to acquire the new group assignment:

$ newgrp lxd

ⓘ The newgrp command will start a new sub-shell (shell within a shell) with the new lxd group assigned.

Building

ⓘ If snapcraft is not yet installed, enter sudo snap install snapcraft --classic.

To build your project using lxd run:

$ cd $HOME/my-snap-project
$ snapcraft cleanbuild

If the build fails, add the --debug option to the snapcraft cleanbuild command. This will drop you into a shell running within the LXD environment that just attempted to build your snap, allowing you to examine where the issue may be.

Experimental: persistent containers

When building with LXD, the old container is discarded. This means that LXD needs to build a new environment, each time you build your snap. This is acceptable with small snaps, or for a final build, but can be problematic during development.

For example, during development, you might normally use:

$ snapcraft
$ snap try prime

The ‘try’ method allows you to directly edit files in a snap’s prime directory without having to re-install or re build after each change. However, when using cleanbuild, this feature is not supported.

But there is an experimental feature that uses LXD in a different way, allowing you to retain intermediate files, and the container:

$ export SNAPCRAFT_BUILD_ENVIRONMENT=lxd 
$ snapcraft

If you get the following error:

Failed to start container: the local folder could not be mounted into the container. 

Add a line containing root:1000:1 to the following files:

  • /etc/subuid
  • /etc/subgid

You may need to log out and back in again before reattempting the build. If successful, you can now try the snap, make changes, and rebuild quickly:

$ snap try prime

The environment variable SNAPCRAFT_BUILD_ENVIRONMENT instructs snapcraft to use experimental LXD integration to build the snap in a persistent LXD container. This container remains after the build has finished, and retains intermediate build files to speed up rebuilds.