]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - modules/private/websites/tools/tools/default.nix
Migrate php sessions to redis
[perso/Immae/Config/Nix.git] / modules / private / websites / tools / tools / default.nix
1 { lib, pkgs, config, ... }:
2 let
3 flakeCompat = import ../../../../../lib/flake-compat.nix;
4
5 adminer = pkgs.callPackage ./adminer.nix {};
6 ympd = pkgs.callPackage ./ympd.nix {
7 env = config.myEnv.tools.ympd;
8 };
9 ttrss = pkgs.callPackage ./ttrss.nix {
10 inherit (pkgs.webapps) ttrss ttrss-plugins;
11 env = config.myEnv.tools.ttrss;
12 php = pkgs.php72;
13 inherit config;
14 };
15 kanboard = pkgs.callPackage ./kanboard.nix {
16 inherit config;
17 env = config.myEnv.tools.kanboard;
18 };
19 wallabag = pkgs.callPackage ./wallabag.nix {
20 wallabag = pkgs.webapps.wallabag.override {
21 composerEnv = pkgs.composerEnv.override {
22 php = pkgs.php73.withExtensions({ enabled, all }: enabled ++ [all.tidy]);
23 };
24 };
25 env = config.myEnv.tools.wallabag;
26 inherit config;
27 };
28 yourls = pkgs.callPackage ./yourls.nix {
29 inherit (pkgs.webapps) yourls yourls-plugins;
30 env = config.myEnv.tools.yourls;
31 inherit config;
32 };
33 rompr = pkgs.callPackage ./rompr.nix {
34 inherit (pkgs.webapps) rompr;
35 env = config.myEnv.tools.rompr;
36 };
37 shaarli = pkgs.callPackage ./shaarli.nix {
38 env = config.myEnv.tools.shaarli;
39 inherit config;
40 };
41 dokuwiki = pkgs.callPackage ./dokuwiki.nix {
42 inherit (pkgs.webapps) dokuwiki dokuwiki-plugins;
43 };
44 ldap = pkgs.callPackage ./ldap.nix {
45 inherit (pkgs.webapps) phpldapadmin;
46 env = config.myEnv.tools.phpldapadmin;
47 inherit config;
48 };
49 grocy = pkgs.callPackage ./grocy.nix {
50 grocy = pkgs.webapps.grocy.override { composerEnv = pkgs.composerEnv.override { php = pkgs.php72; }; };
51 };
52 phpbb = pkgs.callPackage ./phpbb.nix {
53 phpbb = (pkgs.webapps.phpbb.withLangs (l: [ l.fr ])).withExts (e: [
54 e.alfredoramos.markdown e.davidiq.mailinglist e.dmzx.mchat
55 e.empteintesduweb.monitoranswers e.lr94.autosubscribe
56 e.phpbbmodders.adduser ]);
57 };
58 webhooks-bin-env = pkgs.buildEnv {
59 name = "webhook-env";
60 paths = [ pkgs.apprise ];
61 pathsToLink = [ "/bin" ];
62 };
63 webhooks = pkgs.callPackage ./webhooks.nix {
64 env = config.myEnv.tools.webhooks;
65 binEnv = webhooks-bin-env;
66 };
67 dmarc-reports = pkgs.callPackage ./dmarc_reports.nix {
68 env = config.myEnv.tools.dmarc_reports;
69 inherit config;
70 };
71
72 landing = pkgs.callPackage ./landing.nix {};
73
74 cfg = config.myServices.websites.tools.tools;
75 pcfg = config.services.phpfpm.pools;
76 in {
77 imports =
78 builtins.attrValues (flakeCompat ../../../../../flakes/private/paste).nixosModules;
79
80 options.myServices.websites.tools.tools = {
81 enable = lib.mkEnableOption "enable tools website";
82 };
83
84 config = lib.mkIf cfg.enable {
85 myServices.chatonsProperties.services = {
86 dokuwiki = dokuwiki.chatonsProperties;
87 shaarli = shaarli.chatonsProperties;
88 ttrss = ttrss.chatonsProperties;
89 wallabag = wallabag.chatonsProperties;
90 paste = {
91 file.datetime = "2022-08-22T00:15:00";
92 service = {
93 name = "Paste";
94 description = "A simple paster script with syntax highlight";
95 website = "https://tools.immae.eu/paste/";
96 logo = "https://assets.immae.eu/logo.jpg";
97 status.level = "OK";
98 status.description = "OK";
99 registration."" = ["MEMBER" "CLIENT"];
100 registration.load = "OPEN";
101 install.type = "PACKAGE";
102 guide.user = "https://tools.immae.eu/paste/";
103 };
104 software = {
105 name = "Paste";
106 website = "https://tools.immae.eu/paste/";
107 license.url = "https://tools.immae.eu/paste/license";
108 license.name = "MIT License";
109 version = "Unversioned";
110 source.url = "https://tools.immae.eu/paste/abcd123/py";
111 };
112 };
113 };
114 myServices.chatonsProperties.hostings = {
115 dokuwiki = dokuwiki.chatonsHostingProperties;
116 phpbb = phpbb.chatonsHostingProperties;
117 };
118 secrets.keys =
119 kanboard.keys
120 // ldap.keys
121 // shaarli.keys
122 // ttrss.keys
123 // wallabag.keys
124 // yourls.keys
125 // dmarc-reports.keys
126 // webhooks.keys;
127
128 services.websites.env.tools.modules =
129 [ "proxy_fcgi" ]
130 ++ adminer.apache.modules
131 ++ ympd.apache.modules
132 ++ ttrss.apache.modules
133 ++ wallabag.apache.modules
134 ++ yourls.apache.modules
135 ++ rompr.apache.modules
136 ++ shaarli.apache.modules
137 ++ dokuwiki.apache.modules
138 ++ dmarc-reports.apache.modules
139 ++ phpbb.apache.modules
140 ++ ldap.apache.modules
141 ++ kanboard.apache.modules;
142
143 services.websites.env.integration.vhostConfs.devtools = {
144 certName = "integration";
145 certMainHost = "tools.immae.dev";
146 addToCerts = true;
147 hosts = [ "tools.immae.dev" ];
148 root = "/var/lib/ftp/immae/devtools";
149 extraConfig = [
150 ''
151 Use Apaxy "/var/lib/ftp/immae/devtools" "title"
152 Timeout 600
153 ProxyTimeout 600
154 Header always set Content-Security-Policy-Report-Only "${config.myEnv.tools.csp_reports.policies.inline}"
155 <Directory "/var/lib/ftp/immae/devtools">
156 DirectoryIndex index.php index.htm index.html
157 AllowOverride all
158 Require all granted
159 <FilesMatch "\.php$">
160 SetHandler "proxy:unix:${pcfg.devtools.socket}|fcgi://localhost"
161 </FilesMatch>
162 </Directory>
163 ''
164 ];
165 };
166
167 services.websites.env.tools.vhostConfs.tools = {
168 certName = "eldiron";
169 addToCerts = true;
170 hosts = ["tools.immae.eu" ];
171 root = landing;
172 extraConfig = [
173 ''
174 RedirectMatch 301 ^/vpn(.*)$ https://vpn.immae.eu$1
175 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
176 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
177
178 <Directory "${landing}">
179 DirectoryIndex index.html
180 AllowOverride None
181 Require all granted
182
183 <FilesMatch "\.php$">
184 SetHandler "proxy:unix:${pcfg.tools.socket}|fcgi://localhost"
185 </FilesMatch>
186 </Directory>
187 ''
188 (adminer.apache.vhostConf pcfg.adminer.socket)
189 ympd.apache.vhostConf
190 (ttrss.apache.vhostConf pcfg.ttrss.socket)
191 (wallabag.apache.vhostConf pcfg.wallabag.socket)
192 (yourls.apache.vhostConf pcfg.yourls.socket)
193 (rompr.apache.vhostConf pcfg.rompr.socket)
194 (shaarli.apache.vhostConf pcfg.shaarli.socket)
195 (dokuwiki.apache.vhostConf pcfg.dokuwiki.socket)
196 (ldap.apache.vhostConf pcfg.ldap.socket)
197 (kanboard.apache.vhostConf pcfg.kanboard.socket)
198 (grocy.apache.vhostConf pcfg.grocy.socket)
199 (phpbb.apache.vhostConf pcfg.phpbb.socket)
200 (dmarc-reports.apache.vhostConf pcfg.dmarc-reports.socket)
201 ''
202 <Location "/paste/">
203 ProxyPass unix://${config.services.paste.sockets.gunicorn}|http://tools.immae.eu/paste/
204 ProxyPassReverse unix://${config.services.paste.sockets.gunicorn}|http://tools.immae.eu/paste/
205 ProxyPreserveHost on
206 </Location>
207 <Location "/paste">
208 ProxyPass unix://${config.services.paste.sockets.gunicorn}|http://tools.immae.eu/paste/
209 ProxyPassReverse unix://${config.services.paste.sockets.gunicorn}|http://tools.immae.eu/paste/
210 ProxyPreserveHost on
211 </Location>
212
213 <Location "/ntfy/">
214 SetEnv proxy-nokeepalive 1
215 SetEnv proxy-sendchunked 1
216 LimitRequestBody 102400
217
218 RewriteEngine On
219
220 # FIXME: why is landing prefixed in the url?
221 RewriteCond %{HTTP:Upgrade} websocket [NC]
222 RewriteCond %{HTTP:Connection} upgrade [NC]
223 RewriteRule ^(${landing}/ntfy)?/?(.*) unix:///run/ntfy/ntfy.sock|ws://tools.immae.eu/$2 [P,NE,QSA,L]
224
225 RewriteRule ^(${landing}/ntfy)?/?(.*) unix:///run/ntfy/ntfy.sock|http://tools.immae.eu/$2 [P,NE,QSA,L]
226 </Location>
227 Alias /BIP39 /var/lib/buildbot/outputs/immae/bip39
228 <Directory "/var/lib/buildbot/outputs/immae/bip39">
229 DirectoryIndex index.html
230 AllowOverride None
231 Require all granted
232 </Directory>
233
234 Alias /webhooks ${config.secrets.fullPaths."webapps/webhooks"}
235 <Directory "${config.secrets.fullPaths."webapps/webhooks"}">
236 Options -Indexes
237 DirectoryIndex index.php
238 Require all granted
239 AllowOverride None
240 <FilesMatch "\.php$">
241 SetHandler "proxy:unix:${pcfg.tools.socket}|fcgi://localhost"
242 </FilesMatch>
243 </Directory>
244 ''
245 ];
246 };
247
248 services.websites.env.tools.vhostConfs.outils = {
249 certName = "eldiron";
250 addToCerts = true;
251 hosts = [ "outils.immae.eu" ];
252 root = null;
253 extraConfig = [
254 ''
255 RedirectMatch 301 ^/mediagoblin(.*)$ https://mgoblin.immae.eu$1
256
257 RedirectMatch 301 ^/ether(.*)$ https://ether.immae.eu$1
258
259 RedirectMatch 301 ^/nextcloud(.*)$ https://cloud.immae.eu$1
260 RedirectMatch 301 ^/owncloud(.*)$ https://cloud.immae.eu$1
261
262 RedirectMatch 301 ^/carddavmate(.*)$ https://dav.immae.eu/infcloud$1
263 RedirectMatch 301 ^/caldavzap(.*)$ https://dav.immae.eu/infcloud$1
264 RedirectMatch 301 ^/caldav.php(.*)$ https://dav.immae.eu/caldav.php$1
265 RedirectMatch 301 ^/davical(.*)$ https://dav.immae.eu/davical$1
266
267 RedirectMatch 301 ^/taskweb(.*)$ https://task.immae.eu/taskweb$1
268
269 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
270
271 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
272
273 RedirectMatch 301 ^/vpn(.*)$ https://vpn.immae.eu$1
274
275 RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1
276 ''
277 ];
278 };
279
280 systemd.services = {
281 phpfpm-dokuwiki = {
282 after = lib.mkAfter dokuwiki.phpFpm.serviceDeps;
283 wants = dokuwiki.phpFpm.serviceDeps;
284 };
285 phpfpm-phpbb = {
286 after = lib.mkAfter phpbb.phpFpm.serviceDeps;
287 wants = phpbb.phpFpm.serviceDeps;
288 };
289 phpfpm-kanboard = {
290 after = lib.mkAfter kanboard.phpFpm.serviceDeps;
291 wants = kanboard.phpFpm.serviceDeps;
292 };
293 phpfpm-ldap = {
294 after = lib.mkAfter ldap.phpFpm.serviceDeps;
295 wants = ldap.phpFpm.serviceDeps;
296 };
297 phpfpm-shaarli = {
298 after = lib.mkAfter shaarli.phpFpm.serviceDeps;
299 wants = shaarli.phpFpm.serviceDeps;
300 };
301 phpfpm-ttrss = {
302 after = lib.mkAfter ttrss.phpFpm.serviceDeps;
303 wants = ttrss.phpFpm.serviceDeps;
304 };
305 phpfpm-wallabag = {
306 after = lib.mkAfter wallabag.phpFpm.serviceDeps;
307 wants = wallabag.phpFpm.serviceDeps;
308 preStart = lib.mkAfter wallabag.phpFpm.preStart;
309 };
310 phpfpm-yourls = {
311 after = lib.mkAfter yourls.phpFpm.serviceDeps;
312 wants = yourls.phpFpm.serviceDeps;
313 };
314 ntfy = {
315 description = "send push notifications to your phone or desktop via scripts from any computer";
316 wantedBy = [ "multi-user.target" ];
317 serviceConfig = {
318 ExecStart = "${pkgs.ntfy-sh}/bin/ntfy serve --listen-http '' --listen-unix %t/ntfy/ntfy.sock --cache-file %S/ntfy/cache.db --cache-duration 120h --behind-proxy --attachment-cache-dir %S/ntfy/attachments --base-url https://tools.immae.eu/ntfy";
319 Type = "simple";
320 WorkingDirectory = "%S/ntfy";
321 RuntimeDirectory = "ntfy";
322 StateDirectory = "ntfy";
323 User = "wwwrun";
324 };
325 };
326 ympd = {
327 description = "Standalone MPD Web GUI written in C";
328 wantedBy = [ "multi-user.target" ];
329 script = ''
330 export MPD_PASSWORD=$(cat ${config.secrets.fullPaths."mpd"})
331 ${pkgs.ympd}/bin/ympd --host ${ympd.config.host} --port ${toString ympd.config.port} --webport ${ympd.config.webPort} --user nobody
332 '';
333 };
334 tt-rss = {
335 description = "Tiny Tiny RSS feeds update daemon";
336 serviceConfig = {
337 User = "wwwrun";
338 ExecStart = "${pkgs.php72}/bin/php ${ttrss.webRoot}/update.php --daemon";
339 StandardOutput = "syslog";
340 StandardError = "syslog";
341 PermissionsStartOnly = true;
342 };
343
344 wantedBy = [ "multi-user.target" ];
345 requires = ["postgresql.service"];
346 after = ["network.target" "postgresql.service"];
347 };
348 };
349
350 services.filesWatcher.ympd = {
351 restart = true;
352 paths = [ config.secrets.fullPaths."mpd" ];
353 };
354
355 services.phpfpm.pools = {
356 tools = {
357 user = "wwwrun";
358 group = "wwwrun";
359 settings = {
360 "listen.owner" = "wwwrun";
361 "listen.group" = "wwwrun";
362 "pm" = "dynamic";
363 "pm.max_children" = "60";
364 "pm.start_servers" = "2";
365 "pm.min_spare_servers" = "1";
366 "pm.max_spare_servers" = "10";
367
368 "php_admin_value[session.save_handler]" = "redis";
369 "php_admin_value[session.save_path]" = "'unix:///run/redis-php-sessions/redis.sock?persistent=1&prefix=Tools:Tools:'";
370 # Needed to avoid clashes in browser cookies (same domain)
371 "php_value[session.name]" = "ToolsPHPSESSID";
372 "php_admin_value[open_basedir]" = builtins.concatStringsSep ":" [
373 "/run/wrappers/bin/sendmail" landing "/tmp"
374 config.secrets.fullPaths."webapps/webhooks"
375 "${webhooks-bin-env}/bin"
376 ];
377 };
378 phpEnv = {
379 CONTACT_EMAIL = config.myEnv.tools.contact;
380 };
381 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [ all.redis ]);
382 };
383 devtools = {
384 user = "wwwrun";
385 group = "wwwrun";
386 settings = {
387 "listen.owner" = "wwwrun";
388 "listen.group" = "wwwrun";
389 "pm" = "dynamic";
390 "pm.max_children" = "60";
391 "pm.start_servers" = "2";
392 "pm.min_spare_servers" = "1";
393 "pm.max_spare_servers" = "10";
394
395 "php_admin_value[session.save_handler]" = "redis";
396 "php_admin_value[session.save_path]" = "'unix:///run/redis-php-sessions/redis.sock?persistent=1&prefix=Tools:Devtools:'";
397 "php_admin_value[open_basedir]" = "/run/wrappers/bin/sendmail:/var/lib/ftp/immae/devtools:/tmp";
398 };
399 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.mysqli all.sqlite3 all.redis all.apcu all.opcache ]);
400 };
401 adminer = adminer.phpFpm;
402 ttrss = {
403 user = "wwwrun";
404 group = "wwwrun";
405 settings = ttrss.phpFpm.pool;
406 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
407 };
408 wallabag = {
409 user = "wwwrun";
410 group = "wwwrun";
411 settings = wallabag.phpFpm.pool;
412 phpPackage = pkgs.php73.withExtensions({ enabled, all }: enabled ++ [all.tidy all.redis]);
413 };
414 yourls = {
415 user = "wwwrun";
416 group = "wwwrun";
417 settings = yourls.phpFpm.pool;
418 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
419 };
420 rompr = {
421 user = "wwwrun";
422 group = "wwwrun";
423 settings = rompr.phpFpm.pool;
424 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
425 };
426 shaarli = {
427 user = "wwwrun";
428 group = "wwwrun";
429 settings = shaarli.phpFpm.pool;
430 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
431 };
432 dmarc-reports = {
433 user = "wwwrun";
434 group = "wwwrun";
435 settings = dmarc-reports.phpFpm.pool;
436 phpEnv = dmarc-reports.phpFpm.phpEnv;
437 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
438 };
439 dokuwiki = {
440 user = "wwwrun";
441 group = "wwwrun";
442 settings = dokuwiki.phpFpm.pool;
443 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
444 };
445 phpbb = {
446 user = "wwwrun";
447 group = "wwwrun";
448 settings = phpbb.phpFpm.pool;
449 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
450 };
451 ldap = {
452 user = "wwwrun";
453 group = "wwwrun";
454 settings = ldap.phpFpm.pool;
455 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
456 };
457 kanboard = {
458 user = "wwwrun";
459 group = "wwwrun";
460 settings = kanboard.phpFpm.pool;
461 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
462 };
463 grocy = {
464 user = "wwwrun";
465 group = "wwwrun";
466 settings = grocy.phpFpm.pool;
467 phpPackage = pkgs.php72.withExtensions({ enabled, all }: enabled ++ [all.redis]);
468 };
469 };
470
471 system.activationScripts = {
472 grocy = grocy.activationScript;
473 ttrss = ttrss.activationScript;
474 wallabag = wallabag.activationScript;
475 rompr = rompr.activationScript;
476 shaarli = shaarli.activationScript;
477 dokuwiki = dokuwiki.activationScript;
478 phpbb = phpbb.activationScript;
479 kanboard = kanboard.activationScript;
480 };
481
482 services.websites.env.tools.watchPaths = [
483 config.secrets.fullPaths."webapps/tools-shaarli"
484 ];
485 services.filesWatcher.phpfpm-wallabag = {
486 restart = true;
487 paths = [ config.secrets.fullPaths."webapps/tools-wallabag" ];
488 };
489
490 };
491 }
492