diff options
author | Christina Rust <christina@cafkafk.com> | 2024-05-13 13:14:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-13 13:14:51 +0200 |
commit | 31a5a35b7e8515b5941892e1e39a5e8f108f6521 (patch) | |
tree | 321919c60f878809e2a3e8fba2c09218817b9645 /nixos | |
parent | c8b2579f1fe502a7cff41fbc55e8958f27650287 (diff) | |
parent | 52e0ad744d55f92d0127173d9859aca2d7609944 (diff) |
Merge pull request #305286 from cafkafk/devpi-server-init
nixos/devpi-server: init
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/misc/devpi-server.nix | 128 | ||||
-rw-r--r-- | nixos/tests/all-tests.nix | 1 | ||||
-rw-r--r-- | nixos/tests/devpi-server.nix | 35 |
4 files changed, 165 insertions, 0 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3cbb4617517aa..2a308af6ed2dd 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -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 diff --git a/nixos/modules/services/misc/devpi-server.nix b/nixos/modules/services/misc/devpi-server.nix new file mode 100644 index 0000000000000..0234db4bc2c5b --- /dev/null +++ b/nixos/modules/services/misc/devpi-server.nix @@ -0,0 +1,128 @@ +{ + 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 ]; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index a8f8c470e6e29..cbddae381399f 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -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 {}; diff --git a/nixos/tests/devpi-server.nix b/nixos/tests/devpi-server.nix new file mode 100644 index 0000000000000..2a16d49724dbc --- /dev/null +++ b/nixos/tests/devpi-server.nix @@ -0,0 +1,35 @@ +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}") + ''; +}) |