1# pkgs.portableService {#sec-pkgs-portableService} 2 3`pkgs.portableService` is a function to create [Portable Services](https://systemd.io/PORTABLE_SERVICES/) in a read-only, immutable, `squashfs` raw disk image. 4This lets you use Nix to build images which can be run on many recent Linux distributions. 5 6::: {.note} 7Portable services are supported starting with systemd 239 (released on 2018-06-22). 8::: 9 10The 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. 11When generated, the image will exist in the Nix store with the `.raw` file extension, as required by the specification. 12See [](#ex-portableService-hello) to understand how to use the output of `portableService`. 13 14## Inputs {#ssec-pkgs-portableService-inputs} 15 16`portableService` expects one argument with the following attributes: 17 18`pname` (String) 19 20: The name of the portable service. 21 The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification. 22 23`version` (String) 24 25: The version of the portable service. 26 The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification. 27 28`units` (List of Attribute Set) 29 30: A list of derivations for systemd unit files. 31 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). 32 See [](#ex-portableService-hello) to better understand this naming constraint. 33 34`description` (String or Null; _optional_) 35 36: If specified, the value is added as `PORTABLE_PRETTY_NAME` to the `/etc/os-release` file in the generated image. 37 This could be used to provide more information to anyone inspecting the image. 38 39 _Default value:_ `null`. 40 41`homepage` (String or Null; _optional_) 42 43: If specified, the value is added as `HOME_URL` to the `/etc/os-release` file in the generated image. 44 This could be used to provide more information to anyone inspecting the image. 45 46 _Default value:_ `null`. 47 48`symlinks` (List of Attribute Set; _optional_) 49 50: A list of attribute sets in the format `{object, symlink}`. 51 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`. 52 53 All packages that `object` depends on and their dependencies are automatically copied into the image. 54 55 This can be used to create symlinks for applications that assume some files to exist globally (`/etc/ssl` or `/bin/bash`, for example). 56 See [](#ex-portableService-symlinks) to understand how to do that. 57 58 _Default value:_ `[]`. 59 60`contents` (List of Attribute Set; _optional_) 61 62: A list of additional derivations to be included as-is in the image. 63 These derivations will be included directly in a `/nix/store` directory inside the image. 64 65 _Default value:_ `[]`. 66 67`squashfsTools` (Attribute Set; _optional_) 68 69: Allows you to override the package that provides {manpage}`mksquashfs(1)`, which is used internally by `portableService`. 70 71 _Default value:_ `pkgs.squashfsTools`. 72 73`squash-compression` (String; _optional_) 74 75: Passed as the compression option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`. 76 77 _Default value:_ `"xz -Xdict-size 100%"`. 78 79`squash-block-size` (String; _optional_) 80 81: Passed as the block size option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`. 82 83 _Default value:_ `"1M"`. 84 85## Examples {#ssec-pkgs-portableService-examples} 86 87[]{#ex-pkgs-portableService} 88:::{.example #ex-portableService-hello} 89# Building a Portable Service image 90 91The following example builds a Portable Service image with the `hello` package, along with a service unit that runs it. 92 93```nix 94{ 95 lib, 96 writeText, 97 portableService, 98 hello, 99}: 100let 101 hello-service = writeText "hello.service" '' 102 [Unit] 103 Description=Hello world service 104 105 [Service] 106 Type=oneshot 107 ExecStart=${lib.getExe hello} 108 ''; 109in 110portableService { 111 pname = "hello"; 112 inherit (hello) version; 113 units = [ hello-service ]; 114} 115``` 116 117After building the package, the generated image can be loaded into a system through {manpage}`portablectl(1)`: 118 119```shell 120$ nix-build 121(some output removed for clarity) 122/nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1 123 124$ portablectl attach /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw 125Created directory /etc/systemd/system.attached. 126Created directory /etc/systemd/system.attached/hello.service.d. 127Written /etc/systemd/system.attached/hello.service.d/20-portable.conf. 128Created symlink /etc/systemd/system.attached/hello.service.d/10-profile.conf → /usr/lib/systemd/portable/profile/default/service.conf. 129Copied /etc/systemd/system.attached/hello.service. 130Created symlink /etc/portables/hello_2.12.1.raw → /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw. 131 132$ systemctl start hello 133$ journalctl -u hello 134Feb 28 22:39:16 hostname systemd[1]: Starting Hello world service... 135Feb 28 22:39:16 hostname hello[102887]: Hello, world! 136Feb 28 22:39:16 hostname systemd[1]: hello.service: Deactivated successfully. 137Feb 28 22:39:16 hostname systemd[1]: Finished Hello world service. 138 139$ portablectl detach hello_2.12.1 140Removed /etc/systemd/system.attached/hello.service. 141Removed /etc/systemd/system.attached/hello.service.d/10-profile.conf. 142Removed /etc/systemd/system.attached/hello.service.d/20-portable.conf. 143Removed /etc/systemd/system.attached/hello.service.d. 144Removed /etc/portables/hello_2.12.1.raw. 145Removed /etc/systemd/system.attached. 146``` 147::: 148 149:::{.example #ex-portableService-symlinks} 150# Specifying symlinks when building a Portable Service image 151 152Some services may expect files or directories to be available globally. 153An example is a service which expects all trusted SSL certificates to exist in a specific location by default. 154 155To make things available globally, you must specify the `symlinks` attribute when using `portableService`. 156The 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`). 157 158```nix 159{ 160 lib, 161 writeText, 162 portableService, 163 hello, 164 cacert, 165}: 166let 167 hello-service = writeText "hello.service" '' 168 [Unit] 169 Description=Hello world service 170 171 [Service] 172 Type=oneshot 173 ExecStart=${lib.getExe hello} 174 ''; 175in 176portableService { 177 pname = "hello"; 178 inherit (hello) version; 179 units = [ hello-service ]; 180 symlinks = [ 181 { 182 object = "${cacert}/etc/ssl"; 183 symlink = "/etc/ssl"; 184 } 185 ]; 186} 187``` 188:::