1{ config, lib, pkgs, ... }:
2
3with lib;
4let
5 cfg = config.services.galene;
6 defaultstateDir = "/var/lib/galene";
7 defaultrecordingsDir = "${cfg.stateDir}/recordings";
8 defaultgroupsDir = "${cfg.stateDir}/groups";
9 defaultdataDir = "${cfg.stateDir}/data";
10in
11{
12 options = {
13 services.galene = {
14 enable = mkEnableOption "Galene Service.";
15
16 stateDir = mkOption {
17 default = defaultstateDir;
18 type = types.str;
19 description = ''
20 The directory where Galene stores its internal state. If left as the default
21 value this directory will automatically be created before the Galene server
22 starts, otherwise the sysadmin is responsible for ensuring the directory
23 exists with appropriate ownership and permissions.
24 '';
25 };
26
27 user = mkOption {
28 type = types.str;
29 default = "galene";
30 description = "User account under which galene runs.";
31 };
32
33 group = mkOption {
34 type = types.str;
35 default = "galene";
36 description = "Group under which galene runs.";
37 };
38
39 insecure = mkOption {
40 type = types.bool;
41 default = false;
42 description = ''
43 Whether Galene should listen in http or in https. If left as the default
44 value (false), Galene needs to be fed a private key and a certificate.
45 '';
46 };
47
48 certFile = mkOption {
49 type = types.nullOr types.str;
50 default = null;
51 example = "/path/to/your/cert.pem";
52 description = ''
53 Path to the server's certificate. The file is copied at runtime to
54 Galene's data directory where it needs to reside.
55 '';
56 };
57
58 keyFile = mkOption {
59 type = types.nullOr types.str;
60 default = null;
61 example = "/path/to/your/key.pem";
62 description = ''
63 Path to the server's private key. The file is copied at runtime to
64 Galene's data directory where it needs to reside.
65 '';
66 };
67
68 httpAddress = mkOption {
69 type = types.str;
70 default = "";
71 description = "HTTP listen address for galene.";
72 };
73
74 httpPort = mkOption {
75 type = types.port;
76 default = 8443;
77 description = "HTTP listen port.";
78 };
79
80 staticDir = mkOption {
81 type = types.str;
82 default = "${cfg.package.static}/static";
83 defaultText = literalExpression ''"''${package.static}/static"'';
84 example = "/var/lib/galene/static";
85 description = "Web server directory.";
86 };
87
88 recordingsDir = mkOption {
89 type = types.str;
90 default = defaultrecordingsDir;
91 example = "/var/lib/galene/recordings";
92 description = "Recordings directory.";
93 };
94
95 dataDir = mkOption {
96 type = types.str;
97 default = defaultdataDir;
98 example = "/var/lib/galene/data";
99 description = "Data directory.";
100 };
101
102 groupsDir = mkOption {
103 type = types.str;
104 default = defaultgroupsDir;
105 example = "/var/lib/galene/groups";
106 description = "Web server directory.";
107 };
108
109 package = mkOption {
110 default = pkgs.galene;
111 defaultText = literalExpression "pkgs.galene";
112 type = types.package;
113 description = ''
114 Package for running Galene.
115 '';
116 };
117 };
118 };
119
120 config = mkIf cfg.enable {
121 assertions = [
122 {
123 assertion = cfg.insecure || (cfg.certFile != null && cfg.keyFile != null);
124 message = ''
125 Galene needs both certFile and keyFile defined for encryption, or
126 the insecure flag.
127 '';
128 }
129 ];
130
131 systemd.services.galene = {
132 description = "galene";
133 after = [ "network.target" ];
134 wantedBy = [ "multi-user.target" ];
135
136 preStart = ''
137 ${optionalString (cfg.insecure != true) ''
138 install -m 700 -o '${cfg.user}' -g '${cfg.group}' ${cfg.certFile} ${cfg.dataDir}/cert.pem
139 install -m 700 -o '${cfg.user}' -g '${cfg.group}' ${cfg.keyFile} ${cfg.dataDir}/key.pem
140 ''}
141 '';
142
143 serviceConfig = mkMerge [
144 {
145 Type = "simple";
146 User = cfg.user;
147 Group = cfg.group;
148 WorkingDirectory = cfg.stateDir;
149 ExecStart = ''${cfg.package}/bin/galene \
150 ${optionalString (cfg.insecure) "-insecure"} \
151 -data ${cfg.dataDir} \
152 -groups ${cfg.groupsDir} \
153 -recordings ${cfg.recordingsDir} \
154 -static ${cfg.staticDir}'';
155 Restart = "always";
156 # Upstream Requirements
157 LimitNOFILE = 65536;
158 StateDirectory = [ ] ++
159 optional (cfg.stateDir == defaultstateDir) "galene" ++
160 optional (cfg.dataDir == defaultdataDir) "galene/data" ++
161 optional (cfg.groupsDir == defaultgroupsDir) "galene/groups" ++
162 optional (cfg.recordingsDir == defaultrecordingsDir) "galene/recordings";
163 }
164 ];
165 };
166
167 users.users = mkIf (cfg.user == "galene")
168 {
169 galene = {
170 description = "galene Service";
171 group = cfg.group;
172 isSystemUser = true;
173 };
174 };
175
176 users.groups = mkIf (cfg.group == "galene") {
177 galene = { };
178 };
179 };
180 meta.maintainers = with lib.maintainers; [ rgrunbla ];
181}