37

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?

1
  • Appears snap's can bind the home/media interface's automatically these days, FWIW...
    – rogerdpack
    Jan 18, 2022 at 17:28

1 Answer 1

55

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. You can find more information about these in the documentation, but I'll describe them here as well:

  • 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 revision of a given snap has its own copy of these directories. Let me explain with an example.

Say you install revision 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 revision 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 revision 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 revision 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
6
  • 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, 2016 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).
    – kyrofa
    Jul 11, 2016 at 21:05
  • 1
    Note that snap run is used as of v2.15.
    – kyrofa
    Oct 19, 2016 at 6:51
  • 2
    Seem the doc updated, here the ref page snapcraft.io/docs/reference/env
    – user.dz
    Apr 20, 2017 at 14:15
  • 4
    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. Dec 9, 2018 at 4:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .