1 { config, lib, pkgs, ... }:
6 cfg = config.services.unit;
8 configFile = pkgs.writeText "unit.json" cfg.config;
13 enable = mkEnableOption "Unit App Server";
14 package = mkPackageOption pkgs "unit" { };
18 description = "User account under which unit runs.";
23 description = "Group account under which unit runs.";
27 default = "/var/spool/unit";
28 description = "Unit data directory.";
32 default = "/var/log/unit";
33 description = "Unit log directory.";
47 "application": "example-php-72"
59 "file": "/etc/php.d/default.ini",
61 "max_execution_time": "30",
62 "max_input_time": "30",
63 "display_errors": "off",
64 "display_startup_errors": "off",
65 "open_basedir": "/dev/urandom:/proc/cpuinfo:/proc/meminfo:/etc/ssl/certs:/var/www",
66 "disable_functions": "exec,passthru,shell_exec,system"
73 description = "Unit configuration in JSON format. More details here https://unit.nginx.org/configuration";
78 config = mkIf cfg.enable {
80 environment.systemPackages = [ cfg.package ];
82 systemd.tmpfiles.rules = [
83 "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -"
84 "d '${cfg.logDir}' 0750 ${cfg.user} ${cfg.group} - -"
87 systemd.services.unit = {
88 description = "Unit App Server";
89 after = [ "network.target" ];
90 wantedBy = [ "multi-user.target" ];
92 [ ! -e '${cfg.stateDir}/conf.json' ] || rm -f '${cfg.stateDir}/conf.json'
95 ${pkgs.curl}/bin/curl -X PUT --data-binary '@${configFile}' --unix-socket '/run/unit/control.unit.sock' 'http://localhost/config'
99 PIDFile = "/run/unit/unit.pid";
101 ${cfg.package}/bin/unitd --control 'unix:/run/unit/control.unit.sock' --pid '/run/unit/unit.pid' \
102 --log '${cfg.logDir}/unit.log' --statedir '${cfg.stateDir}' --tmpdir '/tmp' \
103 --user ${cfg.user} --group ${cfg.group}
106 ${pkgs.curl}/bin/curl -X DELETE --unix-socket '/run/unit/control.unit.sock' 'http://localhost/config'
108 # Runtime directory and mode
109 RuntimeDirectory = "unit";
110 RuntimeDirectoryMode = "0750";
111 # Access write directories
112 ReadWritePaths = [ cfg.stateDir cfg.logDir ];
114 NoNewPrivileges = true;
116 ProtectSystem = "strict";
119 PrivateDevices = true;
120 PrivateUsers = false;
121 ProtectHostname = true;
123 ProtectKernelTunables = true;
124 ProtectKernelModules = true;
125 ProtectKernelLogs = true;
126 ProtectControlGroups = true;
127 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
128 LockPersonality = true;
129 MemoryDenyWriteExecute = true;
130 RestrictRealtime = true;
131 RestrictSUIDSGID = true;
132 PrivateMounts = true;
133 # System Call Filtering
134 SystemCallArchitectures = "native";
138 users.users = optionalAttrs (cfg.user == "unit") {
145 users.groups = optionalAttrs (cfg.group == "unit") {