1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
# Snapd packaging
Snapd upstream project provides reference packaging for various distributions
that are part of its CI process (Ubuntu, Debian, Fedora, openSUSE, Arch etc).
The reference packaging is provided under the top level [packaging
directory](/packaging) in snapd source tree.
It is recommended to stay as close as possible to what is in the upstream
repository. Snapd developers keep the packaging updated as new features or
dependencies are introduced. At the same time, we are happy to accept patches
and contributions related to packaging. If you find that the reference packaging
is done incorrectly, or does not meet established conventions for your
distribution, feel free to open a pull-request.
The guide focuses on packaging of snapd for use with a classic Linux
distribution, such as Ubuntu, Fedora, Arch Linux, and **not** an immutable
system like Ubuntu Core.
## Dependencies
Majority of snapd is written in Go, but some smaller bits are written in C. See
the [go.mod](/go.mod) file for the minimum required version of Go. While for
building the C code any reasonably recent version of GCC or Clang will suffice.
Other high level build and runtime dependencies are:
- Linux kernel >= 4.4 (or otherwise reasonably recent)
- systemd
- autotools, pkg-config
- libc static
- libudev
- libseccomp
- libcap
- libapparmor (if using AppArmor)
- libselinux (if using SELinux)
- gnupg2
- python3-docutils
- squashfs
## Source tarballs
Snapd [release assets](https://github.com/canonical/snapd/releases/latest)
consist of 3 source tarballs:
- `snapd_<ver>.tar.xz` (e.g. `snapd_2.72.tar.xz`) - a unified snapshot, which
includes the snapd source tree plus all vendored Go dependencies
- `snapd_<ver>.no-vendor.tar.xz` - snapshot without any Go dependencies
- `snapd_<ver>.only-vendor.tar.xz` - snapshot of all Go dependencies only
Refer to the packaging policy of your distribution to decide which source
tarball is appropriate for your use case.
## Configuration and build
The build process of snapd is split in a couple of parts:
- set snapd version
- configure and build the C code
- configure and build the Go code
- generate any other data files
The build version is set by invoking `mkversion.sh` script like so:
``` sh
./mkversion.sh <snapd-version>
# e.g. 2.72.1 with Arch build tag
./mkversion.sh 2.72.1-arch1
```
### C
All of the C code is contained within `cmd` directory. It is configured and
built using autotools. The high level process for building the code is:
``` sh
cd cmd
autoreconf -i -f
./configure <options>
```
Most relevant `configure` options:
- `--enable-apparmor` - enable AppArmor support
- `--enable-selinux` - enable limited SELinux support
- `--libexecdir` - set the location of where snapd internal tools are located,
typically /usr/lib/snapd (or /usr/libexec/snapd)
- `--with-snap-mount-dir` - expected snap mount directory, typically
/var/lib/snapd/snap (or /snap)
### Go
It is recommended to use `packaging/snapd.mk` helper for simplifying the build
of Go code which will invoke `go build` with appropriate options and build tags.
The helper requires a bit of configuration, see [openSUSE RPM
spec](/packaging/opensuse/snapd.spec) for examples of usage. It expects to find a
`snapd.defines.mk` configuration file within the build directory. The file
itself it directly included by `snapd.mk` and so it must follow Make syntax. An
example snippet which generates the configuration file, extracted from openSUSE
RPM spec, is provided below:
``` make
# This file is generated by openSUSE's snapd.spec
###
# Directory variables.
###
# Desired installation prefix, usually /usr
prefix = %{_prefix}
# Desired installation path for system wide binaries, usually /usr/bin
bindir = %{_bindir}
# ...and /usr/sbin
sbindir = %{_sbindir}
# Desired location of snapd internal tools, one of /usr/lib/ or /usr/libexec/
libexecdir = %{_libexecdir}
# Location of manpages, typically /usr/share/man
mandir = %{_mandir}
# Location of data files, typically /usr/share
datadir = %{_datadir}
# Location of local state, typically /var/lib
localstatedir = %{_localstatedir}
# Location of shared state, typically /var
sharedstatedir = %{_sharedstatedir}
# Systemd system units directory, usually /usr/lib/systemd/system
unitdir = %{_unitdir}
# Build directory, depends on the build environment
builddir = %{_builddir}
###
# Build configuration
###
# Enable or disable Ubuntu Core specific pieces, 0|1
with_core_bits = 0
# Expect alternative snap mount directory, 0|1
with_alt_snap_mount_dir = 1
# Enable AppArmor support, 0|1
with_apparmor = 1
# Enable use of PIE when building static binaries, 0|1
# Ensure support in your distribution toolchain.
with_static_pie = $build_with_static_pie
# Use vendored dependencies, 0|1
with_vendor = 1
# Pass any additional flags to `go build`
EXTRA_GO_BUILD_FLAGS = -v -x
# Pass any additional flags for `go tool link` in go build invocation
EXTRA_GO_LDFLAGS = -compressdwarf=false
# Enable test keys
# NOTE this option is relevant only in builds for snapd CI
with_testkeys = 0
```
The helper is invoked like so:
```sh
make -f packaging/snapd.mk \
SNAPD_DEFINES_DIR=$PWD \
install # or: build|check|clean|all
```
Where `SNAPD_DEFINES_DIR` is set to the path of the directory containing
`snapd.defines.mk` file.
### Other build artifacts
The top level `data` directory contains additional files that need to be
configured and built. Those are systemd units, completion support, SELinux
policy module, environment tweaks and similar. The build and installation is
carried out like so, passing a number of overrides for the desired filesystem
locations (snippet extracted from [Fedora
packaging](/packaging/fedora/snapd.spec)):
``` sh
pushd ./data
make BINDIR="%{_bindir}" LIBEXECDIR="%{_libexecdir}" DATADIR="%{_datadir}" \
SYSTEMDSYSTEMUNITDIR="%{_unitdir}" \
USE_CANONICAL_SNAP_MOUNT_DIR=false \
USE_ALT_SNAP_MOUNT_DIR=true \
SNAPD_ENVIRONMENT_FILE="%{_sysconfdir}/sysconfig/snapd"
# or
make install BINDIR=...
popd
```
It is essential to pass the same set of Make variable overrides during build and
installation.
### Notes on building
The following binaries are provided by the native host package, but need to be
executed within the snap sandbox, and as such they need to be built statically:
- snap-exec
- snap-update-ns
- snapctl
- snapd-gdbserver-shim
The reference packaging contains relevant snippets for confirming that the
binaries listed above are indeed built statically. Packagers are encouraged to
copy the applicable snippets as needed.
## Installation
### snap-confine
The `snap-confine` binary is expected to have the file capabilities listed in
[`cmd/snap-confine/snap-confine.v2-only.caps`](/cmd/snap-confine/snap-confine.v2-only.caps).
set on it once the package has been installed.
The [`cmd/snap-confine/snap-confine.caps`](/cmd/snap-confine/snap-confine.caps)
file lists the same set of capabilities, but additionally includes
`cap_setuid,cap_setgid`, which is a workaround for kernel cgroup v1 issues and
relevant only if expecting that the snapd package will be used within a
container running on a host kernel that is booted with cgroup v1 support.
Packaging is encouraged to **not** ship or otherwise use this file, unless
deemed necessary for the use case.
### Systemd units
The main systemd units are `snapd.service`, the snapd daemon, and
`snapd.socket`, a socket unit which is responsible for creating the two sockets
over which clients communicate with snapd: /run/snapd.sock (for `snap` command),
and /run/snapd-snap.sock (for calls from within the sandbox using `snapctl`
tool).
On systems with AppArmor enabled, `snapd.apparmor.service` needs to be installed
as well. It is a dedicated unit which invokes `snapd-apparmor` internal tool,
that is responsible for loading AppArmor profiles of installed snaps.
The table provides a summary of all systemd units that are relevant for classic
distribution packaging:
| Unit | Kind | Purpose |
|-------------------------------|--------|-----------------------------------------------------------------------|
| `snapd.service` | system | Main snapd service |
| `snapd.socket` | system | Snapd sockets unit, activates `snapd.service` |
| `snapd.apparmor.service` | system | Loads snap AppArmor profiles |
| `snapd.mounts.target` | system | Synchronization target right after snap mounts have completed |
| `snapd.mounts-pre.target` | system | Synchronization target for mounting snap units |
| `snapd.seeded.service` | system | Service waiting for snapd initialization to complete |
| `snapd.session-agent.service` | user | User session agent |
| `snapd.session-agent.socket` | user | User session socket for communication with snapd, activates the agent |
It is recommended to enable at least `snapd.socket` and
`snapd.session-agent.socket` units, however this should be done in accordance
with a policy established by a given distribution.
### Directories
The `snapd` daemon will create relevant state directories as needed (see the
reference packaging for a list of actual locations), however some directories
are expected to be created by the packaging, those are:
- /usr/lib/snapd or /usr/libexec/snapd - snapd internal tools directory
- /var/lib/snapd/snap or /snap - snap mount directory
Consult your distribution policies to decide which locations are appropriate.
Historically, the internal tools and snap mount directories needed to be
hardcoded in snapd, however starting with 2.71, `snapd` will probe and use the
locations created by distribution packaging.
Support for classic snaps (such as code editors, compilers etc.) requires /snap
to be present, either as directory, or as a symbolic link pointing to
/var/lib/snapd/snap. The users are free to create a symbolic link themselves and
the packaging should account for that.
### Support scripts
Snapd provides support scripts that can be used during package installation:
#### `snap-mgmt`
This script is expected to be invoked during package removal, in a pre-remove
step, like so:
``` sh
${libexecdir}/snapd/snap-mgmt --purge
```
Its purpose is to ensure that all snaps and their data is removed from system wide locations.
#### `snap-mgmt-selinux`
A support script which can be invoked from the snapd SELinux policy subpackage.
Its purpose is to patch snap mount units to use a dedicated SELinux context for
all snap mounts. The script is only relevant if there is possibility that the
users, on a SELinux enabled system, may be updating from snapd older than 2.39.
|