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