8 cfg = config.services.devpi-server;
10 secretsFileName = "devpi-secret-file";
12 stateDirName = "devpi";
14 runtimeDir = "/run/${stateDirName}";
15 serverDir = "/var/lib/${stateDirName}";
18 options.services.devpi-server = {
19 enable = lib.mkEnableOption "Devpi Server";
21 package = lib.mkPackageOption pkgs "devpi-server" { };
23 primaryUrl = lib.mkOption {
25 description = "Url for the primary node. Required option for replica nodes.";
28 replica = lib.mkOption {
29 type = lib.types.bool;
32 Run node as a replica.
33 Requires the secretFile option and the primaryUrl to be enabled.
37 secretFile = lib.mkOption {
38 type = lib.types.nullOr lib.types.path;
41 Path to a shared secret file used for synchronization,
42 Required for all nodes in a replica/primary setup.
48 default = "localhost";
50 domain/ip address to listen on
55 type = lib.types.port;
57 description = "The port on which Devpi Server will listen.";
60 openFirewall = lib.mkEnableOption "opening the default ports in the firewall for Devpi Server";
63 config = lib.mkIf cfg.enable {
65 systemd.services.devpi-server = {
67 description = "devpi PyPI-compatible server";
68 documentation = [ "https://devpi.net/docs/devpi/devpi/stable/+d/index.html" ];
69 wants = [ "network-online.target" ];
70 wantedBy = [ "multi-user.target" ];
71 after = [ "network-online.target" ];
72 # Since at least devpi-server 6.10.0, devpi requires the secrets file to
73 # have 0600 permissions.
76 ${lib.optionalString (!isNull cfg.secretFile)
77 "install -Dm 0600 \${CREDENTIALS_DIRECTORY}/devpi-secret ${runtimeDir}/${secretsFileName}"
80 if [ -f ${serverDir}/.nodeinfo ]; then
81 # already initialized the package index, exit gracefully
84 ${cfg.package}/bin/devpi-init --serverdir ${serverDir} ''
85 + lib.optionalString cfg.replica "--role=replica --master-url=${cfg.primaryUrl}";
88 LoadCredential = lib.mkIf (! isNull cfg.secretFile) [
89 "devpi-secret:${cfg.secretFile}"
97 "--serverdir=${serverDir}"
99 "--port=${builtins.toString cfg.port}"
101 ++ lib.optionals (! isNull cfg.secretFile) [
102 "--secretfile=${runtimeDir}/${secretsFileName}"
108 "--master-url=${cfg.primaryUrl}"
114 "${cfg.package}/bin/devpi-server ${lib.concatStringsSep " " args}";
116 StateDirectory = stateDirName;
117 RuntimeDirectory = stateDirName;
118 PrivateDevices = true;
121 ProtectSystem = "strict";
125 networking.firewall = lib.mkIf cfg.openFirewall {
126 allowedTCPPorts = [ cfg.port ];
129 meta.maintainers = [ lib.maintainers.cafkafk ];