vuls: init at 0.27.0 (#348530)
[NixPkgs.git] / nixos / modules / services / web-apps / galene.nix
blob32854e757ac373a9a51820b1d8d093b21dffc7f4
1 { config, lib, options, pkgs, ... }:
3 with lib;
4 let
5   cfg = config.services.galene;
6   opt = options.services.galene;
7   defaultstateDir = "/var/lib/galene";
8   defaultrecordingsDir = "${cfg.stateDir}/recordings";
9   defaultgroupsDir = "${cfg.stateDir}/groups";
10   defaultdataDir = "${cfg.stateDir}/data";
13   options = {
14     services.galene = {
15       enable = mkEnableOption "Galene Service";
17       stateDir = mkOption {
18         default = defaultstateDir;
19         type = types.str;
20         description = ''
21           The directory where Galene stores its internal state. If left as the default
22           value this directory will automatically be created before the Galene server
23           starts, otherwise the sysadmin is responsible for ensuring the directory
24           exists with appropriate ownership and permissions.
25         '';
26       };
28       user = mkOption {
29         type = types.str;
30         default = "galene";
31         description = "User account under which galene runs.";
32       };
34       group = mkOption {
35         type = types.str;
36         default = "galene";
37         description = "Group under which galene runs.";
38       };
40       insecure = mkOption {
41         type = types.bool;
42         default = false;
43         description = ''
44           Whether Galene should listen in http or in https. If left as the default
45           value (false), Galene needs to be fed a private key and a certificate.
46         '';
47       };
49       certFile = mkOption {
50         type = types.nullOr types.str;
51         default = null;
52         example = "/path/to/your/cert.pem";
53         description = ''
54           Path to the server's certificate. The file is copied at runtime to
55           Galene's data directory where it needs to reside.
56         '';
57       };
59       keyFile = mkOption {
60         type = types.nullOr types.str;
61         default = null;
62         example = "/path/to/your/key.pem";
63         description = ''
64           Path to the server's private key. The file is copied at runtime to
65           Galene's data directory where it needs to reside.
66         '';
67       };
69       httpAddress = mkOption {
70         type = types.str;
71         default = "";
72         description = "HTTP listen address for galene.";
73       };
75       httpPort = mkOption {
76         type = types.port;
77         default = 8443;
78         description = "HTTP listen port.";
79       };
81       staticDir = mkOption {
82         type = types.str;
83         default = "${cfg.package.static}/static";
84         defaultText = literalExpression ''"''${package.static}/static"'';
85         example = "/var/lib/galene/static";
86         description = "Web server directory.";
87       };
89       recordingsDir = mkOption {
90         type = types.str;
91         default = defaultrecordingsDir;
92         defaultText = literalExpression ''"''${config.${opt.stateDir}}/recordings"'';
93         example = "/var/lib/galene/recordings";
94         description = "Recordings directory.";
95       };
97       dataDir = mkOption {
98         type = types.str;
99         default = defaultdataDir;
100         defaultText = literalExpression ''"''${config.${opt.stateDir}}/data"'';
101         example = "/var/lib/galene/data";
102         description = "Data directory.";
103       };
105       groupsDir = mkOption {
106         type = types.str;
107         default = defaultgroupsDir;
108         defaultText = literalExpression ''"''${config.${opt.stateDir}}/groups"'';
109         example = "/var/lib/galene/groups";
110         description = "Web server directory.";
111       };
113       package = mkPackageOption pkgs "galene" { };
114     };
115   };
117   config = mkIf cfg.enable {
118     assertions = [
119       {
120         assertion = cfg.insecure || (cfg.certFile != null && cfg.keyFile != null);
121         message = ''
122           Galene needs both certFile and keyFile defined for encryption, or
123           the insecure flag.
124         '';
125       }
126     ];
128     systemd.services.galene = {
129       description = "galene";
130       after = [ "network.target" ];
131       wantedBy = [ "multi-user.target" ];
133       preStart = ''
134         ${optionalString (cfg.insecure != true) ''
135            install -m 700 -o '${cfg.user}' -g '${cfg.group}' ${cfg.certFile} ${cfg.dataDir}/cert.pem
136            install -m 700 -o '${cfg.user}' -g '${cfg.group}' ${cfg.keyFile} ${cfg.dataDir}/key.pem
137         ''}
138       '';
140       serviceConfig = mkMerge [
141         {
142           Type = "simple";
143           User = cfg.user;
144           Group = cfg.group;
145           WorkingDirectory = cfg.stateDir;
146           ExecStart = ''${cfg.package}/bin/galene \
147           ${optionalString (cfg.insecure) "-insecure"} \
148           -data ${cfg.dataDir} \
149           -groups ${cfg.groupsDir} \
150           -recordings ${cfg.recordingsDir} \
151           -static ${cfg.staticDir}'';
152           Restart = "always";
153           # Upstream Requirements
154           LimitNOFILE = 65536;
155           StateDirectory = [ ] ++
156             optional (cfg.stateDir == defaultstateDir) "galene" ++
157             optional (cfg.dataDir == defaultdataDir) "galene/data" ++
158             optional (cfg.groupsDir == defaultgroupsDir) "galene/groups" ++
159             optional (cfg.recordingsDir == defaultrecordingsDir) "galene/recordings";
161           # Hardening
162           CapabilityBoundingSet = [ "" ];
163           DeviceAllow = [ "" ];
164           LockPersonality = true;
165           MemoryDenyWriteExecute = true;
166           NoNewPrivileges = true;
167           PrivateDevices = true;
168           PrivateTmp = true;
169           PrivateUsers = true;
170           ProcSubset = "pid";
171           ProtectClock = true;
172           ProtectControlGroups = true;
173           ProtectHome = true;
174           ProtectHostname = true;
175           ProtectKernelLogs = true;
176           ProtectKernelModules = true;
177           ProtectKernelTunables = true;
178           ProtectProc = "invisible";
179           ProtectSystem = "strict";
180           ReadWritePaths = cfg.recordingsDir;
181           RemoveIPC = true;
182           RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_NETLINK" ];
183           RestrictNamespaces = true;
184           RestrictRealtime = true;
185           RestrictSUIDSGID = true;
186           SystemCallArchitectures = "native";
187           SystemCallFilter = [ "@system-service" "~@privileged" ];
188           UMask = "0077";
189         }
190       ];
191     };
193     users.users = mkIf (cfg.user == "galene")
194       {
195         galene = {
196           description = "galene Service";
197           group = cfg.group;
198           isSystemUser = true;
199         };
200       };
202     users.groups = mkIf (cfg.group == "galene") {
203       galene = { };
204     };
205   };
206   meta.maintainers = with lib.maintainers; [ rgrunbla ];