Use of home and network plugs

What is the right way to define a “strict” snap so that it can access the network and a files in the user home directory?

I’m trying to define a snap for an application that needs to read a configuration file in the home directory, and connect via sockets. I’ve try declaring a snap as follows:

app:
  my-app:
    command: run-app
    plugs: [home, network]

However I cannot read files in the home directory, nor I can connect to the newtork when using strict mode. I could not find any information on how to configure this properly. Am I missing something?

you should note that the home plug only allows accessing non-hidden files so if that config file you are using is in a subdir starting with a dot, this wont work … (snap config files should be put into $SNAP_USER_DATA instead which translates to /home/$USER/snap//current … there you can also use dot-prefixed files and dont even need the home plug)

regarding the network part, it would be interesting to see the denials you get in syslog or journalctl …

Beyond @ogra’s points, note that you may very well need network-bind as well.

Oh, that would be a problem, since I expect the users of the app to adapt their configuration files in their home directory, regardless of whether they are using snap… I don’t know if there would be any workaround for this (other than defaulting to “classic” mode).

Beyond @ogra’s points, note that you may very well need network-bind as well.

Great! I was missing that part! Thanks.

I’ll see how to solve the configuration issue…

If all that is wanted is access to configuration files, the best way is indeed to have the snap and its configuration files confined. This protects the user data in general, and enables support for reverts, and soon snapshots as well. It will also make the snap work correctly when we introduce parallel snap installations soon.

I understand. In our case the problem is that we try to build an app for Windows, Linux, and Mac. So this will create inconsistencies when writing the documentation (since different OS will require different locations for the configuration files). Maybe there’s a way to overcome this, but I don’t know it.

Hmm… can you detail it a bit more the issue so we can try to help?

Aren’t the different operating systems already storing their configuration naturally in different locations, for example?

Hmm… can you detailed a bit more the issue so we can try to help?

Sure. Thanks a lot!

The piece of software I’m trying to package is TorXakis. It is a Haskell based project, and it needs two SMT solvers z3 and cvc4 which are run via system calls. I managed to successfully build a snap on this branch (see snap directory). If you have time to review what I’ve done that’d be great. I promise to write about snapping a Haskell app in return :slight_smile:

There are a couple of issues nevertheless:

  1. The configuration file cannot be read, since it is a hidden file. Since we control where the configuration files are stored, this in principle could be worked around by looking at different locations depending on the OS. The problem is the configuration for z3 and cvc4 which we don’t control.
  2. The executables are named torxakis.txsui and torxakis.txsserver. Ideally I would like to have just the unqualified names. I can alias these, but I can only do it manually, which will require an additional step by the user, which I would prefer to avoid at all cost. But I don’t know if this can be done…

Aren’t the different operating systems already storing their configuration naturally in different locations, for example?

Right now we assume the configuration to be stored in $HOME/.torxakis.yaml regardless of the OS. But I guess that I’ll have to change this if I want to use the snap in strict mode.

Thanks a lot for your help!

I’m trying to see if the use of $SNAP_USER_DATA is feasible. How does an application access this directory? Through the $SNAP_USER_DATA variable? In this case the application has to be snap aware, right?

yes, it is in the environment:

$ sudo snap install hello-world
...
$ hello-world.env |grep SNAP
SNAP_USER_COMMON=/home/ogra/snap/hello-world/common
SNAP_CONTEXT=smpRsTNltk8XfDFcrcBDTkvskgqW4qXWTSjP5g6D0B8P
SNAP_LIBRARY_PATH=/var/lib/snapd/lib/gl:
SNAP_COMMON=/var/snap/hello-world/common
SNAP_USER_DATA=/home/ogra/snap/hello-world/27
SNAP_DATA=/var/snap/hello-world/27
SNAP_REVISION=27
SNAP_NAME=hello-world
SNAP_COOKIE=smpRsTNltk8XfDFcrcBDTkvskgqW4qXWTSjP5g6D0B8P
SNAP_ARCH=amd64
SNAP_VERSION=6.3
SNAP=/snap/hello-world/27
$
1 Like

For exactly that reason, we actually change $HOME in strict snaps so it matches $SNAP_USER_DATA, so in theory it won’t have to do anything else. Did you find any issues doing that?

Deal! :slight_smile:

The snapcraft.yaml file looks very reasonable. The only thing that might optionally be changed is perhaps to move the plugs to the global scope, since every application is already using them:

plugs:
    network: 
    network-bind:
    home:

This works as long as they’re indeed needed for every application. Once applications require differences, then they must be locally declared again.

Oh, that’s a very important piece of information! So that means that within my application I could just look at $HOME/.torxakis.yaml? In that case, what worries me is that I won’t be able to access the user files, and this is a must. User usually store their models (text files) anywhere within their home, so the application should be able to have read-access to them.

The snapcraft.yaml file looks very reasonable. The only thing that might optionally be changed is perhaps to move the plugs to the global scope, since every application is already using them:

Nice tip, I was looking for a way to factoring this out!

If you have the home interface connected (which happens automatically as long as you have the plug defined), then the access to the usual home is also granted. It’s just not what $HOME will point to.

1 Like

Now I’m trying to copy some bootstrap configuration to $SNAP_USER_DATA during in the install hook. However I don’t know where to place this bootstrap configuration so that the installation script can see it…

For instance this won’t work:

#!/bin/sh

# Installation script to run upon snap installation.

if [ -z "$SNAP_USER_DATA" ]; then
    echo "Variable SNAP_USER_DATA is not defined"
    exit 1
fi

cp data/bootstrap-config.yaml $SNAP_USER_DATA/.torxakis.yml

the install hook does not run as the user, so $SNAP_USER_DATA (if set at all at this point) would point to /root/snap/<snapname>/<version> …

you would have to use a wrapper script around your app instead …

Right, consider that this would have to do something every time a different user tries to use the application, and new users may be added after the snap has been installed.

the install hook does not run as the user, so $SNAP_USER_DATA (if set at all at this point) would point to /root/snap// …

Of course! I overlooked that sudo part before the install as well :frowning:

Ok, suppose that I run the script above upon initializing the app (if there is no configuration file, then copy one). The question is where the app can copy the bootstrap configuration file from?

have a look at line 31 in

this snap ships the default config in the toplevel of the package … if you have some subdir for your initial defaults you’d add that to your source path in the copy command …

cp $SNAP/mydefaultconfigpath/myconfig.conf $SNAP_USER_DATA/
1 Like

have a look at line 31 in

I see. For the case at hand, the bootstrap configuration (.torxakis.yaml) lives in the root directory of the source repository. But I currently I’m not dumping the whole directory (I’m packaging a pre-built app since Haskell is not a supported language):

parts:  
  torxakis-bin:
    plugin: dump
    source: .stack-work/install/x86_64-linux-nopie/lts-9.7/8.0.2/bin/

Should I put the configuration in a data directory and add:

  torxakis-data:
    plugin: dump
    source: data/