1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.murmur;
7 configFile = pkgs.writeText "murmurd.ini" ''
8 database=/var/lib/murmur/murmur.sqlite
9 dbDriver=QSQLITE
10
11 autobanAttempts=${toString cfg.autobanAttempts}
12 autobanTimeframe=${toString cfg.autobanTimeframe}
13 autobanTime=${toString cfg.autobanTime}
14
15 logfile=/var/log/murmur/murmurd.log
16 pidfile=${cfg.pidfile}
17
18 welcome="${cfg.welcome}"
19 port=${toString cfg.port}
20
21 ${if cfg.hostName == "" then "" else "host="+cfg.hostName}
22 ${if cfg.password == "" then "" else "serverpassword="+cfg.password}
23
24 bandwidth=${toString cfg.bandwidth}
25 users=${toString cfg.users}
26
27 textmessagelength=${toString cfg.textMsgLength}
28 imagemessagelength=${toString cfg.imgMsgLength}
29 allowhtml=${if cfg.allowHtml then "true" else "false"}
30 logdays=${toString cfg.logDays}
31 bonjour=${if cfg.bonjour then "true" else "false"}
32 sendversion=${if cfg.sendVersion then "true" else "false"}
33
34 ${if cfg.registerName == "" then "" else "registerName="+cfg.registerName}
35 ${if cfg.registerPassword == "" then "" else "registerPassword="+cfg.registerPassword}
36 ${if cfg.registerUrl == "" then "" else "registerUrl="+cfg.registerUrl}
37 ${if cfg.registerHostname == "" then "" else "registerHostname="+cfg.registerHostname}
38
39 certrequired=${if cfg.clientCertRequired then "true" else "false"}
40 ${if cfg.sslCert == "" then "" else "sslCert="+cfg.sslCert}
41 ${if cfg.sslKey == "" then "" else "sslKey="+cfg.sslKey}
42 ${if cfg.sslCa == "" then "" else "sslCA="+cfg.sslCa}
43
44 ${cfg.extraConfig}
45 '';
46in
47{
48 options = {
49 services.murmur = {
50 enable = mkOption {
51 type = types.bool;
52 default = false;
53 description = "If enabled, start the Murmur Service.";
54 };
55
56 autobanAttempts = mkOption {
57 type = types.int;
58 default = 10;
59 description = ''
60 Number of attempts a client is allowed to make in
61 <literal>autobanTimeframe</literal> seconds, before being
62 banned for <literal>autobanTime</literal>.
63 '';
64 };
65
66 autobanTimeframe = mkOption {
67 type = types.int;
68 default = 120;
69 description = ''
70 Timeframe in which a client can connect without being banned
71 for repeated attempts (in seconds).
72 '';
73 };
74
75 autobanTime = mkOption {
76 type = types.int;
77 default = 300;
78 description = "The amount of time an IP ban lasts (in seconds).";
79 };
80
81 pidfile = mkOption {
82 type = types.path;
83 default = "/tmp/murmurd.pid";
84 description = "Path to PID file for Murmur daemon.";
85 };
86
87 welcome = mkOption {
88 type = types.str;
89 default = "";
90 description = "Welcome message for connected clients.";
91 };
92
93 port = mkOption {
94 type = types.int;
95 default = 64738;
96 description = "Ports to bind to (UDP and TCP).";
97 };
98
99 hostName = mkOption {
100 type = types.str;
101 default = "";
102 description = "Host to bind to. Defaults binding on all addresses.";
103 };
104
105 password = mkOption {
106 type = types.str;
107 default = "";
108 description = "Required password to join server, if specified.";
109 };
110
111 bandwidth = mkOption {
112 type = types.int;
113 default = 72000;
114 description = ''
115 Maximum bandwidth (in bits per second) that clients may send
116 speech at.
117 '';
118 };
119
120 users = mkOption {
121 type = types.int;
122 default = 100;
123 description = "Maximum number of concurrent clients allowed.";
124 };
125
126 textMsgLength = mkOption {
127 type = types.int;
128 default = 5000;
129 description = "Max length of text messages. Set 0 for no limit.";
130 };
131
132 imgMsgLength = mkOption {
133 type = types.int;
134 default = 131072;
135 description = "Max length of image messages. Set 0 for no limit.";
136 };
137
138 allowHtml = mkOption {
139 type = types.bool;
140 default = true;
141 description = ''
142 Allow HTML in client messages, comments, and channel
143 descriptions.
144 '';
145 };
146
147 logDays = mkOption {
148 type = types.int;
149 default = 31;
150 description = ''
151 How long to store RPC logs for in the database. Set 0 to
152 keep logs forever, or -1 to disable DB logging.
153 '';
154 };
155
156 bonjour = mkOption {
157 type = types.bool;
158 default = false;
159 description = ''
160 Enable Bonjour auto-discovery, which allows clients over
161 your LAN to automatically discover Murmur servers.
162 '';
163 };
164
165 sendVersion = mkOption {
166 type = types.bool;
167 default = true;
168 description = "Send Murmur version in UDP response.";
169 };
170
171 registerName = mkOption {
172 type = types.str;
173 default = "";
174 description = ''
175 Public server registration name, and also the name of the
176 Root channel. Even if you don't publicly register your
177 server, you probably still want to set this.
178 '';
179 };
180
181 registerPassword = mkOption {
182 type = types.str;
183 default = "";
184 description = ''
185 Public server registry password, used authenticate your
186 server to the registry to prevent impersonation; required for
187 subsequent registry updates.
188 '';
189 };
190
191 registerUrl = mkOption {
192 type = types.str;
193 default = "";
194 description = "URL website for your server.";
195 };
196
197 registerHostname = mkOption {
198 type = types.str;
199 default = "";
200 description = ''
201 DNS hostname where your server can be reached. This is only
202 needed if you want your server to be accessed by its
203 hostname and not IP - but the name *must* resolve on the
204 internet properly.
205 '';
206 };
207
208 clientCertRequired = mkOption {
209 type = types.bool;
210 default = false;
211 description = "Require clients to authenticate via certificates.";
212 };
213
214 sslCert = mkOption {
215 type = types.str;
216 default = "";
217 description = "Path to your SSL certificate.";
218 };
219
220 sslKey = mkOption {
221 type = types.str;
222 default = "";
223 description = "Path to your SSL key.";
224 };
225
226 sslCa = mkOption {
227 type = types.str;
228 default = "";
229 description = "Path to your SSL CA certificate.";
230 };
231
232 extraConfig = mkOption {
233 type = types.str;
234 default = "";
235 description = "Extra configuration to put into mumur.ini.";
236 };
237 };
238 };
239
240 config = mkIf cfg.enable {
241 users.extraUsers.murmur = {
242 description = "Murmur Service user";
243 home = "/var/lib/murmur";
244 createHome = true;
245 uid = config.ids.uids.murmur;
246 };
247
248 systemd.services.murmur = {
249 description = "Murmur Chat Service";
250 wantedBy = [ "multi-user.target" ];
251 after = [ "network.target "];
252
253 serviceConfig = {
254 Type = "forking";
255 PIDFile = cfg.pidfile;
256 Restart = "always";
257 User = "murmur";
258 ExecStart = "${pkgs.murmur}/bin/murmurd -ini ${configFile}";
259 PermissionsStartOnly = true;
260 };
261
262 preStart = ''
263 mkdir -p /var/log/murmur
264 chown -R murmur /var/log/murmur
265 '';
266 };
267 };
268}