diff options
author | Дамјан Георгиевски <gdamjan@gmail.com> | 2022-08-25 23:14:41 +0200 |
---|---|---|
committer | Дамјан Георгиевски <gdamjan@gmail.com> | 2022-09-22 20:11:25 +0200 |
commit | 499aebcf340f48ef02211700b39512c429bf88bb (patch) | |
tree | 8900d10000369c8f5bbfbc01d97b04551b68471a /pkgs/build-support/portable-service/default.nix | |
parent | a22f7345336c7bbb785d3525c6760c5391c3171f (diff) | |
download | nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.tar nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.tar.gz nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.tar.bz2 nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.tar.lz nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.tar.xz nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.tar.zst nixpkgs-499aebcf340f48ef02211700b39512c429bf88bb.zip |
portableService: tooling to create portable service images
see https://systemd.io/PORTABLE_SERVICES/ about the definition of portable services. this tooling is analogous to the `pkgs.dockerTools.buildImage` tooling and is called `pkgs.portableService`. systemd (since version 239) supports a concept of “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. The primary tool for interacting with Portable Services is portablectl, and they are managed by the systemd-portabled service. This function will create a squashfs raw image in `result/$pname_$version.raw` that has the required files by the portable services spec, and all the dependencies for the running program in the nix store.
Diffstat (limited to 'pkgs/build-support/portable-service/default.nix')
-rw-r--r-- | pkgs/build-support/portable-service/default.nix | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/pkgs/build-support/portable-service/default.nix b/pkgs/build-support/portable-service/default.nix new file mode 100644 index 00000000000..6389e8d66fb --- /dev/null +++ b/pkgs/build-support/portable-service/default.nix @@ -0,0 +1,111 @@ +{ pkgs, lib, stdenv }: +/* + Create a systemd portable service image + https://systemd.io/PORTABLE_SERVICES/ + + Example: + pkgs.portableService { + pname = "demo"; + version = "1.0"; + units = [ demo-service demo-socket ]; + } +*/ +{ + # The name and version of the portable service. The resulting image will be + # created in result/$pname_$version.raw + pname +, version + + # Units is a list of derivations for systemd unit files. Those files will be + # copied to /etc/systemd/system in the resulting image. Note that the unit + # names must be prefixed with the name of the portable service. +, units + + # Basic info about the portable service image, used for the generated + # /etc/os-release +, description ? null +, homepage ? null + + # A list of attribute sets {object, symlink}. Symlinks will be created + # in the root filesystem of the image to objects in the nix store. +, symlinks ? [ ] + + # A list of additional derivations to be included in the image as-is. +, contents ? [ ] + + # mksquashfs options +, squashfsTools ? pkgs.squashfsTools +, squash-compression ? "xz -Xdict-size 100%" +, squash-block-size ? "1M" +}: + +let + filterNull = lib.filterAttrs (_: v: v != null); + envFileGenerator = lib.generators.toKeyValue { }; + + rootFsScaffold = + let + os-release-params = { + PORTABLE_ID = pname; + PORTABLE_PRETTY_NAME = description; + HOME_URL = homepage; + ID = "nixos"; + PRETTY_NAME = "NixOS"; + BUILD_ID = "rolling"; + }; + os-release = pkgs.writeText "os-release" + (envFileGenerator (filterNull os-release-params)); + + in + stdenv.mkDerivation { + pname = "root-fs-scaffold"; + inherit version; + + buildCommand = '' + # scaffold a file system layout + mkdir -p $out/etc/systemd/system $out/proc $out/sys $out/dev $out/run \ + $out/tmp $out/var/tmp $out/var/lib $out/var/cache $out/var/log + + # empty files to mount over with host's version + touch $out/etc/resolv.conf $out/etc/machine-id + + # required for portable services + cp ${os-release} $out/etc/os-release + '' + # units **must** be copied to /etc/systemd/system/ + + (lib.concatMapStringsSep "\n" (u: "cp ${u} $out/etc/systemd/system/${u.name};") units) + + (lib.concatMapStringsSep "\n" + ({ object, symlink }: '' + mkdir -p $(dirname $out/${symlink}); + ln -s ${object} $out/${symlink}; + '') + symlinks) + ; + }; +in + +assert lib.assertMsg (lib.all (u: lib.hasPrefix pname u.name) units) "Unit names must be prefixed with the service name"; + +stdenv.mkDerivation { + pname = "${pname}-img"; + inherit version; + + nativeBuildInputs = [ squashfsTools ]; + closureInfo = pkgs.closureInfo { rootPaths = [ rootFsScaffold ] ++ contents; }; + + buildCommand = '' + mkdir -p nix/store + for i in $(< $closureInfo/store-paths); do + cp -a "$i" "''${i:1}" + done + + mkdir -p $out + # the '.raw' suffix is mandatory by the portable service spec + mksquashfs nix ${rootFsScaffold}/* $out/"${pname}_${version}.raw" \ + -quiet -noappend \ + -exit-on-error \ + -keep-as-directory \ + -all-root -root-mode 755 \ + -b ${squash-block-size} -comp ${squash-compression} + ''; +} |