1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.mwlib;
7 pypkgs = pkgs.python27Packages;
8
9 inherit (pypkgs) python mwlib;
10
11 user = mkOption {
12 default = "nobody";
13 type = types.str;
14 description = "User to run as.";
15 };
16
17in
18{
19
20 options.services.mwlib = {
21
22 nserve = {
23 enable = mkOption {
24 default = false;
25 type = types.bool;
26 description = ''
27 Whether to enable nserve. Nserve is a HTTP
28 server. The Collection extension is talking to
29 that program directly. Nserve uses at least
30 one qserve instance in order to distribute
31 and manage jobs.
32 '';
33 }; # nserve.enable
34
35 port = mkOption {
36 default = 8899;
37 type = types.int;
38 description = "Specify port to listen on.";
39 }; # nserve.port
40
41 address = mkOption {
42 default = "127.0.0.1";
43 type = types.str;
44 description = "Specify network interface to listen on.";
45 }; # nserve.address
46
47 qserve = mkOption {
48 default = [ "${cfg.qserve.address}:${toString cfg.qserve.port}" ];
49 type = types.listOf types.str;
50 description = "Register qserve instance.";
51 }; # nserve.qserve
52
53 inherit user;
54 }; # nserve
55
56 qserve = {
57 enable = mkOption {
58 default = false;
59 type = types.bool;
60 description = ''
61 A job queue server used to distribute and manage
62 jobs. You should start one qserve instance
63 for each machine that is supposed to render pdf
64 files. Unless you’re operating the Wikipedia
65 installation, one machine should suffice.
66 '';
67 }; # qserve.enable
68
69 port = mkOption {
70 default = 14311;
71 type = types.int;
72 description = "Specify port to listen on.";
73 }; # qserve.port
74
75 address = mkOption {
76 default = "127.0.0.1";
77 type = types.str;
78 description = "Specify network interface to listen on.";
79 }; # qserve.address
80
81 datadir = mkOption {
82 default = "/var/lib/mwlib-qserve";
83 type = types.path;
84 description = "qserve data directory (FIXME: unused?)";
85 }; # qserve.datadir
86
87 allow = mkOption {
88 default = [ "127.0.0.1" ];
89 type = types.listOf types.str;
90 description = "List of allowed client IPs. Empty means any.";
91 }; # qserve.allow
92
93 inherit user;
94 }; # qserve
95
96 nslave = {
97 enable = mkOption {
98 default = cfg.qserve.enable;
99 type = types.bool;
100 description = ''
101 Pulls new jobs from exactly one qserve instance
102 and calls the zip and render programs
103 in order to download article collections and
104 convert them to different output formats. Nslave
105 uses a cache directory to store the generated
106 documents. Nslave also starts an internal http
107 server serving the content of the cache directory.
108 '';
109 }; # nslave.enable
110
111 cachedir = mkOption {
112 default = "/var/cache/mwlib-nslave";
113 type = types.path;
114 description = "Directory to store generated documents.";
115 }; # nslave.cachedir
116
117 numprocs = mkOption {
118 default = 10;
119 type = types.int;
120 description = "Number of parallel jobs to be executed.";
121 }; # nslave.numprocs
122
123 http = mkOption {
124 default = {};
125 description = ''
126 Internal http server serving the content of the cache directory.
127 You have to enable it, or use your own way for serving files
128 and set the http.url option accordingly.
129 '';
130 type = types.submodule ({
131 options = {
132 enable = mkOption {
133 default = true;
134 type = types.bool;
135 description = "Enable internal http server.";
136 }; # nslave.http.enable
137
138 port = mkOption {
139 default = 8898;
140 type = types.int;
141 description = "Port to listen to when serving files from cache.";
142 }; # nslave.http.port
143
144 address = mkOption {
145 default = "127.0.0.1";
146 type = types.str;
147 description = "Specify network interface to listen on.";
148 }; # nslave.http.address
149
150 url = mkOption {
151 default = "http://localhost:${toString cfg.nslave.http.port}/cache";
152 type = types.str;
153 description = ''
154 Specify URL for accessing generated files from cache.
155 The Collection extension of Mediawiki won't be able to
156 download files without it.
157 '';
158 }; # nslave.http.url
159 };
160 }); # types.submodule
161 }; # nslave.http
162
163 inherit user;
164 }; # nslave
165
166 }; # options.services
167
168 config = {
169
170 systemd.services.mwlib-nserve = mkIf cfg.nserve.enable
171 {
172 description = "mwlib network interface";
173
174 wantedBy = [ "multi-user.target" ];
175 after = [ "network.target" "mwlib-qserve.service" ];
176
177 serviceConfig = {
178 ExecStart = concatStringsSep " " (
179 [
180 "${mwlib}/bin/nserve"
181 "--port ${toString cfg.nserve.port}"
182 "--interface ${cfg.nserve.address}"
183 ] ++ cfg.nserve.qserve
184 );
185 User = cfg.nserve.user;
186 };
187 }; # systemd.services.mwlib-nserve
188
189 systemd.services.mwlib-qserve = mkIf cfg.qserve.enable
190 {
191 description = "mwlib job queue server";
192
193 wantedBy = [ "multi-user.target" ];
194 after = [ "network.target" "local-fs.target" ];
195
196 preStart = ''
197 mkdir -pv '${cfg.qserve.datadir}'
198 chown -Rc ${cfg.qserve.user}:`id -ng ${cfg.qserve.user}` '${cfg.qserve.datadir}'
199 chmod -Rc u=rwX,go= '${cfg.qserve.datadir}'
200 '';
201
202 serviceConfig = {
203 ExecStart = concatStringsSep " " (
204 [
205 "${mwlib}/bin/mw-qserve"
206 "-p ${toString cfg.qserve.port}"
207 "-i ${cfg.qserve.address}"
208 "-d ${cfg.qserve.datadir}"
209 ] ++ map (a: "-a ${a}") cfg.qserve.allow
210 );
211 User = cfg.qserve.user;
212 PermissionsStartOnly = true;
213 };
214 }; # systemd.services.mwlib-qserve
215
216 systemd.services.mwlib-nslave = mkIf cfg.nslave.enable
217 {
218 description = "mwlib worker";
219
220 wantedBy = [ "multi-user.target" ];
221 after = [ "network.target" "local-fs.target" ];
222
223 preStart = ''
224 mkdir -pv '${cfg.nslave.cachedir}'
225 chown -Rc ${cfg.nslave.user}:`id -ng ${cfg.nslave.user}` '${cfg.nslave.cachedir}'
226 chmod -Rc u=rwX,go= '${cfg.nslave.cachedir}'
227 '';
228
229 path = with pkgs; [ imagemagick pdftk ];
230 environment = {
231 PYTHONPATH = concatMapStringsSep ":"
232 (m: "${pypkgs.${m}}/lib/${python.libPrefix}/site-packages")
233 [ "mwlib-rl" "mwlib-ext" "pygments" "pyfribidi" ];
234 };
235
236 serviceConfig = {
237 ExecStart = concatStringsSep " " (
238 [
239 "${mwlib}/bin/nslave"
240 "--cachedir ${cfg.nslave.cachedir}"
241 "--numprocs ${toString cfg.nslave.numprocs}"
242 "--url ${cfg.nslave.http.url}"
243 ] ++ (
244 if cfg.nslave.http.enable then
245 [
246 "--serve-files-port ${toString cfg.nslave.http.port}"
247 "--serve-files-address ${cfg.nslave.http.address}"
248 ] else
249 [
250 "--no-serve-files"
251 ]
252 ));
253 User = cfg.nslave.user;
254 PermissionsStartOnly = true;
255 };
256 }; # systemd.services.mwlib-nslave
257
258 }; # config
259}