How to make deb or rpm packages work inside snaps

There are several different approaches you can use here, @chani, and the best one really depends on details of the application you are using.

When you ask snapcraft to ship a deb or an rpm package in the snap, or even unpack a tarball containing pre-built binaries, the content will be bundled in your snap and will be installed (mounted read-only) in the final system under the /snap/yoursnap/current/ directory. That means you’ll end up with directories which are typically found at the root, such as /usr/bin and /usr/lib under a place they don’t expect, such as /snap/yoursnap/current/usr/bin, etc.

Then, when the application runs, one of these things will happen:

Option 1: application is relocatable

This is the nirvana option, which makes me want to go after developers to buy them tea or beer.

The application might simply not care about where it’s installed, because they have no external resources or looks for them as a path relative to the binary app.

Option 2: application may be configured

In many cases, the application relies on configuration files, environment variables, or even command line flags to tell it where to run. This is very easy to get sorted.

If the application expects a flag defining its root, or perhaps its data directory, simply modify the command: line in the snapcraft.yaml to provide the given flag.

If the application expects a configuration file with its root, that file may be shipped in the snap itself so that it can be pointed to with a flag or similar, or alternatively a copy of that shipped configuration file living in $SNAP_DATA so that other bits may be tuned at runtime.

If the application expects an environment variable, that may also be sorted directly in snapcraft.yaml by including a section either at the top level or under the application entry, along the lines of:

environment:
    SOME_VAR_NAME: /snap/yoursnap/current/

and/or

apps:
    myapp:
        command: ...
        environment:
            SOME_VAR_NAME: /snap/yoursnap/current/

If the configuration is more complex than that, there’s always the option of replacing the application command in snapcraft.yaml with a shell script shipped in the snap which is tasked with performing the configuration and tuning before the real application runs.

In many well known cases, snapcraft itself will do exactly that and inject the wrapper before the actual application is run so that the real command knows where to find its data, its libraries, etc. Looking into the meta/snap.yaml file of the built snap, check the commands to understand better how that takes place.

Option 3: rebuild from source

I realize the topic here is pre-built binaries, but it’s worth pointing out that this is always an option assuming the source code is available. That is, rebuilding the software from source it can always be tuned to look into any desired location.

Option 4: chroot

If the software is hardcoded to look into a fixed location, the option is to tune the world around it instead.

If the software doesn’t care about writing anywhere, it’s trivial to call it from a script with:

chroot $SNAP /usr/bin/app

More likely, though, it’ll want to use some storage, or logs, or temporary files, so that won’t work. If the content of the snap is small enough, it may be copied into a temporary writable directory and have the chroot done there instead.

If that’s not an option, read on.

Option 5: bind mounts

This is the most flexible option of all, but right now it requires the snap to remain in devmode. In the near future, we’ll fix that and make that much easier to do, and it will also work under strict mode.

The idea here is bind-mounting the content you want into specific locations. For example, inside a script used as your app’s command, you can fully replace directories by bind mounting them:

mount --bind /snap/yoursnap/current/opt /optc

This option is extremely flexible and allows pretty much anything to be made to work with enough tuning, but it’s also extremely easy to get wrong, in the sense that you may be making content that you’d like to use later inaccessible. For example, snapctl lives in /usr/bin, so if you want to replace that one it might be good to move the directory elsewhere first.

Once we implement the planned feature, this will be made easier to use.


So those are a few ways in which you can get out of the trouble when using pre-built binaries. There are likely others.

Please let us know how things go for you.

4 Likes