Installing and running snaps without systemd

I am currently running MX Linux, a distribution which does not run systemd by default. As snap/snapd uses systemd as a soft dependency this got in the way of being able to install snap packages.

I have found a way to mostly work around this issue using a shell script which intercepts snapd requests for mounting snap/squashfs archives and tries to act the way systemctl would.

I have managed to get snaps installed (yay!) and got two out of three snaps to even run. The gory details of how I got that far are here:

The problem I’m facing now is the last few rough edges. Specifically two things:

  1. I cannot run snaps from the /snap/bin/ directory. I need to run mounted snaps using their full path name, such as /snap/hello-world/27/bin/hello-world. For some reason the /snap/bin/hello-world symbolic link does not world. I get the error message: “cannot create temporary directory for the root file system: Permission denied”

  2. On a related note, apps don’t seem to be contained. For example, if I try to run the VLC binary, it links to my system libraries, not its own bundled Snap libraries.

In short, I’m got snap packages installed, but they don’t seem to be contained/mounted properly when I go to run them. I’d appreciate some help smoothing out these last few edges as it would allow people on non-systemd platforms to run Snaps.


That’s great, and as we discussed it should be something minor given we have quite a diverse set of distributions working by now.

@zyga Does that ring any bells before we dig in further?

this is just the result of 1. the confinement handling is done via the machanism you avoided by directly executing the binaries inside the snap (and you are just lucky that you actually have the libs vlc needs installed on your host, typically it would not start without being executed by the confinement wrapper that corrects the library search paths).

Agreed. My issue is I’m not sure what magic snapd is doing to try to contain the binaries inside the snap. During the install process it mounts the squash archive, using systemctl, but I’m not sure what else it’s supposed to do, since no error or warning is thrown during the install.

I’ve looked around, but I can’t find any documentation on what’s happening in the background, I’ve been basically trying to find relevant pieces of the source code to work out the steps.

Hey there. I can tell you all about how the execution environment works and looks like. The key to the puzzle is show the typical execution chain starts from /snap/bin/stuff, a symlink to /usr/bin/snap, being a convenient way to do snap run stuff. This is in turn equivalent to snap run stuff.stuff which means run app stuff from the snap stuff. This follows to running /usr/bin/snap-confine with constructs the execution environment (a separate mount namespace sharing some of the mount points with the main mount namespace, apparmor profile applied, seccomp profile applied and some cgroup changes) and runs /usr/lib/snapd/snap-exec (now already on the inside of the mount namespace) which finally reads the snap’s meta.yaml to run the correct command.

Now as for not having systemd you will run into issues when the mount namespaces are changed as systemd-less systems don’t have implicit sharing of mount events (mount --make-rshared /). Having said that, what happens if you install a trivial snap and run it with snap run hello?

Can the trick for trusty be applied to this distro?

The “deputy init” trick done for systemd would work for any Linux distribution that wants to support Snaps and not use systemd as primary init.

If I try to run a simple snap, like the Hello World package, I get the following:

$ snap run hello-world
error: cannot find installed snap “hello-world” at revision 27

If I mount the Hello World snap first using the custom script mentioned above, then I get

$ snap run hello-world
Can not open /var/lib/snapd/seccomp/profiles//snap.hello-world.hello-world (No such file or directory)
aborting: No such file or directory

A check shows the only file in the /var/lib/snapd/seccomp/profiles directory is “”. There isn’t one for Hello World or VLC, though these snaps were previously installed.

What is the deputy init trick?

Can you please paste the contents of /proc/self/mountinfo

Sure, the contents of my /proc/self/mountinfo is as follows, I’m guessing the relevant line is the last one:

21 26 0:20 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
22 26 0:4 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
23 26 0:6 / /dev rw,nosuid,relatime - devtmpfs udev rw,size=2770940k,nr_inodes=692735,mode=755
24 23 0:21 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000
25 26 0:22 / /run rw,nosuid,noexec,relatime - tmpfs tmpfs rw,size=557108k,mode=755
26 0 8:1 / / rw,noatime - ext4 /dev/sda1 rw,data=ordered
27 25 0:23 / /run/lock rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=5120k
28 21 0:24 / /sys/fs/pstore rw,relatime - pstore pstore rw
30 25 0:26 / /run/shm rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=1895520k
31 26 8:3 / /home rw,noatime - ext3 /dev/sda3 rw,data=ordered
32 21 0:7 / /sys/kernel/security rw,relatime - securityfs none rw
33 25 0:27 / /run/rpc_pipefs rw,relatime - rpc_pipefs rpc_pipefs rw
34 21 0:28 / /sys/fs/cgroup rw,relatime - tmpfs cgroup rw,size=12k,mode=755
37 34 0:41 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup systemd rw,release_agent=/run/cgmanager/agents/cgm-release-agent.systemd,name=systemd
38 25 0:43 / /run/user/115 rw,nosuid,nodev,relatime - tmpfs tmpfs rw,size=557104k,mode=700,uid=115,gid=126
39 25 0:44 / /run/user/1000 rw,nosuid,nodev,relatime - tmpfs tmpfs rw,size=557104k,mode=700,uid=1000,gid=1000
40 21 0:45 / /sys/fs/fuse/connections rw,relatime - fusectl fusectl rw
41 39 0:46 / /run/user/1000/gvfs rw,nosuid,nodev,relatime - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000
42 26 7:0 / /snap/hello-world/27 rw,relatime - squashfs /dev/loop0 ro

Are there plans to officially extend snapd to work without systemd? I have a few machines running on distros with systemd, but significant numbers running on systems without systemd. In practice that means I don’t end up using snaps anywhere. I would be very interested in being able to use snaps, but the systemd dependency (which means that it can only run on some of my systems) prevents me from doing so. I don’t think “universal Linux packages” should have a dependency on a parochial init(+).

There are no such plans. Systemd is pretty much ubiquitous now and having to depend on one implementation rather than several is an advantage in terms of lower complexity, consistency and simplicity for developers.

EDIT: IMO the sane way to handle that is to extend systemd to work as non-pid-1 init system that can co-exist with other systems. I’m not sure this is possible in general (cgroups for instance) but it might be possible in the narrower scope of systemd snapd interaction.

Calling systemd ubiquitous seems generous. Around 25% of Linux distributions still don’t use (and probably won’t use) systemd. By ignoring a quarter of the Linux distros you’re basically encouraging those users to avoid Snaps in favour of something like, like Flatpak.

As emacsomancer pointed out, having Snap rely on systemd is a non-starter for many of us, whether it runs as PID 1 or not.


For snaps that don’t have services, as far as I know all you need is a systemctl in snapd’s path that knows how to mount things. That is, it’ll receive systemctl daemon-reload, systemctl enable some.mount, and systemctl start some.mount after which the snap should be mounted. You should be able to create such a script without too much work (especially if you don’t worry about the general case and just implement the bits we use).

Of course for snaps that do have services things are more complicated, and the best way would be to add a backend to snapd. Elsewhere in the forum I think we went into some detail about what this would entail. Patches still welcome.

It is not the number of distributions but the number of users that matter. By your count Mandarin is a small language out of 100s.

Certainly in terms of number of users there are lots of people using systemd distros (Fedora, Ubuntu, Debian, Arch and derivatives). But nevertheless dependence on a specific parochial init belies the self-applied description of “universal Linux packages” (maybe “universal systemd packages”). I have both systemd and non-systemd machines, and while (having used snapd on my Ubuntu 16.04 machine) I like lots of aspects of snapd, this does not make it attractive because it only ends up being a solution for some of my machines.

Fortunately snapd doesn’t link with systemd, it just relies on the interfaces it provides: loading and respecting of systemd service, timer and mount units. We rely almost exclusively on writing unit files and using systemctl to manage them. If you re-implement those features without systemd then snapd will happily function just as it does on a system with real systemd.

Don’t get me wrong, I don’t have an option about init systems, it’s just a darn good dependency for a lot of things we don’t have to do, that are pretty hard to do correctly.


I have systemd as non pid1 on my debian system, because there is no way I’ll upgrade my laptop to systemd in place (i.e. so many things will break if the upgrade even succeeds at all).
I can report back that what you suggest, while appealing, doesn’t work:
saruman:~# snap install hello-world
2019/11/01 12:42:03.448508 api.go:879: Installing snap “hello-world” revision unset
error: cannot perform the following tasks:

  • Mount snap “core” (7917) ([daemon-reload] failed with exit status 1: System has not been booted with systemd as init system (PID 1). Can’t operate.
    Failed to connect to bus: Host is down

this is snapd 2.21-2+b1 on debian.
Can snap be made to work without systemd being pid 1, or not?

1 Like

snapd runs with systemd not being pid 1 in 14.04, for example. So it is doable, although it requires considerable care. Good luck!

1 Like

Ok. I don’t run ubuntu though, if it only works in ubuntu, that defeats the purpose a little bit :slight_smile:
which version is known working with systemd not pid 1?