query
On this page

portableService

pkgs.portableService

Functor
Docs pulled from | This Revision | about 1 hour ago


Contribute
Enhance the ecosystem with your expertise! Contribute to fill the gaps in documentation. Your input can make a difference.

Noogle detected

This is a Functor

Learn about functors

Implementation

The following is the current implementation of this function.

{
  # 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.all (u: lib.hasPrefix pname u.name) units
  || throw "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
    # We have to set SOURCE_DATE_EPOCH to 0 here for reproducibility (https://github.com/NixOS/nixpkgs/issues/390696)
    SOURCE_DATE_EPOCH=0 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}
  '';
}