portable-svc/default.nix

84 lines
1.9 KiB
Nix
Raw Normal View History

{ pkgs, lib, stdenv }:
/*
Create a systemd portable service image
https://systemd.io/PORTABLE_SERVICES/
Example:
pkgs.portableService {
name = "hello";
version = "2.4.3";
description = "hello portable";
units = [ hello-service ./files/hello.socket ];
symlinks = [
{ object = "${pkgs.cacert}/etc/ssl"; symlink = "/etc/ssl"; }
{ object = "${pkgs.bash}/bin/bash"; symlink = "/bin/sh"; }
];
}
*/
{ name
, version ? "dev"
, description ? null
, homepage ? null
, units ? [ ]
, symlinks ? [ ]
, contents ? [ ]
, squashfsTools ? pkgs.squashfsTools
, squash-compression ? "xz -Xdict-size 100%"
, squash-block-size ? "1M"
}:
let
image-name = "${name}_${version}";
os-release-params = lib.filterAttrs (n: v: v != null) {
PORTABLE_ID = name;
PORTABLE_PRETTY_NAME = description;
HOME_URL = homepage;
ID = "nixos";
PRETTY_NAME = "NixOS";
BUILD_ID = "rolling";
};
os-release = pkgs.writeText "os-release" (lib.generators.toKeyValue {} os-release-params);
getUnitName = u:
if lib.isDerivation u then u.name
else if builtins.isPath u then baseNameOf u
else throw "unit must be either derivation or path";
rootfs = stdenv.mkDerivation {
name = "rootfs";
serviceName = name;
builder = ./build-rootfs.sh;
inherit units;
unitNames = map getUnitName units;
osRelease = os-release;
objects = map (x: x.object) symlinks;
targets = map (x: x.symlink) symlinks;
};
in
stdenv.mkDerivation {
name = "${image-name}.raw";
nativeBuildInputs = [ squashfsTools ];
buildCommand = ''
closureInfo=${pkgs.closureInfo { rootPaths = contents ++ [rootfs]; }}
mkdir -p nix/store
for i in $(< $closureInfo/store-paths); do
cp -a "$i" "''${i:1}"
done
mksquashfs nix ${rootfs}/* $out \
-quiet -noappend \
-keep-as-directory \
-all-root -root-mode 755 \
-b ${squash-block-size} -comp ${squash-compression}
'';
}