Having Transmission compiled binaries, we can now build our first snap package1. For that we will need the following extra files:
package.yaml (for the package metadata) and
The package directory/files structure will be:
meta/ package.yaml readme.md transmission.png web/* # HTML/static assets for the web UI (copied from the transmission build) x86_64/ lib/* # compiled dependencies/libraries (copied from the deps build) transmission-daemon # binary for the daemon (copied from the transmission build) settings.json transmission-daemon # custom script to run the daemon in snappy
Note the above is just how I decided to organize it, but you can change/adapt as desired. The only required bits are the meta directory and the
readme.md files in there.
A wrapper script to run the daemon is added to define custom environment variables23 to run Transmission daemon taking into account Snappy filesystem structure4. Also, a custom default settings file is provided that enables access to web UI from the local network.
If you take a look, this script will also handle multiple architecture binaries (that will be useful once we compile Transmission for ARM, for example).
Back to snap packaging, the minimal
package.yaml5 for our Transmission package could look something like:
As you can see we are providing our package metadata (icon, version, architectures, etc) and describing how the service is run.
Since the daemon will act as a server and a client, and require access to networking capabilities, we set the respective
caps property. We also declare the
ports we will need to be open, for the web UI (under the
ui label, convention used by webdm to link to the web app) and for the (optional) peers listening.
To build our package, in the package root directory, run:
If everything went ok, you can push it to your Snappy instance as we see in the first post:
We have Transmission daemon running, but you will notice a few issues: the web UI freezes, and checking the logs 6 you will see apparmor denials when trying to access mounts and when attempting to do
This is because our package runs confined, and access to some resources is not allowed by default, for security reasons. You could customize apparmor and security profiles to get access to those resources7, but this will trigger a manual review when uploading the package to the store and it will likely be rejected, since you will be breaking the default confinement. So, instead, let’s try to find a work around.
Checking Transmission source code (this file:
libtransmission/platform-quota.c), you will notice that
quotactl calls are related to the free space checks the daemon does. You can also see that there are different implementations for different platforms, guarded by compilation flags. Then, we can tweak our compilation flags to use a different implementation, particularly the one based on
statvfs, which works without any extra requirement in Snappy, and so it won’t require a custom profile and/or trigger a manual review.
After re-compiling with those changes, re-packaging and pushing to our Snappy instance, everything works as expected and there is no error in the logs!
Exposing other binaries
If you want, you could also provide extra binaries (and/or services) in your package. For example, we could also include and provide binaries for the extra Transmission tools, like
For that, we will be updating our
package.yaml and add the required extra files: the compiled binary and a wrapper script:
meta/ package.yaml readme.md transmission.png web/* x86_64/ lib/* transmission-daemon transmission-remote # binary for the remote tool (copied from the transmission build) settings.json transmission-daemon transmission-remote # script to run remote, similar (simplified) to the one for daemon
package.yaml description we add a new
binaries keyword where we list our new executable entry:
Repackaging and pushing to our instance will make the
transmission.remote executable available.
And that’s it, we have a working Transmission snap package for amd64. Next steps will be:
see Debugging section, https://developer.ubuntu.com/en/snappy/guides/security-policy/ ↩