{ lib, pkgs, config, ... }: let inherit (lib) mkOption types; mkRunCommand = name: { image, command ? "", environment ? {}, ports ? [], volumes ? [], envFile ? null, ... }: '' ${pkgs.podman}/bin/podman run \ ${toString (builtins.attrValues (builtins.mapAttrs (name: value: "-e ${name}='${value}'") environment))} \ ${toString (builtins.map (mapping: "-p ${mapping}") ports)} \ ${toString (builtins.map (mapping: "-v ${mapping}") volumes)} \ ${ if builtins.isNull envFile then "" else "--env-file ${toString envFile}" } \ --detach --replace \ --name ${name} \ ${image} ${command} ''; opts = { config, name, ... }: { options = { image = mkOption { type = types.str; }; command = mkOption { type = types.str; default = ""; }; environment = mkOption { type = types.attrsOf types.str; default = {}; }; ports = mkOption { type = types.listOf types.str; default = []; }; volumes = mkOption { type = types.listOf types.str; default = []; }; envFile = mkOption { type = types.nullOr types.path; default = null; }; }; }; mkService = name: config: { enable = true; wants = ["network-online.target"]; after = ["network-online.target"]; wantedBy = ["default.target"]; unitConfig = { RequiresMountsFor = "/run/containers/storage"; }; serviceConfig = { Environment = "PODMAN_SYSTEMD_UNIT=%n"; Restart = "on-failure"; TimeoutStopSec = 70; ExecStart = mkRunCommand name config; ExecStop = "${pkgs.podman}/bin/podman stop -t 10 ${name}"; ExecStopPost = "${pkgs.podman}/bin/podman stop -t 10 ${name}"; Type = "forking"; }; }; in { options.podman = mkOption { type = types.attrsOf (types.submodule opts); default = {}; }; config = { systemd.services = lib.mapAttrs mkService config.podman; }; }