]> git.ipfire.org Git - thirdparty/systemd.git/blame - docs/PORTABLE_SERVICES.md
docs: place all our markdown docs in rough categories
[thirdparty/systemd.git] / docs / PORTABLE_SERVICES.md
CommitLineData
c3e270f4
FB
1---
2title: Portable Services Introduction
4cdca0af 3category: Concepts
c3e270f4
FB
4---
5
44d565ed
LP
6# Portable Services Introduction
7
8This systemd version includes a preview of the "portable service"
9concept. "Portable Services" are supposed to be an incremental improvement over
10traditional system services, making two specific facets of container management
11available to system services more readily. Specifically:
12
131. The bundling of applications, i.e. packing up multiple services, their
14 binaries and all their dependencies in a single image, and running them
15 directly from it.
16
172. Stricter default security policies, i.e. sand-boxing of applications.
18
19The primary tool for interfacing with "portable services" is the new
20"portablectl" program. It's currently shipped in /usr/lib/systemd/portablectl
21(i.e. not in the `$PATH`), since it's not yet considered part of the officially
22supported systemd interfaces — it's a preview still after all.
23
24Portable services don't bring anything inherently new to the table. All they do
25is put together known concepts in a slightly nicer way to cover a specific set
26of use-cases in a nicer way.
27
991b4350 28## So, what *is* a "Portable Service"?
44d565ed
LP
29
30A portable service is ultimately just an OS tree, either inside of a directory
31tree, or inside a raw disk image containing a Linux file system. This tree is
32called the "image". It can be "attached" or "detached" from the system. When
33"attached" specific systemd units from the image are made available on the host
34system, then behaving pretty much exactly like locally installed system
35services. When "detached" these units are removed again from the host, leaving
36no artifacts around (except maybe messages they might have logged).
37
38The OS tree/image can be created with any tool of your choice. For example, you
39can use `dnf --installroot=` if you like, or `debootstrap`, the image format is
40entirely generic, and doesn't have to carry any specific metadata beyond what
41distribution images carry anyway. Or to say this differently: the image format
42doesn't define any new metadata as unit files and OS tree directories or disk
43images are already sufficient, and pretty universally available these days. One
44particularly nice tool for creating suitable images is
45[mkosi](https://github.com/systemd/mkosi), but many other existing tools will
46do too.
47
48If you so will, "Portable Services" are a nicer way to manage chroot()
49environments, with better security, tooling and behavior.
50
991b4350 51## Where's the difference to a "Container"?
44d565ed
LP
52
53"Container" is a very vague term, after all it is used for
54systemd-nspawn/LXC-type OS containers, for Docker/rkt-like micro service
55containers, and even certain 'lightweight' VM runtimes.
56
57The "portable service" concept ultimately will not provide a fully isolated
58environment to the payload, like containers mostly intend to. Instead they are
59from the beginning more alike regular system services, can be controlled with
60the same tools, are exposed the same way in all infrastructure and so on. Their
61main difference is that the use a different root directory than the rest of the
62system. Hence, the intention is not to run code in a different, isolated world
63from the host — like most containers would do it —, but to run it in the same
64world, but with stricter access controls on what the service can see and do.
65
66As one point of differentiation: as programs run as "portable services" are
67pretty much regular system services, they won't run as PID 1 (like Docker would
68do it), but as normal process. A corollary of that is that they aren't supposed
69to manage anything in their own environment (such as the network) as the
70execution environment is mostly shared with the rest of the system.
71
72The primary focus use-case of "portable services" is to extend the host system
73with encapsulated extensions, but provide almost full integration with the rest
74of the system, though possibly restricted by effective security knobs. This
75focus includes system extensions otherwise sometimes called "super-privileged
76containers".
77
78Note that portable services are only available for system services, not for
79user services. i.e. the functionality cannot be used for the stuff
80bubblewrap/flatpak is focusing on.
81
991b4350 82## Mode of Operation
44d565ed
LP
83
84If you have portable service image, maybe in a raw disk image called
85`foobar_0.7.23.raw`, then attaching the services to the host is as easy as:
86
87```
88# /usr/lib/systemd/portablectl attach foobar_0.7.23.raw
89```
90
91This command does the following:
92
6f61b14d
ДГ
931. It dissects the image, checks and validates the `/etc/os-release`
94 (or `/usr/lib/os-release`, see below) data of the image, and looks for
95 all included unit files.
44d565ed
LP
96
972. It copies out all unit files with a suffix of `.service`, `.socket`,
98 `.target`, `.timer` and `.path`. whose name begins with the image's name
99 (with the .raw removed), truncated at the first underscore (if there is
100 one). This prefix name generated from the image name must be followed by a
101 ".", "-" or "@" character in the unit name. Or in other words, given the
102 image name of `foobar_0.7.23.raw` all unit files matching
103 `foobar-*.{service|socket|target|timer|path}`,
104 `foobar@.{service|socket|target|timer|path}` as well as
105 `foobar.*.{service|socket|target|timer|path}` and
106 `foobar.{service|socket|target|timer|path}` are copied out. These unit files
83f72cd6
LP
107 are placed in `/etc/systemd/system.attached/` (which is part of the normal
108 unit file search path of PID 1, and thus loaded exactly like regular unit
109 files). Within the images the unit files are looked for at the usual
110 locations, i.e. in `/usr/lib/systemd/system/` and `/etc/systemd/system/` and
111 so on, relative to the image's root.
44d565ed
LP
112
1133. For each such unit file a drop-in file is created. Let's say
114 `foobar-waldo.service` was one of the unit files copied to
83f72cd6
LP
115 `/etc/systemd/system.attached/`, then a drop-in file
116 `/etc/systemd/system.attached/foobar-waldo.service.d/20-portable.conf` is
117 created, containing a few lines of additional configuration:
44d565ed
LP
118
119 ```
120 [Service]
121 RootImage=/path/to/foobar.raw
122 Environment=PORTABLE=foobar
123 LogExtraFields=PORTABLE=foobar
124 ```
125
1264. For each such unit a "profile" drop-in is linked in. This "profile" drop-in
127 generally contains security options that lock down the service. By default
128 the `default` profile is used, which provides a medium level of
129 security. There's also `trusted` which runs the service at the highest
b99bfb13 130 privileges, i.e. host's root and everything. The `strict` profile comes with
44d565ed
LP
131 the toughest security restrictions. Finally, `nonetwork` is like `default`
132 but without network access. Users may define their own profiles too (or
133 modify the existing ones)
134
135And that's already it.
136
137Note that the images need to stay around (and the same location) as long as the
138portable service is attached. If an image is moved, the `RootImage=` line
139written to the unit drop-in would point to an non-existing place, and break the
140logic.
141
142The `portablectl detach` command executes the reverse operation: it looks for
143the drop-ins and the unit files associated with the image, and removes them
144again.
145
146Note that `portable attach` won't enable or start any of the units it copies
147out. This still has to take place in a second, separate step. (That said We
148might add options to do this automatically later on.).
149
991b4350 150## Requirements on Images
44d565ed
LP
151
152Note that portable services don't introduce any new image format, but most OS
153images should just work the way they are. Specifically, the following
154requirements are made for an image that can be attached/detached with
155`portablectl`.
156
957848db
LP
1571. It must contain an executable that shall be invoked, along with all its
158 dependencies. If binary code, the code needs to be compiled for an
159 architecture compatible with the host.
44d565ed
LP
160
1612. The image must either be a plain sub-directory (or btrfs subvolume)
162 containing the binaries and its dependencies in a classic Linux OS tree, or
163 must be a raw disk image either containing only one, naked file system, or
164 an image with a partition table understood by the Linux kernel with only a
165 single partition defined, or alternatively, a GPT partition table with a set
166 of properly marked partitions following the [Discoverable Partitions
167 Specification](https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/).
168
1693. The image must at least contain one matching unit file, with the right name
170 prefix and suffix (see above). The unit file is searched in the usual paths,
171 i.e. primarily /etc/systemd/system/ and /usr/lib/systemd/system/ within the
172 image. (The implementation will check a couple of other paths too, but it's
173 recommended to use these two paths.)
174
6f61b14d
ДГ
1754. The image must contain an os-release file, either in `/etc/os-release` or
176 `/usr/lib/os-release`. The file should follow the standard format.
177
1785. The image must contain the files `/etc/resolv.conf` and `/etc/machine-id`
179 (empty files are ok), they will be bind mounted from the host at runtime.
44d565ed 180
957848db
LP
1816. The image must contain directories `/proc/`, `/sys/`, `/dev/`, `/run/`,
182 `/tmp/`, `/var/tmp/` that can be mounted over with the corresponding version
183 from the host.
184
1857. The OS might require other files or directories to be in place. For example,
186 if the image is built based on glibc, the dynamic loader needs to be
187 available in `/lib/ld-linux.so.2` or `/lib64/ld-linux-x86-64.so.2` (or
188 similar, depending on architecture), and if the distribution implements a
189 merged `/usr/` tree, this means `/lib` and/or `/lib64` need to be symlinks
190 to their respective counterparts below `/usr/`. For details see your
191 distribution's documentation.
192
193Note that images created by tools such as `debootstrap`, `dnf --installroot=`
194or `mkosi` generally qualify for all of the above in one way or another. If you
195wonder what the most minimal image would be that complies with the requirements
196above, it could consist of this:
44d565ed
LP
197
198```
570ee29c
LP
199/usr/bin/minimald # a statically compiled binary
200/usr/lib/systemd/system/minimal-test.service # the unit file for the service, with ExecStart=/usr/bin/minimald
201/usr/lib/os-release # an os-release file explaining what this is
202/etc/resolv.conf # empty file to mount over with host's version
203/etc/machine-id # ditto
204/proc/ # empty directory to use as mount point for host's API fs
205/sys/ # ditto
206/dev/ # ditto
207/run/ # ditto
208/tmp/ # ditto
209/var/tmp/ # ditto
44d565ed
LP
210```
211
212And that's it.
213
214Note that qualifying images do not have to contain an init system of their
215own. If they do, it's fine, it will be ignored by the portable service logic,
216but they generally don't have to, and it might make sense to avoid any, to keep
217images minimal.
218
957848db
LP
219If the image is writable, and some of the files or directories that are
220overmounted from the host do not exist yet they are automatically created. On
221read-only, immutable images (e.g. squashfs images) all files and directories to
222over-mount must exist already.
223
44d565ed
LP
224Note that as no new image format or metadata is defined, it's very
225straight-forward to define images than can be made use of it a number of
226different ways. For example, by using `mkosi -b` you can trivially build a
227single, unified image that:
228
2291. Can be attached as portable service, to run any container services natively
230 on the host.
231
2322. Can be run as OS container, using `systemd-nspawn`, by booting the image
233 with `systemd-nspawn -i -b`.
234
2353. Can be booted directly as VM image, using a generic VM executor such as
236 `virtualbox`/`qemu`/`kvm`
237
2384. Can be booted directly on bare-metal systems.
239
240Of course, to facilitate 2, 3 and 4 you need to include an init system in the
241image. To facility 3 and 4 you also need to include a boot loader in the
242image. As mentioned `mkosi -b` takes care of all of that for you, but any other
243image generator should work too.
244
991b4350 245## Execution Environment
44d565ed
LP
246
247Note that the code in portable service images is run exactly like regular
248services. Hence there's no new execution environment to consider. Oh, unlike
249Docker would do it, as these are regular system services they aren't run as PID
2501 either, but with regular PID values.
251
991b4350 252## Access to host resources
44d565ed
LP
253
254If services shipped with this mechanism shall be able to access host resources
255(such as files or AF_UNIX sockets for IPC), use the normal `BindPaths=` and
256`BindReadOnlyPaths=` settings in unit files to mount them in. In fact the
257`default` profile mentioned above makes use of this to ensure
258`/etc/resolv.conf`, the D-Bus system bus socket or write access to the logging
259subsystem are available to the service.
260
991b4350 261## Instantiation
44d565ed
LP
262
263Sometimes it makes sense to instantiate the same set of services multiple
264times. The portable service concept does not introduce a new logic for this. It
265is recommended to use the regular unit templating of systemd for this, i.e. to
266include template units such as `foobar@.service`, so that instantiation is as
267simple as:
268
269```
270# /usr/lib/systemd/portablectl attach foobar_0.7.23.raw
271# systemctl enable --now foobar@instancea.service
272# systemctl enable --now foobar@instanceb.service
273
274```
275
276The benefit of this approach is that templating works exactly the same for
277units shipped with the OS itself as for attached portable services.
278
991b4350 279## Immutable images with local data
44d565ed
LP
280
281It's a good idea to keep portable service images read-only during normal
282operation. In fact all but the `trusted` profile will default to this kind of
283behaviour, by setting the `ProtectSystem=strict` option. In this case writable
284service data may be placed on the host file system. Use `StateDirectory=` in
285the unit files to enable such behaviour and add a local data directory to the
286services copied onto the host.