nixpkgs/doc/build-helpers/images/portableservice.section.md

6.6 KiB

pkgs.portableService

pkgs.portableService is a function to create Portable Services in a read-only, immutable, squashfs raw disk image. This lets you use Nix to build images which can be run on many recent Linux distributions.

::: {.note} Portable services are supported starting with systemd 239 (released on 2018-06-22). :::

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 to understand how to use the output of 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 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 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

[]{#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.

{ lib, writeText, portableService, hello }:
let
  hello-service = writeText "hello.service" ''
    [Unit]
    Description=Hello world service

    [Service]
    Type=oneshot
    ExecStart=${lib.getExe hello}
  '';
in
portableService {
  pname = "hello";
  inherit (hello) version;
  units = [ hello-service ];
}

After building the package, the generated image can be loaded into a system through {manpage}portablectl(1):

$ 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.

:::

:::{.example #ex-portableService-symlinks}

Specifying symlinks when building a Portable Service image

Some services may expect files or directories to be available globally. An example is a service which expects all trusted SSL certificates to exist in a specific location by default.

To make things available globally, you must specify the symlinks attribute when using portableService. The following package builds on the package from to make /etc/ssl available globally (this is only for illustrative purposes, because hello doesn't use /etc/ssl).

{ lib, writeText, portableService, hello, cacert }:
let
  hello-service = writeText "hello.service" ''
    [Unit]
    Description=Hello world service

    [Service]
    Type=oneshot
    ExecStart=${lib.getExe hello}
  '';
in
portableService {
  pname = "hello";
  inherit (hello) version;
  units = [ hello-service ];
  symlinks = [
    { object = "${cacert}/etc/ssl"; symlink = "/etc/ssl"; }
  ];
}

:::