doc: update docs for portableService, follow doc conventions
This commit is contained in:
parent
c5989d6524
commit
62552e3683
2 changed files with 152 additions and 58 deletions
|
@ -1,81 +1,174 @@
|
||||||
# pkgs.portableService {#sec-pkgs-portableService}
|
# pkgs.portableService {#sec-pkgs-portableService}
|
||||||
|
|
||||||
`pkgs.portableService` is a function to create _portable service images_,
|
`pkgs.portableService` is a function to create [Portable Services](https://systemd.io/PORTABLE_SERVICES/) in a read-only, immutable, `squashfs` raw disk image.
|
||||||
as read-only, immutable, `squashfs` archives.
|
This lets you use Nix to build images which can be run on many recent Linux distributions.
|
||||||
|
|
||||||
systemd supports a concept of [Portable Services](https://systemd.io/PORTABLE_SERVICES/).
|
|
||||||
Portable Services are a delivery method for system services that uses two specific features of container management:
|
|
||||||
|
|
||||||
* Applications are bundled. I.e. multiple services, their binaries and
|
|
||||||
all their dependencies are packaged in an image, and are run directly from it.
|
|
||||||
* Stricter default security policies, i.e. sandboxing of applications.
|
|
||||||
|
|
||||||
This allows using Nix to build images which can be run on many recent Linux distributions.
|
|
||||||
|
|
||||||
The primary tool for interacting with Portable Services is `portablectl`,
|
|
||||||
and they are managed by the `systemd-portabled` system service.
|
|
||||||
|
|
||||||
::: {.note}
|
::: {.note}
|
||||||
Portable services are supported starting with systemd 239 (released on 2018-06-22).
|
Portable services are supported starting with systemd 239 (released on 2018-06-22).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
A very simple example of using `portableService` is described below:
|
The generated image will contain the file system structure as required by the Portable Services specification, along with the packages given to `portableService` and all of their dependencies.
|
||||||
|
When generated, the image will exist in the Nix store with the `.raw` file extension, as required by the specification.
|
||||||
|
See [](#ex-portableService-hello) to understand how to use the output of `portableService`.
|
||||||
|
|
||||||
|
## Inputs {#ssec-pkgs-portableService-inputs}
|
||||||
|
|
||||||
|
`portableService` expects one argument with the following attributes:
|
||||||
|
|
||||||
|
`pname` (String)
|
||||||
|
|
||||||
|
: The name of the portable service.
|
||||||
|
The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification.
|
||||||
|
|
||||||
|
`version` (String)
|
||||||
|
|
||||||
|
: The version of the portable service.
|
||||||
|
The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification.
|
||||||
|
|
||||||
|
`units` (List of Attribute Set)
|
||||||
|
|
||||||
|
: A list of derivations for systemd unit files.
|
||||||
|
Each derivation must produce a single file, and must have a name that starts with the value of `pname` and ends with the suffix of the unit type (e.g. ".service", ".socket", ".timer", and so on).
|
||||||
|
See [](#ex-portableService-hello) to better understand this naming constraint.
|
||||||
|
|
||||||
|
`description` (String or Null; _optional_)
|
||||||
|
|
||||||
|
: If specified, the value is added as `PORTABLE_PRETTY_NAME` to the `/etc/os-release` file in the generated image.
|
||||||
|
This could be used to provide more information to anyone inspecting the image.
|
||||||
|
|
||||||
|
_Default value:_ `null`.
|
||||||
|
|
||||||
|
`homepage` (String or Null; _optional_)
|
||||||
|
|
||||||
|
: If specified, the value is added as `HOME_URL` to the `/etc/os-release` file in the generated image.
|
||||||
|
This could be used to provide more information to anyone inspecting the image.
|
||||||
|
|
||||||
|
_Default value:_ `null`.
|
||||||
|
|
||||||
|
`symlinks` (List of Attribute Set; _optional_)
|
||||||
|
|
||||||
|
: A list of attribute sets in the format `{object, symlink}`.
|
||||||
|
For each item in the list, `portableService` will create a symlink in the path specified by `symlink` (relative to the root of the image) that points to `object`.
|
||||||
|
|
||||||
|
All packages that `object` depends on and their dependencies are automatically copied into the image.
|
||||||
|
|
||||||
|
This can be used to create symlinks for applications that assume some files to exist globally (`/etc/ssl` or `/bin/bash`, for example).
|
||||||
|
See [](#ex-portableService-symlinks) to understand how to do that.
|
||||||
|
|
||||||
|
_Default value:_ `[]`.
|
||||||
|
|
||||||
|
`contents` (List of Attribute Set; _optional_)
|
||||||
|
|
||||||
|
: A list of additional derivations to be included as-is in the image.
|
||||||
|
These derivations will be included directly in a `/nix/store` directory inside the image.
|
||||||
|
|
||||||
|
_Default value:_ `[]`.
|
||||||
|
|
||||||
|
`squashfsTools` (Attribute Set; _optional_)
|
||||||
|
|
||||||
|
: Allows you to override the package that provides {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
|
||||||
|
|
||||||
|
_Default value:_ `pkgs.squashfsTools`.
|
||||||
|
|
||||||
|
`squash-compression` (String; _optional_)
|
||||||
|
|
||||||
|
: Passed as the compression option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
|
||||||
|
|
||||||
|
_Default value:_ `"xz -Xdict-size 100%"`.
|
||||||
|
|
||||||
|
`squash-block-size` (String; _optional_)
|
||||||
|
|
||||||
|
: Passed as the block size option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
|
||||||
|
|
||||||
|
_Default value:_ `"1M"`.
|
||||||
|
|
||||||
|
## Examples {#ssec-pkgs-portableService-examples}
|
||||||
|
|
||||||
[]{#ex-pkgs-portableService}
|
[]{#ex-pkgs-portableService}
|
||||||
|
:::{.example #ex-portableService-hello}
|
||||||
|
# Building a Portable Service image
|
||||||
|
|
||||||
|
The following example builds a Portable Service image with the `hello` package, along with a service unit that runs it.
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
pkgs.portableService {
|
{ lib, writeText, portableService, hello }:
|
||||||
pname = "demo";
|
let
|
||||||
version = "1.0";
|
hello-service = writeText "hello.service" ''
|
||||||
units = [ demo-service demo-socket ];
|
[Unit]
|
||||||
|
Description=Hello world service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=${lib.getExe hello}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
portableService {
|
||||||
|
pname = "hello";
|
||||||
|
inherit (hello) version;
|
||||||
|
units = [ hello-service ];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The above example will build an squashfs archive image in `result/$pname_$version.raw`. The image will contain the
|
After building the package, the generated image can be loaded into a system through {manpage}`portablectl(1)`:
|
||||||
file system structure as required by the portable service specification, and a subset of the Nix store with all the
|
|
||||||
dependencies of the two derivations in the `units` list.
|
|
||||||
`units` must be a list of derivations, and their names must be prefixed with the service name (`"demo"` in this case).
|
|
||||||
Otherwise `systemd-portabled` will ignore them.
|
|
||||||
|
|
||||||
::: {.note}
|
```shell
|
||||||
The `.raw` file extension of the image is required by the portable services specification.
|
$ nix-build
|
||||||
|
(some output removed for clarity)
|
||||||
|
/nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1
|
||||||
|
|
||||||
|
$ portablectl attach /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw
|
||||||
|
Created directory /etc/systemd/system.attached.
|
||||||
|
Created directory /etc/systemd/system.attached/hello.service.d.
|
||||||
|
Written /etc/systemd/system.attached/hello.service.d/20-portable.conf.
|
||||||
|
Created symlink /etc/systemd/system.attached/hello.service.d/10-profile.conf → /usr/lib/systemd/portable/profile/default/service.conf.
|
||||||
|
Copied /etc/systemd/system.attached/hello.service.
|
||||||
|
Created symlink /etc/portables/hello_2.12.1.raw → /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw.
|
||||||
|
|
||||||
|
$ systemctl start hello
|
||||||
|
$ journalctl -u hello
|
||||||
|
Feb 28 22:39:16 hostname systemd[1]: Starting Hello world service...
|
||||||
|
Feb 28 22:39:16 hostname hello[102887]: Hello, world!
|
||||||
|
Feb 28 22:39:16 hostname systemd[1]: hello.service: Deactivated successfully.
|
||||||
|
Feb 28 22:39:16 hostname systemd[1]: Finished Hello world service.
|
||||||
|
|
||||||
|
$ portablectl detach hello_2.12.1
|
||||||
|
Removed /etc/systemd/system.attached/hello.service.
|
||||||
|
Removed /etc/systemd/system.attached/hello.service.d/10-profile.conf.
|
||||||
|
Removed /etc/systemd/system.attached/hello.service.d/20-portable.conf.
|
||||||
|
Removed /etc/systemd/system.attached/hello.service.d.
|
||||||
|
Removed /etc/portables/hello_2.12.1.raw.
|
||||||
|
Removed /etc/systemd/system.attached.
|
||||||
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Some other options available are:
|
:::{.example #ex-portableService-symlinks}
|
||||||
- `description`, `homepage`
|
# Specifying symlinks when building a Portable Service image
|
||||||
|
|
||||||
Are added to the `/etc/os-release` in the image and are shown by the portable services tooling.
|
Some services may expect files or directories to be available globally.
|
||||||
Default to empty values, not added to os-release.
|
An example is a service which expects all trusted SSL certificates to exist in a specific location by default.
|
||||||
- `symlinks`
|
|
||||||
|
|
||||||
A list of attribute sets {object, symlink}. Symlinks will be created in the root filesystem of the image to
|
To make things available globally, you must specify the `symlinks` attribute when using `portableService`.
|
||||||
objects in the Nix store. Defaults to an empty list.
|
The following package builds on the package from [](#ex-portableService-hello) to make `/etc/ssl` available globally (this is only for illustrative purposes, because `hello` doesn't use `/etc/ssl`).
|
||||||
- `contents`
|
|
||||||
|
|
||||||
A list of additional derivations to be included in the image Nix store, as-is. Defaults to an empty list.
|
|
||||||
- `squashfsTools`
|
|
||||||
|
|
||||||
Defaults to `pkgs.squashfsTools`, allows you to override the package that provides `mksquashfs`.
|
|
||||||
- `squash-compression`, `squash-block-size`
|
|
||||||
|
|
||||||
Options to `mksquashfs`. Default to `"xz -Xdict-size 100%"` and `"1M"` respectively.
|
|
||||||
|
|
||||||
A typical usage of `symlinks` would be:
|
|
||||||
```nix
|
```nix
|
||||||
symlinks = [
|
{ lib, writeText, portableService, hello, cacert }:
|
||||||
{ object = "${pkgs.cacert}/etc/ssl"; symlink = "/etc/ssl"; }
|
let
|
||||||
{ object = "${pkgs.bash}/bin/bash"; symlink = "/bin/sh"; }
|
hello-service = writeText "hello.service" ''
|
||||||
{ object = "${pkgs.php}/bin/php"; symlink = "/usr/bin/php"; }
|
[Unit]
|
||||||
];
|
Description=Hello world service
|
||||||
```
|
|
||||||
to create these symlinks for legacy applications that assume them existing globally.
|
|
||||||
|
|
||||||
Once the image is created, and deployed on a host in `/var/lib/portables/`, you can attach the image and run the service. As root run:
|
[Service]
|
||||||
```console
|
Type=oneshot
|
||||||
portablectl attach demo_1.0.raw
|
ExecStart=${lib.getExe hello}
|
||||||
systemctl enable --now demo.socket
|
'';
|
||||||
systemctl enable --now demo.service
|
in
|
||||||
|
portableService {
|
||||||
|
pname = "hello";
|
||||||
|
inherit (hello) version;
|
||||||
|
units = [ hello-service ];
|
||||||
|
symlinks = [
|
||||||
|
{ object = "${cacert}/etc/ssl"; symlink = "/etc/ssl"; }
|
||||||
|
];
|
||||||
|
}
|
||||||
```
|
```
|
||||||
::: {.note}
|
|
||||||
See the [man page](https://www.freedesktop.org/software/systemd/man/portablectl.html) of `portablectl` for more info on its usage.
|
|
||||||
:::
|
:::
|
||||||
|
|
|
@ -319,5 +319,6 @@
|
||||||
"group(5)": "https://man.archlinux.org/man/group.5",
|
"group(5)": "https://man.archlinux.org/man/group.5",
|
||||||
"login.defs(5)": "https://man.archlinux.org/man/login.defs.5",
|
"login.defs(5)": "https://man.archlinux.org/man/login.defs.5",
|
||||||
"unshare(1)": "https://man.archlinux.org/man/unshare.1.en",
|
"unshare(1)": "https://man.archlinux.org/man/unshare.1.en",
|
||||||
"nix-shell(1)": "https://nixos.org/manual/nix/stable/command-ref/nix-shell.html"
|
"nix-shell(1)": "https://nixos.org/manual/nix/stable/command-ref/nix-shell.html",
|
||||||
|
"mksquashfs(1)": "https://man.archlinux.org/man/extra/squashfs-tools/mksquashfs.1.en"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue