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