about summary refs log tree commit diff
path: root/nixos/modules/virtualisation
diff options
context:
space:
mode:
authorFélix Baylac Jacqué <felix@alternativebit.fr>2023-07-06 13:14:48 +0200
committerFélix Baylac Jacqué <felix@alternativebit.fr>2023-07-06 13:35:31 +0200
commitb7fd022677881ef364859c1c1a54552a470c1f0a (patch)
tree566012b98d351f7a5e671abe044021eed1a2d760 /nixos/modules/virtualisation
parent639ad2f7510a154bc11184dc8b07b10e120c2240 (diff)
downloadnixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.tar
nixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.tar.gz
nixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.tar.bz2
nixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.tar.lz
nixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.tar.xz
nixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.tar.zst
nixlib-b7fd022677881ef364859c1c1a54552a470c1f0a.zip
nixos/oci-containers: make systemd service pre-start extensible
We were setting the systemd pre-start script through the
systemd.services.<name>.preStart NixOS option. This option uses a
string containing the pre-start script as input.

In some scenarios, you want to extend this script to perform some
additional actions before launching a container.

At the moment, your only option is to mkForce the pre-start string and
rewrite a preStart script from scratch. Potentially vendoring the
Nixpkgs pre-start script in your custom pre-start script. (you can
also create a new service unit in charge of running the custom
pre-start and create a dependency link between the units, but that's
also sub-optimal).

The systemd.services.<name>.serviceConfig.ExecStartPre NixOS option
gives us a better way to extend a pre-start script. Instead of being a
simple script, this option can be a list of scripts. The NixOS module
system then merges the multiple list declarations instead of
overriding them. Meaning that if we use this ExecStartPre option, we
can trivially extend the exec-start script: just add the custom script
in the systemd service override and you're done.

ExecStartPre behaves a tiny bit differently from preStart. Instead of
expecting a string containing a script, it expects a path pointing to
a script. We take advantage of this API change to check the pre-start
script with shellCheck via the pkgs.writeShellApplication function.
Diffstat (limited to 'nixos/modules/virtualisation')
-rw-r--r--nixos/modules/virtualisation/oci-containers.nix39
1 files changed, 21 insertions, 18 deletions
diff --git a/nixos/modules/virtualisation/oci-containers.nix b/nixos/modules/virtualisation/oci-containers.nix
index a9f4ab77f866..402adef7d81a 100644
--- a/nixos/modules/virtualisation/oci-containers.nix
+++ b/nixos/modules/virtualisation/oci-containers.nix
@@ -228,6 +228,26 @@ let
   mkService = name: container: let
     dependsOn = map (x: "${cfg.backend}-${x}.service") container.dependsOn;
     escapedName = escapeShellArg name;
+    preStartScript = pkgs.writeShellApplication {
+      name = "pre-start";
+      runtimeInputs = [ ];
+      text = ''
+        ${cfg.backend} rm -f ${name} || true
+        ${optionalString (isValidLogin container.login) ''
+          cat ${container.login.passwordFile} | \
+          ${cfg.backend} login \
+          ${container.login.registry} \
+          --username ${container.login.username} \
+          --password-stdin
+        ''}
+        ${optionalString (container.imageFile != null) ''
+          ${cfg.backend} load -i ${container.imageFile}
+        ''}
+        ${optionalString (cfg.backend == "podman") ''
+          rm -f /run/podman-${escapedName}.ctr-id
+        ''}
+      '';
+    };
   in {
     wantedBy = [] ++ optional (container.autoStart) "multi-user.target";
     after = lib.optionals (cfg.backend == "docker") [ "docker.service" "docker.socket" ]
@@ -242,23 +262,6 @@ let
       else if cfg.backend == "podman" then [ config.virtualisation.podman.package ]
       else throw "Unhandled backend: ${cfg.backend}";
 
-    preStart = ''
-      ${cfg.backend} rm -f ${name} || true
-      ${optionalString (isValidLogin container.login) ''
-        cat ${container.login.passwordFile} | \
-          ${cfg.backend} login \
-            ${container.login.registry} \
-            --username ${container.login.username} \
-            --password-stdin
-        ''}
-      ${optionalString (container.imageFile != null) ''
-        ${cfg.backend} load -i ${container.imageFile}
-        ''}
-      ${optionalString (cfg.backend == "podman") ''
-        rm -f /run/podman-${escapedName}.ctr-id
-        ''}
-      '';
-
     script = concatStringsSep " \\\n  " ([
       "exec ${cfg.backend} run"
       "--rm"
@@ -306,7 +309,7 @@ let
       ###
       # ExecReload = ...;
       ###
-
+      ExecStartPre = [ "${preStartScript}/bin/pre-start" ];
       TimeoutStartSec = 0;
       TimeoutStopSec = 120;
       Restart = "always";