anvil-editor: init at 0.4
[NixPkgs.git] / pkgs / build-support / portable-service / default.nix
blob6389e8d66fb1d37d4c297e6ebb00d7533fe36b70
1 { pkgs, lib, stdenv }:
2 /*
3   Create a systemd portable service image
4   https://systemd.io/PORTABLE_SERVICES/
6   Example:
7   pkgs.portableService {
8     pname = "demo";
9     version = "1.0";
10     units = [ demo-service demo-socket ];
11   }
14   # The name and version of the portable service. The resulting image will be
15   # created in result/$pname_$version.raw
16   pname
17 , version
19   # Units is a list of derivations for systemd unit files. Those files will be
20   # copied to /etc/systemd/system in the resulting image. Note that the unit
21   # names must be prefixed with the name of the portable service.
22 , units
24   # Basic info about the portable service image, used for the generated
25   # /etc/os-release
26 , description ? null
27 , homepage ? null
29   # A list of attribute sets {object, symlink}. Symlinks will be created
30   # in the root filesystem of the image to objects in the nix store.
31 , symlinks ? [ ]
33   # A list of additional derivations to be included in the image as-is.
34 , contents ? [ ]
36   # mksquashfs options
37 , squashfsTools ? pkgs.squashfsTools
38 , squash-compression ? "xz -Xdict-size 100%"
39 , squash-block-size ? "1M"
42 let
43   filterNull = lib.filterAttrs (_: v: v != null);
44   envFileGenerator = lib.generators.toKeyValue { };
46   rootFsScaffold =
47     let
48       os-release-params = {
49         PORTABLE_ID = pname;
50         PORTABLE_PRETTY_NAME = description;
51         HOME_URL = homepage;
52         ID = "nixos";
53         PRETTY_NAME = "NixOS";
54         BUILD_ID = "rolling";
55       };
56       os-release = pkgs.writeText "os-release"
57         (envFileGenerator (filterNull os-release-params));
59     in
60     stdenv.mkDerivation {
61       pname = "root-fs-scaffold";
62       inherit version;
64       buildCommand = ''
65         # scaffold a file system layout
66         mkdir -p $out/etc/systemd/system $out/proc $out/sys $out/dev $out/run \
67                  $out/tmp $out/var/tmp $out/var/lib $out/var/cache $out/var/log
69         # empty files to mount over with host's version
70         touch $out/etc/resolv.conf $out/etc/machine-id
72         # required for portable services
73         cp ${os-release} $out/etc/os-release
74       ''
75       # units **must** be copied to /etc/systemd/system/
76       + (lib.concatMapStringsSep "\n" (u: "cp ${u} $out/etc/systemd/system/${u.name};") units)
77       + (lib.concatMapStringsSep "\n"
78         ({ object, symlink }: ''
79           mkdir -p $(dirname $out/${symlink});
80           ln -s ${object} $out/${symlink};
81         '')
82         symlinks)
83       ;
84     };
87 assert lib.assertMsg (lib.all (u: lib.hasPrefix pname u.name) units) "Unit names must be prefixed with the service name";
89 stdenv.mkDerivation {
90   pname = "${pname}-img";
91   inherit version;
93   nativeBuildInputs = [ squashfsTools ];
94   closureInfo = pkgs.closureInfo { rootPaths = [ rootFsScaffold ] ++ contents; };
96   buildCommand = ''
97     mkdir -p nix/store
98     for i in $(< $closureInfo/store-paths); do
99       cp -a "$i" "''${i:1}"
100     done
102     mkdir -p $out
103     # the '.raw' suffix is mandatory by the portable service spec
104     mksquashfs nix ${rootFsScaffold}/* $out/"${pname}_${version}.raw" \
105       -quiet -noappend \
106       -exit-on-error \
107       -keep-as-directory \
108       -all-root -root-mode 755 \
109       -b ${squash-block-size} -comp ${squash-compression}
110   '';