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