Unverified Commit 31a5a35b authored by Christina Sørensen's avatar Christina Sørensen Committed by GitHub
Browse files

Merge pull request #305286 from cafkafk/devpi-server-init

nixos/devpi-server: init
parents c8b2579f 52e0ad74
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -699,6 +699,7 @@
  ./services/misc/cpuminer-cryptonight.nix
  ./services/misc/db-rest.nix
  ./services/misc/devmon.nix
  ./services/misc/devpi-server.nix
  ./services/misc/dictd.nix
  ./services/misc/disnix.nix
  ./services/misc/docker-registry.nix
+128 −0
Original line number Diff line number Diff line
{
  pkgs,
  lib,
  config,
  ...
}:
with lib;
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 = mkEnableOption "Devpi Server";

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

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

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

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

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

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

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

  config = 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 =
        ''
          cp ${cfg.secretFile} ${runtimeDir}/${secretsFileName}
          chmod 0600 ${runtimeDir}/*${secretsFileName}

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

      serviceConfig = {
        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 ${concatStringsSep " " args}";
        DynamicUser = true;
        StateDirectory = stateDirName;
        RuntimeDirectory = stateDirName;
        PrivateDevices = true;
        PrivateTmp = true;
        ProtectHome = true;
        ProtectSystem = "strict";
      };
    };

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

    meta.maintainers = [ cafkafk ];
  };
}
+1 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ in {
  deepin = handleTest ./deepin.nix {};
  deluge = handleTest ./deluge.nix {};
  dendrite = handleTest ./matrix/dendrite.nix {};
  devpi-server = handleTest ./devpi-server.nix {};
  dex-oidc = handleTest ./dex-oidc.nix {};
  dhparams = handleTest ./dhparams.nix {};
  disable-installer-tools = handleTest ./disable-installer-tools.nix {};
+35 −0
Original line number Diff line number Diff line
import ./make-test-python.nix ({pkgs, ...}: let
  server-port = 3141;
in {
  name = "devpi-server";
  meta = with pkgs.lib.maintainers; {
    maintainers = [cafkafk];
  };

  nodes = {
    devpi = {...}: {
      services.devpi-server = {
        enable = true;
        host = "0.0.0.0";
        port = server-port;
        openFirewall = true;
        secretFile = pkgs.writeText "devpi-secret" "v263P+V3YGDYUyfYL/RBURw+tCPMDw94R/iCuBNJrDhaYrZYjpA6XPFVDDH8ViN20j77y2PHoMM/U0opNkVQ2g==";
      };
    };

    client1 = {...}: {
      environment.systemPackages = with pkgs; [
        devpi-client
        jq
      ];
    };
  };

  testScript = ''
    start_all()
    devpi.wait_for_unit("devpi-server.service")
    devpi.wait_for_open_port(${builtins.toString server-port})

    client1.succeed("devpi getjson http://devpi:${builtins.toString server-port}")
  '';
})
+6 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
, webtest
, testers
, devpi-server
, nixosTests
}:


@@ -108,9 +109,12 @@ buildPythonApplication rec {
    "devpi_server"
  ];

  passthru.tests.version = testers.testVersion {
  passthru.tests = {
    devpi-server = nixosTests.devpi-server;
    version = testers.testVersion {
      package = devpi-server;
    };
  };

  meta = with lib;{
    homepage = "http://doc.devpi.net";