at 24.11-pre 3.5 kB view raw
1{ 2 pkgs, 3 lib, 4 config, 5 ... 6}: 7with lib; 8let 9 cfg = config.services.devpi-server; 10 11 secretsFileName = "devpi-secret-file"; 12 13 stateDirName = "devpi"; 14 15 runtimeDir = "/run/${stateDirName}"; 16 serverDir = "/var/lib/${stateDirName}"; 17in 18{ 19 options.services.devpi-server = { 20 enable = mkEnableOption "Devpi Server"; 21 22 package = mkPackageOption pkgs "devpi-server" { }; 23 24 primaryUrl = mkOption { 25 type = types.str; 26 description = "Url for the primary node. Required option for replica nodes."; 27 }; 28 29 replica = mkOption { 30 type = types.bool; 31 default = false; 32 description = '' 33 Run node as a replica. 34 Requires the secretFile option and the primaryUrl to be enabled. 35 ''; 36 }; 37 38 secretFile = mkOption { 39 type = types.nullOr types.path; 40 default = null; 41 description = '' 42 Path to a shared secret file used for synchronization, 43 Required for all nodes in a replica/primary setup. 44 ''; 45 }; 46 47 host = mkOption { 48 type = types.str; 49 default = "localhost"; 50 description = '' 51 domain/ip address to listen on 52 ''; 53 }; 54 55 port = mkOption { 56 type = types.port; 57 default = 3141; 58 description = "The port on which Devpi Server will listen."; 59 }; 60 61 openFirewall = mkEnableOption "opening the default ports in the firewall for Devpi Server"; 62 }; 63 64 config = mkIf cfg.enable { 65 66 systemd.services.devpi-server = { 67 enable = true; 68 description = "devpi PyPI-compatible server"; 69 documentation = [ "https://devpi.net/docs/devpi/devpi/stable/+d/index.html" ]; 70 wants = [ "network-online.target" ]; 71 wantedBy = [ "multi-user.target" ]; 72 after = [ "network-online.target" ]; 73 # Since at least devpi-server 6.10.0, devpi requires the secrets file to 74 # have 0600 permissions. 75 preStart = 76 '' 77 cp ${cfg.secretFile} ${runtimeDir}/${secretsFileName} 78 chmod 0600 ${runtimeDir}/*${secretsFileName} 79 80 if [ -f ${serverDir}/.nodeinfo ]; then 81 # already initialized the package index, exit gracefully 82 exit 0 83 fi 84 ${cfg.package}/bin/devpi-init --serverdir ${serverDir} '' 85 + strings.optionalString cfg.replica "--role=replica --master-url=${cfg.primaryUrl}"; 86 87 serviceConfig = { 88 Restart = "always"; 89 ExecStart = 90 let 91 args = 92 [ 93 "--request-timeout=5" 94 "--serverdir=${serverDir}" 95 "--host=${cfg.host}" 96 "--port=${builtins.toString cfg.port}" 97 ] 98 ++ lib.optionals (! isNull cfg.secretFile) [ 99 "--secretfile=${runtimeDir}/${secretsFileName}" 100 ] 101 ++ ( 102 if cfg.replica then 103 [ 104 "--role=replica" 105 "--master-url=${cfg.primaryUrl}" 106 ] 107 else 108 [ "--role=master" ] 109 ); 110 in 111 "${cfg.package}/bin/devpi-server ${concatStringsSep " " args}"; 112 DynamicUser = true; 113 StateDirectory = stateDirName; 114 RuntimeDirectory = stateDirName; 115 PrivateDevices = true; 116 PrivateTmp = true; 117 ProtectHome = true; 118 ProtectSystem = "strict"; 119 }; 120 }; 121 122 networking.firewall = mkIf cfg.openFirewall { 123 allowedTCPPorts = [ cfg.port ]; 124 }; 125 126 meta.maintainers = [ cafkafk ]; 127 }; 128}