summary refs log tree commit diff
path: root/nixos/modules/virtualisation/podman.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/virtualisation/podman.nix')
-rw-r--r--nixos/modules/virtualisation/podman.nix115
1 files changed, 98 insertions, 17 deletions
diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix
index e0e2f04e24c..e245004e04a 100644
--- a/nixos/modules/virtualisation/podman.nix
+++ b/nixos/modules/virtualisation/podman.nix
@@ -1,6 +1,8 @@
 { config, lib, pkgs, ... }:
 let
   cfg = config.virtualisation.podman;
+  toml = pkgs.formats.toml { };
+  json = pkgs.formats.json { };
 
   inherit (lib) mkOption types;
 
@@ -21,14 +23,24 @@ let
     done
   '';
 
-  # Copy configuration files to avoid having the entire sources in the system closure
-  copyFile = filePath: pkgs.runCommandNoCC (builtins.unsafeDiscardStringContext (builtins.baseNameOf filePath)) {} ''
-    cp ${filePath} $out
+  net-conflist = pkgs.runCommand "87-podman-bridge.conflist" {
+    nativeBuildInputs = [ pkgs.jq ];
+    extraPlugins = builtins.toJSON cfg.defaultNetwork.extraPlugins;
+    jqScript = ''
+      . + { "plugins": (.plugins + $extraPlugins) }
+    '';
+  } ''
+    jq <${cfg.package}/etc/cni/net.d/87-podman-bridge.conflist \
+      --argjson extraPlugins "$extraPlugins" \
+      "$jqScript" \
+      >$out
   '';
 
 in
 {
   imports = [
+    ./podman-dnsname.nix
+    ./podman-network-socket.nix
     (lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ])
   ];
 
@@ -50,6 +62,20 @@ in
         '';
       };
 
+    dockerSocket.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Make the Podman socket available in place of the Docker socket, so
+        Docker tools can find the Podman socket.
+
+        Podman implements the Docker API.
+
+        Users must be in the <code>podman</code> group in order to connect. As
+        with Docker, members of this group can gain root access.
+      '';
+    };
+
     dockerCompat = mkOption {
       type = types.bool;
       default = false;
@@ -58,6 +84,14 @@ in
       '';
     };
 
+    enableNvidia = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable use of NVidia GPUs from within podman containers.
+      '';
+    };
+
     extraPackages = mkOption {
       type = with types; listOf package;
       default = [ ];
@@ -80,24 +114,71 @@ in
       '';
     };
 
+    defaultNetwork.extraPlugins = lib.mkOption {
+      type = types.listOf json.type;
+      default = [];
+      description = ''
+        Extra CNI plugin configurations to add to podman's default network.
+      '';
+    };
 
   };
 
-  config = lib.mkIf cfg.enable {
-
-    environment.systemPackages = [ cfg.package ]
-      ++ lib.optional cfg.dockerCompat dockerCompat;
-
-    environment.etc."cni/net.d/87-podman-bridge.conflist".source = copyFile "${pkgs.podman-unwrapped.src}/cni/87-podman-bridge.conflist";
-
-    # Enable common /etc/containers configuration
-    virtualisation.containers.enable = true;
+  config = lib.mkIf cfg.enable (lib.mkMerge [
+    {
+      environment.systemPackages = [ cfg.package ]
+        ++ lib.optional cfg.dockerCompat dockerCompat;
+
+      environment.etc."cni/net.d/87-podman-bridge.conflist".source = net-conflist;
+
+      virtualisation.containers = {
+        enable = true; # Enable common /etc/containers configuration
+        containersConf.settings = lib.optionalAttrs cfg.enableNvidia {
+          engine = {
+            conmon_env_vars = [ "PATH=${lib.makeBinPath [ pkgs.nvidia-podman ]}" ];
+            runtimes.nvidia = [ "${pkgs.nvidia-podman}/bin/nvidia-container-runtime" ];
+          };
+        };
+      };
 
-    assertions = [{
-      assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable;
-      message = "Option dockerCompat conflicts with docker";
-    }];
+      systemd.packages = [ cfg.package ];
 
-  };
+      systemd.services.podman.serviceConfig = {
+        ExecStart = [ "" "${cfg.package}/bin/podman $LOGGING system service" ];
+      };
 
+      systemd.sockets.podman.wantedBy = [ "sockets.target" ];
+      systemd.sockets.podman.socketConfig.SocketGroup = "podman";
+
+      systemd.tmpfiles.packages = [
+        # The /run/podman rule interferes with our podman group, so we remove
+        # it and let the systemd socket logic take care of it.
+        (pkgs.runCommand "podman-tmpfiles-nixos" { package = cfg.package; } ''
+          mkdir -p $out/lib/tmpfiles.d/
+          grep -v 'D! /run/podman 0700 root root' \
+            <$package/lib/tmpfiles.d/podman.conf \
+            >$out/lib/tmpfiles.d/podman.conf
+        '') ];
+
+      systemd.tmpfiles.rules =
+        lib.optionals cfg.dockerSocket.enable [
+          "L! /run/docker.sock - - - - /run/podman/podman.sock"
+        ];
+
+      users.groups.podman = {};
+
+      assertions = [
+        {
+          assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable;
+          message = "Option dockerCompat conflicts with docker";
+        }
+        {
+          assertion = cfg.dockerSocket.enable -> !config.virtualisation.docker.enable;
+          message = ''
+            The options virtualisation.podman.dockerSocket.enable and virtualisation.docker.enable conflict, because only one can serve the socket.
+          '';
+        }
+      ];
+    }
+  ]);
 }