30

Applications packaged as snaps in Ubuntu are installed (mounted) under the /snap/$SNAPPNAME location. Everything under /snap is mounted as a read-only file system, thus applications cannot write to that space, neither in other app's directories nor in their own.

While there is a home interface that snaps can specify to read/write the user's home directory, it is reserved for security reasons and needs to be manually connected (enabled) by the user.

So where can an app inside a snap write its config, data and other files? Are there APIs to access special writeable locations?

42

I'm having trouble referring you to documentation, which means I either haven't had my coffee yet (true) or we're missing some documentation (update: some documentation here)

When you declare apps in your snapcraft.yaml, it results in a binary wrapper being generated upon install and placed into /snap/bin/, named after your package and app name (note that if the app is a service, this wrapper is instead a systemd .service file).

That wrapper contains most of the environment under which the application will run. The two environment variables that are most relevant to this question are SNAP_DATA and SNAP_USER_DATA.

  • SNAP_DATA is a system-wide writable area (in /var/snap/). This might be used to host logs for services, for instance.

  • SNAP_USER_DATA is a user-specific writable area in the home directory of the user running the application (specifically /home/<user>/snap/). This might be used for user-specific configuration files, etc.

Both of these directories are very important to the upgrade/rollback functionality, since both of them are versioned. That is, each version of a given snap has its own copy of these directories. Let me explain with an example.

Say you install version 1 of the "foo" snap. That will create two directories:

  • /var/snap/foo/1 (SNAP_DATA)
  • /home/<user>/snap/foo/1 (SNAP_USER_DATA)

Now say "foo" uses both of these. Maybe it has a service that hosts a database in SNAP_DATA, and a binary that uses config files in SNAP_USER_DATA.

Now version 2 of "foo" is released, and it's automatically updated. The first thing that happens is that /var/snap/foo/1 is copied into /var/snap/foo/2 and /home/<user>/snap/foo/1 is copied into /home/<user>/snap/foo/2. Then the new version is fired up. It should notice that it's running on old data, and maybe it has some database migrations to run to the database in SNAP_DATA. It does that, and away it goes.

Now say those migrations fail for whatever reason, and this application needs to be rolled back. It begins using the old version of the /snap/foo application, where SNAP_DATA was pointing to /var/snap/foo/1 and SNAP_USER_DATA was pointing to /home/<user>/snap/foo/1. This picks things up on the old version at the point before the migrations were run, since those operations were run on a copy of the data.

Long story short: don't use the home interface to store data you can be storing in SNAP_DATA or SNAP_USER_DATA, since they're an integral part of the upgrade/rollback strategy. Take advantage of them!

UPDATE for v2.0.10:

Two new data directories were also introduced:

  • SNAP_COMMON sits alongside SNAP_DATA, but is specifically unversioned. Every revision of the specific snap has access to this directory, so it's not copied upon upgrade/rollback etc. This might be used for particularly large, unversioned files (e.g. raw data that isn't really version-specific).

  • SNAP_USER_COMMON sits alongside SNAP_USER_DATA, but is again specifically unversioned. It might be used for storing non-version-specific data per user.

UPDATE for v2.15:

The files placed within /snap/bin are no longer wrappers that define the environment, but symlinks to /usr/bin/snap. So the way to determine the environment under which an application runs would be to use snap run --shell <snap>.<app>, for example:

$ sudo snap install hello-world
$ snap run --shell hello-world
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

$ env | grep SNAP
SNAP_USER_COMMON=/home/kyrofa/snap/hello-world/common
SNAP_REEXEC=
SNAP_LIBRARY_PATH=/var/lib/snapd/lib/gl:
SNAP_COMMON=/var/snap/hello-world/common
SNAP_USER_DATA=/home/kyrofa/snap/hello-world/27
SNAP_DATA=/var/snap/hello-world/27
SNAP_REVISION=27
SNAP_NAME=hello-world
SNAP_ARCH=amd64
SNAP_VERSION=6.3
SNAP=/snap/hello-world/27
  • 1
    Isn't SNAP_USER_COMMON dir being created automatically by snapd? The launcher script in /snap/bin/ doesn't create it, and creating it manually inside the snap fails (permission denied). Running snap run app creates that folder, though (but the command fails with execv failed: No such file or directory... I have no idea how to use that command). – user180409 Jul 11 '16 at 20:14
  • 1
    Yes, it should be, but it's not (a bug that's fixed in the upcoming release where snap run is used). – Kyle Jul 11 '16 at 21:05
  • 1
    Note that snap run is used as of v2.15. – Kyle Oct 19 '16 at 6:51
  • 2
    Seem the doc updated, here the ref page snapcraft.io/docs/reference/env – user.dz Apr 20 '17 at 14:15
  • 2
    Two years later - have you had coffee yet? Still no documentation about where Snap applications can write data in the (virtual or host) file system. That does not offer me great inspiration as I try to understand the basic obvious details about snaps. – Dan Nissenbaum Dec 9 '18 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.