Parallel Installs

Parallel installs enable you to run multiple instances of the same snap on the same system. Each instance is completely isolated from all other instances, including its name, configuration, interface connections, data locations, services, applications and aliases.

This feature is currently considered experimental. In particular, snap install will fail if the same snap is already installed. See below for a workaround and see Current limitations for more details. As a result, to experiment with parallel installs, an experimental feature-flag must first be enabled:

$ sudo snap set system experimental.parallel-instances=true

We recommend rebooting the system after toggling the experimental.parallel-instances flag state to avoid potential namespace problems with snap applications that have already been run.

Version requirements:

snapd version 2.36 or later is required to use parallel installs with strictly confined snaps. Version 2.43 or later is required for snaps using classic confinement. See Snap confinement for more details.


Installing multiple instances

The process for installing multiple instances of a snap is identical to installing a single snap except you must provide a unique identifier, called an instance key, separated by an underscore (_) from the target snap name.

For example, the following command will install two instances of the hello-world snap with the second given an instance key of foo:

sudo snap install hello-world hello-world_foo

To specify a specific channel and track for each instance, install each instance separately.

For example, to install Juju 2.9 alongside Juju 3.0, run the following commands:

sudo snap install --channel 2.9/stable juju_29 --classic
sudo snap install --channel 3.0/stable juju_30 --classic

When installing from snap file, the instance key is set by passing --name=<snap>_<instance> explicitly:

sudo snap install --name hello-world_foo hello-world_27.snap

Instance key naming

The instance key needs to be manually appended to the snap name, and takes the following format: <snap>_<instance-key>

For example, the following are valid instance names, for example:

  • hello-world
  • hello-world_foo
  • hello-world_0123456789

Only lowercase letters or digits are valid, and the instance name can be up to 10 characters long. After being set during the installation of a snap, an instance name cannot be changed.

ⓘ The instance key must match the following regular expression: ^[a-z0-9]{1,10}$.

Instance management

When working with instances, the vast majority of snap commands function just as they would with a single snap. To remove an instance, for example, use remove:

$ snap remove hello-world_foo
hello-world_foo removed

Interfaces

Interfaces work across multiple snap instances just as they do from any one snap to another. For example, xkcd-webserver includes a network plug, as will all of its instances, any of which can be connected to the system’s :network slot:

$ snap connections xkcd-webserver_foo
Interface     Plug                             Slot           Notes
network       xkcd-webserver_foo:network       :network       -
network-bind  xkcd-webserver_foo:network-bind  :network-bind  -

$ sudo snap disconnect xkcd-webserver_foo:network

$ snap connections xkcd-webserver_foo
Interface     Plug                             Slot           Notes
network       xkcd-webserver_foo:network       -              -
network-bind  xkcd-webserver_foo:network-bind  :network-bind  -

$ sudo snap connect xkcd-webserver_foo:network

$ snap connections xkcd-webserver_foo
Interface     Plug                             Slot           Notes
network       xkcd-webserver_foo:network       :network       manual
network-bind  xkcd-webserver_foo:network-bind  :network-bind  -

Services

As with Interfaces, Services function the same with multiple instances of a snap as they do from any one snap to another.

However, with multiple instances, you’re more likely to run into port allocation issues, such as two web servers needing access to port 80. In such cases, only the service from one instance will be active.

$ snap services
Service                            Startup  Current
xkcd-webserver.xkcd-webserver      enabled  active
xkcd-webserver_foo.xkcd-webserver  enabled  inactive

You can see why xkcd-webserver_foo.xkcd-webserver is inactive by looking at its logs:

$ sudo snap logs xkcd-webserver_foo.xkcd-webserver
2018-10-03T12:31:59Z xkcd-webserver_foo.xkcd-webserver[1760]: OSError: [Errno 98] Address already in use
(...)

As with single snap service collisions, the solution is to stop the service on one instance and start the service on the other:

$ sudo snap stop xkcd-webserver.xkcd-webserver
Stopped.

$ sudo snap start xkcd-webserver_foo.xkcd-webserver
Started.

$ snap services
Service                            Startup  Current
xkcd-webserver.xkcd-webserver      enabled  inactive
xkcd-webserver_foo.xkcd-webserver  enabled  active

Application names and aliases

Snap application names for multiple instances are adjusted according to the following pattern:

<instance-name>.<app>

When an application name matches the snap name, a short alias is created to match the instance name.

For example, with hello-world and hello-world_foo installed, hello-world.env has an alias of hello-world_foo.env in the _foo instance:

$ hello-world.env  |grep SNAP_INSTANCE_NAME
SNAP_INSTANCE_NAME=hello-world
$ hello-world_foo.env  |grep SNAP_INSTANCE_NAME
SNAP_INSTANCE_NAME=hello-world_foo

As with regular snaps, aliases can be added separately:

$ sudo snap alias hello-world_bar bar_env
Added:
  - hello-world_bar as bar_env

$ sudo snap alias hello-world_foo foo_env
Added:
  - hello-world_foo as foo_env

$ snap aliases
Command          Alias    Notes
hello-world_bar  bar_env  manual
hello-world_foo  foo_env  manual

Aliases from instances generate conflict errors, just as they would with distinct snaps:

$ sudo snap alias hello-world_foo bar_env
error: cannot perform the following tasks:
- Setup manual alias "bar_env" => "hello-world" for snap "hello-world_foo"
(cannot enable alias "bar_env" for "hello-world_foo", already enabled for "hello-world_bar")

When aliases trigger a conflict during snap installation, try passing --unaliased with the command to disable automatic aliase generation:

$ sudo snap install snap-with-conflicting-alias_foo --unaliased

Snap environment, data and namespace

When a snap application is run, its environment is populated with a number of SNAP* environment variables.

The following environmental variables are potentially affected when installing multiple instances of a snap:

  • SNAP_NAME: the name of the snap, eg. hello-world
  • SNAP_INSTANCE_NAME: the name of the instance, eg. hello-world_foo
  • SNAP_INSTANCE_KEY: instance key, eg, foo for hello-world_foo
  • SNAP: location of files for the snap
  • SNAP_DATA: data for this particular snap revision
  • SNAP_COMMON: data shared between revisions of the same snap
  • SNAP_USER_DATA: user data for this particular snap revision
  • SNAP_USER_COMMON: user data shared between revisions of the same snap
  • HOME: user’s home, equivalent to SNAP_USER_DATA
  • XDG_RUNTIME_DIR: user’s XDG runtime directory

For example, if hello-world and its instance, hello-world_foo, are installed, the following name variables would be set:

snap hello-world hello-world_foo
SNAP_NAME hello-world hello-world
SNAP_INSTANCE_NAME hello-world hello-world_foo
SNAP_INSTANCE_KEY foo

The data and mount points of parallel installed snaps are kept separate on the host filesystem. Assuming the snap mount directory is /snap, the following locations are used:

snap hello-world hello-world_foo
mount point /snap/hello-world/27 /snap/hello-world_foo/27
system data /var/snap/hello-world/ /var/snap/hello-world_foo/
user data $HOME/snap/hello-world/ $HOME/snap/hello-world_foo/

Within the mount namespace of a snap, adjustments are made to map instance-specific locations to the snap locations. Taking hello-world as an example, system data locations are set to the following:

snap hello-world hello-world_foo
SNAP /snap/hello-world/27 /snap/hello-world/27
SNAP_DATA /var/snap/hello-world/27 /var/snap/hello-world/27
SNAP_COMMON /var/snap/hello-world/common /var/snap/hello-world/common

However, due to security concerns, user data locations are not similarly adjusted:

snap hello-world hello-world_foo
SNAP_USER_DATA /home//snap/hello-world/27 /home//snap/hello-world_foo/27
SNAP_USER_COMMON /home//snap/hello-world/common /home//snap/hello-world_foo/common
HOME /home//snap/hello-world/27 /home//snap/hello-world_foo/27
XDG_RUNTIME_DIR /run/user//snap.hello-world /run/user//snap.hello-world_foo

Current limitations

There are a few limitations with parallel installs that will be addressed in subsequent snapd releases.

User data and runtime locations

As described in Snap environment, data and namespace, the user data locations are kept separate across multiple instances. Applications that hard code paths to either user data directories or the XDG runtime directory may not function correctly as the AppArmor profile has been updated to allow accessing instance specific paths only.

Applications need to use SNAP_USER_DATA, SNAP_USER_COMMON or fallback to using HOME.

Applications built using most popular frameworks, such as Gtk/glib or Qt, and that are already capable of observing both HOME and XDG_RUNTIME_DIR, should continue to work.

Ports, DBus names, shared memory and socket activation

Snaps may provide APIs consumed by other snaps or the host system at some well known locations or addresses, such as DBus service names, /dev/shm objects or semaphores, abstract socket addresses. While the default AppArmor template has been updated to allow only instance specific access, connecting interfaces may allow a wider access capabilities that can lead to conflicts between instances of the same snap.

Ports

When snapd installs a snap with services, the services are automatically started. Services trying to bind to the same port may fail or function incorrectly. Such snaps should deliver means for configuration of the service via configure hooks.

A demo snap GitHub - bboozzoo/parallel-installs-demo: Parallel installation of snaps demo provides an example of reconfiguration via configure hooks.

DBus names

Services exporting the API on DBus under a well known name may conflict with other instances of the same snap. Those may require fixes from application or snap developers.

/dev/shm

The default AppArmor profile allows instance specific access only. Applications hardcoding paths can break. Note that some interfaces such as mir allow a wider access to /dev/shm. Such snap would need to be updated to made instance aware.

Socket activation

Snaps using socket activation will collide with each other when parallel installed. The socket unit file may need manual adjustment.

2 Likes

The anchor link doesn’t work as of now: No autolink for headings in topic

1 Like

Bummer. Thanks for spotting.

I’ve enabled the flag and tried to install Firefox Beta with snap install firefox_beta --beta but that produced

error: cannot install "firefox_beta": cannot refresh, install, or download: The Snap is present
       more than once in the request.

I already have Firefox installed, how do I get Firefox Beta installed as a second instance?

Core 16-2.35.5
$ snap info core
tracking:     beta
refresh-date: 6 days ago, at 09:42 BST
installed:   16-2.35.5                   (5742) 92MB core

$ snap version
snap    2.35.5+18.10
snapd   2.35.5+18.10
series  16
ubuntu  18.10
kernel  4.18.0-10-generic

$ snap info firefox
tracking:     stable
refresh-date: 20 days ago, at 22:56 BST
channels:                                
  stable:        62.0.3-1    (137) 204MB -
  beta:          63.0b14-1   (141) 206MB -      
installed:       62.0.3-1    (137) 204MB -

(lines omitted for brevity)

For starters, you’ll want to have the latest and greatest core, at this point --edge is needed.

The store is bit behind on the support. See the note about installing snaps from store. TLDR: you’ll need to grab the snap from the store yourself (eg. snap download) and install it using the file. Note that having 2 instances of Firefox at this pint will probably stop the snaps from refreshing as the store will respond with an error.

1 Like

Alright I’ll wait for more progress then, thanks! :slight_smile:

We’ve caught up! Parallel installs are now fully supported by the store. We’ve tested it pretty thoroughly, but please try your best to break it.

3 Likes

(firefox_beta was created with the command snap install firefox_beta --beta)

$ snap run firefox_beta
/snap/firefox_beta/144/command-firefox.wrapper: 5: exec: desktop-launch: not found
$ snap run firefox_beta.firefox
/snap/firefox_beta/144/command-firefox.wrapper: 5: exec: desktop-launch: not found
$ env BAMF_DESKTOP_FILE_HINT=/var/lib/snapd/desktop/applications/firefox_beta_firefox.desktop /snap/bin/firefox_beta %U
/snap/firefox_beta/144/command-firefox.wrapper: 5: exec: desktop-launch: not found

I suspect a core refresh or a system reboot stopped Firefox Beta from running entirely, normally it launches with a transparent window. After reverting twice to get to core (5742), then removing firefox_beta, then refreshing to core (5789), and installing firefox_beta again, I’m back to BMO bug 1501895, I don’t have the error above… I wonder what happened? snap run firefox was working fine but snap run firefox_beta was not…

Core 16-2.36~pre2+git971.73ec9b5 (5789)
$ snap info firefox
tracking:     stable
refresh-date: 23 days ago, at 22:56 BST
  stable:        62.0.3-1    (137) 204MB - <
installed:       62.0.3-1    (137) 204MB - 

$ snap info firefox_beta
tracking:      beta
refresh-date:  today at 02:26 BST
installed: 64.0b3-1 (144) 208MB -

$ snap version
snap    2.36~pre2+git971.73ec9b5~ubuntu16.04.1
snapd   2.36~pre2+git971.73ec9b5~ubuntu16.04.1
series  16
ubuntu  18.10
kernel  4.18.0-10-generic

$ snap info core
tracking:     edge
refresh-date: today at 02:25 BST
channels:                                                     
  stable:    16-2.35.4                   (5662) 92MB -    
  candidate: 16-2.35.5                   (5742) 92MB -    
  beta:      16-2.36                     (5799) 92MB -    
  edge:      16-2.36~pre2+git971.73ec9b5 (5789) 92MB -    <
installed:   16-2.36~pre2+git971.73ec9b5 (5789) 92MB core

All I get is a black window. The console log is:

[Parent 17752, Main Thread] WARNING: failed to open shm: Permission denied: file /builds/worker/workspace/build/src/ipc/chromium/src/base/shared_memory_posix.cc, line 129
[GFX1-]: Failed to lock new back buffer.
[Parent 17752, Main Thread] WARNING: failed to open shm: Permission denied: file /builds/worker/workspace/build/src/ipc/chromium/src/base/shared_memory_posix.cc, line 129
[GFX1-]: Failed to lock new back buffer.

AppArmor denials:

[  +0.000002] audit: type=1327 audit(1540445566.824:534): proctitle="/snap/firefox/144/firefox"
[  +0.016190] audit: type=1400 audit(1540445566.841:535): apparmor="DENIED" operation="mknod" 
     profile="snap.firefox_beta.firefox" name="/dev/shm/snap.firefox.org.mozilla.ipc.17752.52"
     pid=17752 comm="firefox-bin" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000                                                                               
[  +0.000010] audit: type=1300 audit(1540445566.841:535): arch=c000003e syscall=2 success=no
     exit=-13 a0=7ffd1a3f2060 a1=a00c2 a2=180 a3=67726f2e786f6665 items=0 ppid=2001
     pid=17752 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts2 ses=3
     comm="firefox-bin" exe="/snap/firefox/144/firefox-bin" subj==snap.firefox_beta.firefox (enforce) key=(null)

It’s one of the quirks about accessing /dev/shm:

I’ll see whether I can tweak the snap a little bit.

1 Like

That particular issue is off-topic, I think? Presumably it would affect firefox were (144) the only firefox snap installed? The point I was making was something broke the snap even further and I’m wondering if that was related to an automatic core refresh to (5789) and the parallels install feature… Unfortunately I don’t have time to test again now to try and reliably break it, so it might’ve been some other reasons that made desktop-launch: not found happen, and unfortunately I didn’t check journalctl -f when running the command :frowning:

No it doesn’t, I just verified that in a VM with core from edge and the firefox snap from the beta channel. All works well, so it’s likely only an issue of named access to /dev/shm.

1 Like

Is parallel installs the correct/only way to have both the stable and beta release of e.g. Blender available at the same time?

Yes. Each instance of a snap is separate, and can track different channel.

However, blender is a classic snap, and currently, we only support parallel installation of confined snaps.

There is work planned in the forthcoming months that should address this problem, and hopefully it will be possible to parallel install classic snaps too. Unfortunately, I cannot give any exact dates as to when that feature will be available.

1 Like

@mborzecki how should snaps go forward (confined vs classic)? Does it make sense to have multiple snaps of the same app now?

Look at the Opera Snap. They originally allowed for consecutive installs on all platforms. Since there were no Parallel Install ability from Snaps, they appear to have released 3 snaps to cover this specific use case. Should this be seen as a bad practice nowadays? When is this a good idea?

Android Studio’s snap (classic) is coming up to a similar decision once Parallel Installs are fully supported. https://github.com/snapcrafters/android-studio/issues/26

1 Like

In the command line (v2.40, Ubuntu 18.04), I can’t do parallel installs with --classic – I’d really like to install multiple versions of dotnet-sdk, but if I say

sudo snap install dotnet-sdk dotnet-sdk_22 --classic

I get the error

error: a single snap name is needed to specify mode or channel flags

My guess is that the options parser is interpretting dotnet-sdk_22 as a second package rather than as an alias.

Classic snaps are not parallel installable yet unfortunately.

When using channel (--edge, --beta, --channel=..) or mode (--classic, --jailmode) flags, you can only pass a single snap name in the command line.

As for parallel installs of classic snaps, the current state is as @ijohnson wrote, we do not support it at the moment. However, we have some work scheduled to add support for this feature, so things may indeed change in 2-3 releases.

1 Like

We have discovered one more weird interaction that enabling parallel installs can have with existing snap mount namespaces, see Parallel-instances breaks content snap consumers for details.

With this in mind, I would recommend that if the users ran any snap applications in the currently booted system prior to enabling/disabling the feature, they should reboot after toggling the experimental flag state.
Alternatively they can discard the mount namespace of all snaps, though I see that as something that a snap developer or a snapd hacker would be more willing to try.

Is this still currently the case? It seems to be conflicting with the following passage:

Thanks for spotting. I’ve updated the doc.

2 Likes