1 { config, lib, pkgs, ... }:
3 cfg = config.virtualisation.podman;
4 json = pkgs.formats.json { };
6 inherit (lib) mkOption types;
8 podmanPackage = pkgs.podman.override {
9 extraPackages = cfg.extraPackages
11 ++ [ "/run/wrappers" ]
12 ++ lib.optional (config.boot.supportedFilesystems.zfs or false) config.boot.zfs.package;
13 extraRuntimes = [ pkgs.runc ]
14 ++ lib.optionals (config.virtualisation.containers.containersConf.settings.network.default_rootless_network_cmd or "" == "slirp4netns") (with pkgs; [
19 # Provides a fake "docker" binary mapping to podman
20 dockerCompat = pkgs.runCommand "${podmanPackage.pname}-docker-compat-${podmanPackage.version}"
22 outputs = [ "out" "man" ];
23 inherit (podmanPackage) meta;
24 preferLocalBuild = true;
27 ln -s ${podmanPackage}/bin/podman $out/bin/docker
29 mkdir -p $man/share/man/man1
30 for f in ${podmanPackage.man}/share/man/man1/*; do
31 basename=$(basename $f | sed s/podman/docker/g)
32 ln -s $f $man/share/man/man1/$basename
39 (lib.mkRemovedOptionModule [ "virtualisation" "podman" "defaultNetwork" "dnsname" ]
40 "Use virtualisation.podman.defaultNetwork.settings.dns_enabled instead.")
41 (lib.mkRemovedOptionModule [ "virtualisation" "podman" "defaultNetwork" "extraPlugins" ]
42 "Netavark isn't compatible with CNI plugins.")
47 maintainers = lib.teams.podman.members;
50 options.virtualisation.podman = {
57 This option enables Podman, a daemonless container engine for
58 developing, managing, and running OCI Containers on your Linux System.
60 It is a drop-in replacement for the {command}`docker` command.
64 dockerSocket.enable = mkOption {
68 Make the Podman socket available in place of the Docker socket, so
69 Docker tools can find the Podman socket.
71 Podman implements the Docker API.
73 Users must be in the `podman` group in order to connect. As
74 with Docker, members of this group can gain root access.
78 dockerCompat = mkOption {
82 Create an alias mapping {command}`docker` to {command}`podman`.
86 enableNvidia = mkOption {
90 **Deprecated**, please use hardware.nvidia-container-toolkit.enable instead.
92 Enable use of Nvidia GPUs from within podman containers.
96 extraPackages = mkOption {
97 type = with types; listOf package;
99 example = lib.literalExpression ''
105 Extra packages to be installed in the Podman wrapper.
114 Whether to periodically prune Podman resources. If enabled, a
115 systemd timer will run `podman system prune -f`
116 as specified by the `dates` option.
121 type = types.listOf types.str;
123 example = [ "--all" ];
125 Any additional flags passed to {command}`podman system prune`.
133 Specification (in the format described by
134 {manpage}`systemd.time(7)`) of the time at
135 which the prune will occur.
140 package = lib.mkOption {
141 type = types.package;
142 default = podmanPackage;
145 The final Podman package (including extra packages).
149 defaultNetwork.settings = lib.mkOption {
152 example = lib.literalExpression "{ dns_enabled = true; }";
154 Settings for podman's default network.
165 id = "0000000000000000000000000000000000000000000000000000000000000000";
167 ipam_options = { driver = "host-local"; };
168 ipv6_enabled = false;
170 network_interface = "podman0";
171 subnets = [{ gateway = "10.88.0.1"; subnet = "10.88.0.0/16"; }];
172 } // cfg.defaultNetwork.settings);
173 inherit (networkConfig) dns_enabled network_interface;
175 lib.mkIf cfg.enable {
176 warnings = lib.optionals cfg.enableNvidia [
178 You have set virtualisation.podman.enableNvidia. This option is deprecated, please set hardware.nvidia-container-toolkit.enable instead.
182 environment.systemPackages = [ cfg.package ]
183 ++ lib.optional cfg.dockerCompat dockerCompat;
185 # https://github.com/containers/podman/blob/097cc6eb6dd8e598c0e8676d21267b4edb11e144/docs/tutorials/basic_networking.md#default-network
186 environment.etc."containers/networks/podman.json" = lib.mkIf (cfg.defaultNetwork.settings != { }) {
187 source = json.generate "podman.json" networkConfig;
190 # containers cannot reach aardvark-dns otherwise
191 networking.firewall.interfaces.${network_interface}.allowedUDPPorts = lib.mkIf dns_enabled [ 53 ];
193 virtualisation.containers = {
194 enable = true; # Enable common /etc/containers configuration
195 containersConf.settings = {
196 network.network_backend = "netavark";
200 systemd.packages = [ cfg.package ];
202 systemd.services.podman-prune = {
203 description = "Prune podman resources";
205 restartIfChanged = false;
206 unitConfig.X-StopOnRemoval = false;
208 serviceConfig.Type = "oneshot";
211 ${cfg.package}/bin/podman system prune -f ${toString cfg.autoPrune.flags}
214 startAt = lib.optional cfg.autoPrune.enable cfg.autoPrune.dates;
215 after = [ "podman.service" ];
216 requires = [ "podman.service" ];
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,
225 systemd.sockets.podman.socketConfig.Symlinks =
226 lib.mkIf cfg.dockerSocket.enable [ "/run/docker.sock" ];
228 systemd.user.services.podman.environment = config.networking.proxy.envVars;
229 systemd.user.sockets.podman.wantedBy = [ "sockets.target" ];
231 systemd.timers.podman-prune.timerConfig = lib.mkIf cfg.autoPrune.enable {
233 RandomizedDelaySec = 1800;
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" {
240 package = cfg.package;
241 preferLocalBuild = true;
243 mkdir -p $out/lib/tmpfiles.d/
244 grep -v 'D! /run/podman 0700 root root' \
245 <$package/lib/tmpfiles.d/podman.conf \
246 >$out/lib/tmpfiles.d/podman.conf
250 users.groups.podman = { };
254 assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable;
255 message = "Option dockerCompat conflicts with docker";
258 assertion = cfg.dockerSocket.enable -> !config.virtualisation.docker.enable;
260 The options virtualisation.podman.dockerSocket.enable and virtualisation.docker.enable conflict, because only one can serve the socket.