at 23.05-pre 5.7 kB view raw
1{ config, lib, pkgs, ... }: 2let 3 cfg = config.virtualisation.podman; 4 toml = pkgs.formats.toml { }; 5 json = pkgs.formats.json { }; 6 7 inherit (lib) mkOption types; 8 9 podmanPackage = (pkgs.podman.override { 10 extraPackages = cfg.extraPackages 11 ++ lib.optional (builtins.elem "zfs" config.boot.supportedFilesystems) config.boot.zfs.package; 12 }); 13 14 # Provides a fake "docker" binary mapping to podman 15 dockerCompat = pkgs.runCommand "${podmanPackage.pname}-docker-compat-${podmanPackage.version}" 16 { 17 outputs = [ "out" "man" ]; 18 inherit (podmanPackage) meta; 19 } '' 20 mkdir -p $out/bin 21 ln -s ${podmanPackage}/bin/podman $out/bin/docker 22 23 mkdir -p $man/share/man/man1 24 for f in ${podmanPackage.man}/share/man/man1/*; do 25 basename=$(basename $f | sed s/podman/docker/g) 26 ln -s $f $man/share/man/man1/$basename 27 done 28 ''; 29 30 net-conflist = pkgs.runCommand "87-podman-bridge.conflist" 31 { 32 nativeBuildInputs = [ pkgs.jq ]; 33 extraPlugins = builtins.toJSON cfg.defaultNetwork.extraPlugins; 34 jqScript = '' 35 . + { "plugins": (.plugins + $extraPlugins) } 36 ''; 37 } '' 38 jq <${cfg.package}/etc/cni/net.d/87-podman-bridge.conflist \ 39 --argjson extraPlugins "$extraPlugins" \ 40 "$jqScript" \ 41 >$out 42 ''; 43 44in 45{ 46 imports = [ 47 ./dnsname.nix 48 ./network-socket.nix 49 ]; 50 51 meta = { 52 maintainers = lib.teams.podman.members; 53 }; 54 55 options.virtualisation.podman = { 56 57 enable = 58 mkOption { 59 type = types.bool; 60 default = false; 61 description = lib.mdDoc '' 62 This option enables Podman, a daemonless container engine for 63 developing, managing, and running OCI Containers on your Linux System. 64 65 It is a drop-in replacement for the {command}`docker` command. 66 ''; 67 }; 68 69 dockerSocket.enable = mkOption { 70 type = types.bool; 71 default = false; 72 description = lib.mdDoc '' 73 Make the Podman socket available in place of the Docker socket, so 74 Docker tools can find the Podman socket. 75 76 Podman implements the Docker API. 77 78 Users must be in the `podman` group in order to connect. As 79 with Docker, members of this group can gain root access. 80 ''; 81 }; 82 83 dockerCompat = mkOption { 84 type = types.bool; 85 default = false; 86 description = lib.mdDoc '' 87 Create an alias mapping {command}`docker` to {command}`podman`. 88 ''; 89 }; 90 91 enableNvidia = mkOption { 92 type = types.bool; 93 default = false; 94 description = lib.mdDoc '' 95 Enable use of NVidia GPUs from within podman containers. 96 ''; 97 }; 98 99 extraPackages = mkOption { 100 type = with types; listOf package; 101 default = [ ]; 102 example = lib.literalExpression '' 103 [ 104 pkgs.gvisor 105 ] 106 ''; 107 description = lib.mdDoc '' 108 Extra packages to be installed in the Podman wrapper. 109 ''; 110 }; 111 112 package = lib.mkOption { 113 type = types.package; 114 default = podmanPackage; 115 internal = true; 116 description = lib.mdDoc '' 117 The final Podman package (including extra packages). 118 ''; 119 }; 120 121 defaultNetwork.extraPlugins = lib.mkOption { 122 type = types.listOf json.type; 123 default = [ ]; 124 description = lib.mdDoc '' 125 Extra CNI plugin configurations to add to podman's default network. 126 ''; 127 }; 128 129 }; 130 131 config = lib.mkIf cfg.enable (lib.mkMerge [ 132 { 133 environment.systemPackages = [ cfg.package ] 134 ++ lib.optional cfg.dockerCompat dockerCompat; 135 136 environment.etc."cni/net.d/87-podman-bridge.conflist".source = net-conflist; 137 138 virtualisation.containers = { 139 enable = true; # Enable common /etc/containers configuration 140 containersConf.settings = lib.optionalAttrs cfg.enableNvidia { 141 engine = { 142 conmon_env_vars = [ "PATH=${lib.makeBinPath [ pkgs.nvidia-podman ]}" ]; 143 runtimes.nvidia = [ "${pkgs.nvidia-podman}/bin/nvidia-container-runtime" ]; 144 }; 145 }; 146 }; 147 148 systemd.packages = [ cfg.package ]; 149 150 systemd.services.podman.serviceConfig = { 151 ExecStart = [ "" "${cfg.package}/bin/podman $LOGGING system service" ]; 152 }; 153 154 systemd.sockets.podman.wantedBy = [ "sockets.target" ]; 155 systemd.sockets.podman.socketConfig.SocketGroup = "podman"; 156 157 systemd.user.services.podman.serviceConfig = { 158 ExecStart = [ "" "${cfg.package}/bin/podman $LOGGING system service" ]; 159 }; 160 161 systemd.user.sockets.podman.wantedBy = [ "sockets.target" ]; 162 163 systemd.tmpfiles.packages = [ 164 # The /run/podman rule interferes with our podman group, so we remove 165 # it and let the systemd socket logic take care of it. 166 (pkgs.runCommand "podman-tmpfiles-nixos" { package = cfg.package; } '' 167 mkdir -p $out/lib/tmpfiles.d/ 168 grep -v 'D! /run/podman 0700 root root' \ 169 <$package/lib/tmpfiles.d/podman.conf \ 170 >$out/lib/tmpfiles.d/podman.conf 171 '') 172 ]; 173 174 systemd.tmpfiles.rules = 175 lib.optionals cfg.dockerSocket.enable [ 176 "L! /run/docker.sock - - - - /run/podman/podman.sock" 177 ]; 178 179 users.groups.podman = { }; 180 181 assertions = [ 182 { 183 assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable; 184 message = "Option dockerCompat conflicts with docker"; 185 } 186 { 187 assertion = cfg.dockerSocket.enable -> !config.virtualisation.docker.enable; 188 message = '' 189 The options virtualisation.podman.dockerSocket.enable and virtualisation.docker.enable conflict, because only one can serve the socket. 190 ''; 191 } 192 ]; 193 } 194 ]); 195}