at 25.11-pre 4.7 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.services.unit; 12 13 configFile = pkgs.writeText "unit.json" cfg.config; 14 15in 16{ 17 options = { 18 services.unit = { 19 enable = mkEnableOption "Unit App Server"; 20 package = mkPackageOption pkgs "unit" { }; 21 user = mkOption { 22 type = types.str; 23 default = "unit"; 24 description = "User account under which unit runs."; 25 }; 26 group = mkOption { 27 type = types.str; 28 default = "unit"; 29 description = "Group account under which unit runs."; 30 }; 31 stateDir = mkOption { 32 type = types.path; 33 default = "/var/spool/unit"; 34 description = "Unit data directory."; 35 }; 36 logDir = mkOption { 37 type = types.path; 38 default = "/var/log/unit"; 39 description = "Unit log directory."; 40 }; 41 config = mkOption { 42 type = types.str; 43 default = '' 44 { 45 "listeners": {}, 46 "applications": {} 47 } 48 ''; 49 example = '' 50 { 51 "listeners": { 52 "*:8300": { 53 "application": "example-php-72" 54 } 55 }, 56 "applications": { 57 "example-php-72": { 58 "type": "php 7.2", 59 "processes": 4, 60 "user": "nginx", 61 "group": "nginx", 62 "root": "/var/www", 63 "index": "index.php", 64 "options": { 65 "file": "/etc/php.d/default.ini", 66 "admin": { 67 "max_execution_time": "30", 68 "max_input_time": "30", 69 "display_errors": "off", 70 "display_startup_errors": "off", 71 "open_basedir": "/dev/urandom:/proc/cpuinfo:/proc/meminfo:/etc/ssl/certs:/var/www", 72 "disable_functions": "exec,passthru,shell_exec,system" 73 } 74 } 75 } 76 } 77 } 78 ''; 79 description = "Unit configuration in JSON format. More details here https://unit.nginx.org/configuration"; 80 }; 81 }; 82 }; 83 84 config = mkIf cfg.enable { 85 86 environment.systemPackages = [ cfg.package ]; 87 88 systemd.tmpfiles.rules = [ 89 "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" 90 "d '${cfg.logDir}' 0750 ${cfg.user} ${cfg.group} - -" 91 ]; 92 93 systemd.services.unit = { 94 description = "Unit App Server"; 95 after = [ "network.target" ]; 96 wantedBy = [ "multi-user.target" ]; 97 preStart = '' 98 [ ! -e '${cfg.stateDir}/conf.json' ] || rm -f '${cfg.stateDir}/conf.json' 99 ''; 100 postStart = '' 101 ${pkgs.curl}/bin/curl -X PUT --data-binary '@${configFile}' --unix-socket '/run/unit/control.unit.sock' 'http://localhost/config' 102 ''; 103 serviceConfig = { 104 Type = "forking"; 105 PIDFile = "/run/unit/unit.pid"; 106 ExecStart = '' 107 ${cfg.package}/bin/unitd --control 'unix:/run/unit/control.unit.sock' --pid '/run/unit/unit.pid' \ 108 --log '${cfg.logDir}/unit.log' --statedir '${cfg.stateDir}' --tmpdir '/tmp' \ 109 --user ${cfg.user} --group ${cfg.group} 110 ''; 111 ExecStop = '' 112 ${pkgs.curl}/bin/curl -X DELETE --unix-socket '/run/unit/control.unit.sock' 'http://localhost/config' 113 ''; 114 # Runtime directory and mode 115 RuntimeDirectory = "unit"; 116 RuntimeDirectoryMode = "0750"; 117 # Access write directories 118 ReadWritePaths = [ 119 cfg.stateDir 120 cfg.logDir 121 ]; 122 # Security 123 NoNewPrivileges = true; 124 # Sandboxing 125 ProtectSystem = "strict"; 126 ProtectHome = true; 127 PrivateTmp = true; 128 PrivateDevices = true; 129 PrivateUsers = false; 130 ProtectHostname = true; 131 ProtectClock = true; 132 ProtectKernelTunables = true; 133 ProtectKernelModules = true; 134 ProtectKernelLogs = true; 135 ProtectControlGroups = true; 136 RestrictAddressFamilies = [ 137 "AF_UNIX" 138 "AF_INET" 139 "AF_INET6" 140 ]; 141 LockPersonality = true; 142 MemoryDenyWriteExecute = true; 143 RestrictRealtime = true; 144 RestrictSUIDSGID = true; 145 PrivateMounts = true; 146 # System Call Filtering 147 SystemCallArchitectures = "native"; 148 }; 149 }; 150 151 users.users = optionalAttrs (cfg.user == "unit") { 152 unit = { 153 group = cfg.group; 154 isSystemUser = true; 155 }; 156 }; 157 158 users.groups = optionalAttrs (cfg.group == "unit") { 159 unit = { }; 160 }; 161 162 }; 163}