{
  pkgs,
  lib,
  config,
  ...
}:
let
  cfg = config.services.devpi-server;

  secretsFileName = "devpi-secret-file";

  stateDirName = "devpi";

  runtimeDir = "/run/${stateDirName}";
  serverDir = "/var/lib/${stateDirName}";
in
{
  options.services.devpi-server = {
    enable = lib.mkEnableOption "Devpi Server";

    package = lib.mkPackageOption pkgs "devpi-server" { };

    primaryUrl = lib.mkOption {
      type = lib.types.str;
      description = "Url for the primary node. Required option for replica nodes.";
    };

    replica = lib.mkOption {
      type = lib.types.bool;
      default = false;
      description = ''
        Run node as a replica.
        Requires the secretFile option and the primaryUrl to be enabled.
      '';
    };

    secretFile = lib.mkOption {
      type = lib.types.nullOr lib.types.path;
      default = null;
      description = ''
        Path to a shared secret file used for synchronization,
        Required for all nodes in a replica/primary setup.
      '';
    };

    host = lib.mkOption {
      type = lib.types.str;
      default = "localhost";
      description = ''
        domain/ip address to listen on
      '';
    };

    port = lib.mkOption {
      type = lib.types.port;
      default = 3141;
      description = "The port on which Devpi Server will listen.";
    };

    openFirewall = lib.mkEnableOption "opening the default ports in the firewall for Devpi Server";
  };

  config = lib.mkIf cfg.enable {

    systemd.services.devpi-server = {
      enable = true;
      description = "devpi PyPI-compatible server";
      documentation = [ "https://devpi.net/docs/devpi/devpi/stable/+d/index.html" ];
      wants = [ "network-online.target" ];
      wantedBy = [ "multi-user.target" ];
      after = [ "network-online.target" ];
      # Since at least devpi-server 6.10.0, devpi requires the secrets file to
      # have 0600 permissions.
      preStart =
        ''
          ${lib.optionalString (
            !isNull cfg.secretFile
          ) "install -Dm 0600 \${CREDENTIALS_DIRECTORY}/devpi-secret ${runtimeDir}/${secretsFileName}"}

          if [ -f ${serverDir}/.nodeinfo ]; then
            # already initialized the package index, exit gracefully
            exit 0
          fi
          ${cfg.package}/bin/devpi-init --serverdir ${serverDir} ''
        + lib.optionalString cfg.replica "--role=replica --master-url=${cfg.primaryUrl}";

      serviceConfig = {
        LoadCredential = lib.mkIf (!isNull cfg.secretFile) [
          "devpi-secret:${cfg.secretFile}"
        ];
        Restart = "always";
        ExecStart =
          let
            args =
              [
                "--request-timeout=5"
                "--serverdir=${serverDir}"
                "--host=${cfg.host}"
                "--port=${builtins.toString cfg.port}"
              ]
              ++ lib.optionals (!isNull cfg.secretFile) [
                "--secretfile=${runtimeDir}/${secretsFileName}"
              ]
              ++ (
                if cfg.replica then
                  [
                    "--role=replica"
                    "--master-url=${cfg.primaryUrl}"
                  ]
                else
                  [ "--role=master" ]
              );
          in
          "${cfg.package}/bin/devpi-server ${lib.concatStringsSep " " args}";
        DynamicUser = true;
        StateDirectory = stateDirName;
        RuntimeDirectory = stateDirName;
        PrivateDevices = true;
        PrivateTmp = true;
        ProtectHome = true;
        ProtectSystem = "strict";
      };
    };

    networking.firewall = lib.mkIf cfg.openFirewall {
      allowedTCPPorts = [ cfg.port ];
    };

    meta.maintainers = [ lib.maintainers.cafkafk ];
  };
}
