{
  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;
  };
}
