at 25.11-pre 9.2 kB view raw
1{ 2 config, 3 lib, 4 utils, 5 pkgs, 6 ... 7}: 8let 9 cfg = config.virtualisation.podman; 10 json = pkgs.formats.json { }; 11 12 inherit (lib) mkOption types; 13 14 # Provides a fake "docker" binary mapping to podman 15 dockerCompat = 16 pkgs.runCommand "${cfg.package.pname}-docker-compat-${cfg.package.version}" 17 { 18 outputs = [ 19 "out" 20 "man" 21 ]; 22 inherit (cfg.package) meta; 23 preferLocalBuild = true; 24 } 25 '' 26 mkdir -p $out/bin 27 ln -s ${cfg.package}/bin/podman $out/bin/docker 28 29 mkdir -p $man/share/man/man1 30 for f in ${cfg.package.man}/share/man/man1/*; do 31 basename=$(basename $f | sed s/podman/docker/g) 32 ln -s $f $man/share/man/man1/$basename 33 done 34 ''; 35 36in 37{ 38 imports = [ 39 (lib.mkRemovedOptionModule [ 40 "virtualisation" 41 "podman" 42 "defaultNetwork" 43 "dnsname" 44 ] "Use virtualisation.podman.defaultNetwork.settings.dns_enabled instead.") 45 (lib.mkRemovedOptionModule [ 46 "virtualisation" 47 "podman" 48 "defaultNetwork" 49 "extraPlugins" 50 ] "Netavark isn't compatible with CNI plugins.") 51 ./network-socket.nix 52 ]; 53 54 meta = { 55 maintainers = lib.teams.podman.members; 56 }; 57 58 options.virtualisation.podman = { 59 60 enable = mkOption { 61 type = types.bool; 62 default = false; 63 description = '' 64 This option enables Podman, a daemonless container engine for 65 developing, managing, and running OCI Containers on your Linux System. 66 67 It is a drop-in replacement for the {command}`docker` command. 68 ''; 69 }; 70 71 dockerSocket.enable = mkOption { 72 type = types.bool; 73 default = false; 74 description = '' 75 Make the Podman socket available in place of the Docker socket, so 76 Docker tools can find the Podman socket. 77 78 Podman implements the Docker API. 79 80 Users must be in the `podman` group in order to connect. As 81 with Docker, members of this group can gain root access. 82 ''; 83 }; 84 85 dockerCompat = mkOption { 86 type = types.bool; 87 default = false; 88 description = '' 89 Create an alias mapping {command}`docker` to {command}`podman`. 90 ''; 91 }; 92 93 enableNvidia = mkOption { 94 type = types.bool; 95 default = false; 96 description = '' 97 **Deprecated**, please use hardware.nvidia-container-toolkit.enable instead. 98 99 Enable use of Nvidia GPUs from within podman containers. 100 ''; 101 }; 102 103 extraPackages = mkOption { 104 type = with types; listOf package; 105 default = [ ]; 106 example = lib.literalExpression '' 107 [ 108 pkgs.gvisor 109 ] 110 ''; 111 description = '' 112 Extra packages to be installed in the Podman wrapper. 113 ''; 114 }; 115 116 autoPrune = { 117 enable = mkOption { 118 type = types.bool; 119 default = false; 120 description = '' 121 Whether to periodically prune Podman resources. If enabled, a 122 systemd timer will run `podman system prune -f` 123 as specified by the `dates` option. 124 ''; 125 }; 126 127 flags = mkOption { 128 type = types.listOf types.str; 129 default = [ ]; 130 example = [ "--all" ]; 131 description = '' 132 Any additional flags passed to {command}`podman system prune`. 133 ''; 134 }; 135 136 dates = mkOption { 137 default = "weekly"; 138 type = types.str; 139 description = '' 140 Specification (in the format described by 141 {manpage}`systemd.time(7)`) of the time at 142 which the prune will occur. 143 ''; 144 }; 145 }; 146 147 package = 148 (lib.mkPackageOption pkgs "podman" { 149 extraDescription = '' 150 This package will automatically include extra packages and runtimes. 151 ''; 152 }) 153 // { 154 apply = 155 pkg: 156 pkg.override { 157 extraPackages = 158 cfg.extraPackages 159 ++ [ 160 "/run/wrappers" # setuid shadow 161 config.systemd.package # To allow systemd-based container healthchecks 162 ] 163 ++ lib.optional (config.boot.supportedFilesystems.zfs or false) config.boot.zfs.package; 164 extraRuntimes = 165 [ pkgs.runc ] 166 ++ lib.optionals 167 ( 168 config.virtualisation.containers.containersConf.settings.network.default_rootless_network_cmd or "" 169 == "slirp4netns" 170 ) 171 ( 172 with pkgs; 173 [ 174 slirp4netns 175 ] 176 ); 177 }; 178 }; 179 180 defaultNetwork.settings = lib.mkOption { 181 type = json.type; 182 default = { }; 183 example = lib.literalExpression "{ dns_enabled = true; }"; 184 description = '' 185 Settings for podman's default network. 186 ''; 187 }; 188 189 }; 190 191 config = 192 let 193 networkConfig = ( 194 { 195 dns_enabled = false; 196 driver = "bridge"; 197 id = "0000000000000000000000000000000000000000000000000000000000000000"; 198 internal = false; 199 ipam_options = { 200 driver = "host-local"; 201 }; 202 ipv6_enabled = false; 203 name = "podman"; 204 network_interface = "podman0"; 205 subnets = [ 206 { 207 gateway = "10.88.0.1"; 208 subnet = "10.88.0.0/16"; 209 } 210 ]; 211 } 212 // cfg.defaultNetwork.settings 213 ); 214 inherit (networkConfig) dns_enabled network_interface; 215 in 216 lib.mkIf cfg.enable { 217 warnings = lib.optionals cfg.enableNvidia [ 218 '' 219 You have set virtualisation.podman.enableNvidia. This option is deprecated, please set hardware.nvidia-container-toolkit.enable instead. 220 '' 221 ]; 222 223 environment.systemPackages = [ cfg.package ] ++ lib.optional cfg.dockerCompat dockerCompat; 224 225 # https://github.com/containers/podman/blob/097cc6eb6dd8e598c0e8676d21267b4edb11e144/docs/tutorials/basic_networking.md#default-network 226 environment.etc."containers/networks/podman.json" = lib.mkIf (cfg.defaultNetwork.settings != { }) { 227 source = json.generate "podman.json" networkConfig; 228 }; 229 230 # containers cannot reach aardvark-dns otherwise 231 networking.firewall.interfaces.${network_interface}.allowedUDPPorts = lib.mkIf dns_enabled [ 53 ]; 232 233 virtualisation.containers = { 234 enable = true; # Enable common /etc/containers configuration 235 containersConf.settings = { 236 network.network_backend = "netavark"; 237 }; 238 }; 239 240 systemd.packages = [ cfg.package ]; 241 242 systemd.services.podman-prune = { 243 description = "Prune podman resources"; 244 245 restartIfChanged = false; 246 unitConfig.X-StopOnRemoval = false; 247 248 serviceConfig = { 249 Type = "oneshot"; 250 ExecStart = utils.escapeSystemdExecArgs ( 251 [ 252 (lib.getExe cfg.package) 253 "system" 254 "prune" 255 "-f" 256 ] 257 ++ cfg.autoPrune.flags 258 ); 259 }; 260 261 startAt = lib.optional cfg.autoPrune.enable cfg.autoPrune.dates; 262 after = [ "podman.service" ]; 263 requires = [ "podman.service" ]; 264 }; 265 266 systemd.services.podman.environment = config.networking.proxy.envVars; 267 systemd.sockets.podman.wantedBy = [ "sockets.target" ]; 268 systemd.sockets.podman.socketConfig.SocketGroup = "podman"; 269 # Podman does not support multiple sockets, as of podman 5.0.2, so we use 270 # a symlink. Unfortunately this does not let us use an alternate group, 271 # such as `docker`. 272 systemd.sockets.podman.socketConfig.Symlinks = lib.mkIf cfg.dockerSocket.enable [ 273 "/run/docker.sock" 274 ]; 275 276 systemd.user.services.podman.environment = config.networking.proxy.envVars; 277 systemd.user.sockets.podman.wantedBy = [ "sockets.target" ]; 278 279 systemd.timers.podman-prune.timerConfig = lib.mkIf cfg.autoPrune.enable { 280 Persistent = true; 281 RandomizedDelaySec = 1800; 282 }; 283 284 systemd.tmpfiles.packages = [ 285 # The /run/podman rule interferes with our podman group, so we remove 286 # it and let the systemd socket logic take care of it. 287 (pkgs.runCommand "podman-tmpfiles-nixos" 288 { 289 package = cfg.package; 290 preferLocalBuild = true; 291 } 292 '' 293 mkdir -p $out/lib/tmpfiles.d/ 294 grep -v 'D! /run/podman 0700 root root' \ 295 <$package/lib/tmpfiles.d/podman.conf \ 296 >$out/lib/tmpfiles.d/podman.conf 297 '' 298 ) 299 ]; 300 301 users.groups.podman = { }; 302 303 assertions = [ 304 { 305 assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable; 306 message = "Option dockerCompat conflicts with docker"; 307 } 308 { 309 assertion = cfg.dockerSocket.enable -> !config.virtualisation.docker.enable; 310 message = '' 311 The options virtualisation.podman.dockerSocket.enable and virtualisation.docker.enable conflict, because only one can serve the socket. 312 ''; 313 } 314 ]; 315 }; 316}