grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-apps / engelsystem.nix
blobb32e5e05953f78fc6f25d7bdf288d47a0aef655e
2   config,
3   lib,
4   pkgs,
5   utils,
6   ...
7 }:
9 let
10   inherit (lib)
11     mkDefault
12     mkEnableOption
13     mkIf
14     mkOption
15     mkPackageOption
16     mkRenamedOptionModule
17     types
18   ;
20   cfg = config.services.engelsystem;
21 in {
22   imports = [
23     (mkRenamedOptionModule [ "services" "engelsystem" "config" ] [ "services" "engelsystem" "settings" ])
24   ];
26   options.services.engelsystem = {
27     enable = mkEnableOption "engelsystem, an online tool for coordinating volunteers and shifts on large events";
29     package = mkPackageOption pkgs "engelsystem" { };
31     domain = mkOption {
32       type = types.str;
33       example = "engelsystem.example.com";
34       description = "Domain to serve on.";
35     };
37     createDatabase = mkOption {
38       type = types.bool;
39       default = true;
40       description = ''
41         Whether to create a local database automatically.
42         This will override every database setting in {option}`services.engelsystem.config`.
43       '';
44     };
46     settings = mkOption {
47       type = types.attrs;
48       default = {
49         database = {
50           host = "localhost";
51           database = "engelsystem";
52           username = "engelsystem";
53         };
54       };
55       example = {
56         maintenance = false;
57         database = {
58           host = "database.example.com";
59           database = "engelsystem";
60           username = "engelsystem";
61           password._secret = "/var/keys/engelsystem/database";
62         };
63         email = {
64           driver = "smtp";
65           host = "smtp.example.com";
66           port = 587;
67           from.address = "engelsystem@example.com";
68           from.name = "example engelsystem";
69           encryption = "tls";
70           username = "engelsystem@example.com";
71           password._secret = "/var/keys/engelsystem/mail";
72         };
73         autoarrive = true;
74         min_password_length = 6;
75         default_locale = "de_DE";
76       };
77       description = ''
78         Options to be added to config.php, as a nix attribute set. Options containing secret data
79         should be set to an attribute set containing the attribute _secret - a string pointing to a
80         file containing the value the option should be set to. See the example to get a better
81         picture of this: in the resulting config.php file, the email.password key will be set to
82         the contents of the /var/keys/engelsystem/mail file.
84         See https://engelsystem.de/doc/admin/configuration/ for available options.
86         Note that the admin user login credentials cannot be set here - they always default to
87         admin:asdfasdf. Log in and change them immediately.
88       '';
89     };
90   };
92   config = mkIf cfg.enable {
93     # create database
94     services.mysql = mkIf cfg.createDatabase {
95       enable = true;
96       package = mkDefault pkgs.mariadb;
97       ensureUsers = [{
98         name = "engelsystem";
99         ensurePermissions = { "engelsystem.*" = "ALL PRIVILEGES"; };
100       }];
101       ensureDatabases = [ "engelsystem" ];
102     };
104     environment.etc."engelsystem/config.php".source =
105       pkgs.writeText "config.php" ''
106         <?php
107         return json_decode(file_get_contents("/var/lib/engelsystem/config.json"), true);
108       '';
110     services.phpfpm.pools.engelsystem = {
111       user = "engelsystem";
112       settings = {
113         "listen.owner" = config.services.nginx.user;
114         "pm" = "dynamic";
115         "pm.max_children" = 32;
116         "pm.max_requests" = 500;
117         "pm.start_servers" = 2;
118         "pm.min_spare_servers" = 2;
119         "pm.max_spare_servers" = 5;
120         "php_admin_value[error_log]" = "stderr";
121         "php_admin_flag[log_errors]" = true;
122         "catch_workers_output" = true;
123       };
124     };
126     services.nginx = {
127       enable = true;
128       virtualHosts."${cfg.domain}".locations = {
129         "/" = {
130           root = "${cfg.package}/share/engelsystem/public";
131           extraConfig = ''
132             index index.php;
133             try_files $uri $uri/ /index.php?$args;
134             autoindex off;
135           '';
136         };
137         "~ \\.php$" = {
138           root = "${cfg.package}/share/engelsystem/public";
139           extraConfig = ''
140             fastcgi_pass unix:${config.services.phpfpm.pools.engelsystem.socket};
141             fastcgi_index index.php;
142             fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
143             include ${config.services.nginx.package}/conf/fastcgi_params;
144             include ${config.services.nginx.package}/conf/fastcgi.conf;
145           '';
146         };
147       };
148     };
150     systemd.services."engelsystem-init" = {
151       wantedBy = [ "multi-user.target" ];
152       serviceConfig = { Type = "oneshot"; };
153       script =
154         let
155           genConfigScript = pkgs.writeScript "engelsystem-gen-config.sh"
156             (utils.genJqSecretsReplacementSnippet cfg.settings "config.json");
157         in ''
158           umask 077
159           mkdir -p /var/lib/engelsystem/storage/app
160           mkdir -p /var/lib/engelsystem/storage/cache/views
161           cd /var/lib/engelsystem
162           ${genConfigScript}
163           chmod 400 config.json
164           chown -R engelsystem .
165       '';
166     };
167     systemd.services."engelsystem-migrate" = {
168       wantedBy = [ "multi-user.target" ];
169       serviceConfig = {
170         Type = "oneshot";
171         User = "engelsystem";
172         Group = "engelsystem";
173       };
174       script = ''
175         versionFile="/var/lib/engelsystem/.version"
176         version=$(cat "$versionFile" 2>/dev/null || echo 0)
178         if [[ $version != ${cfg.package.version} ]]; then
179           # prune template cache between releases
180           rm -rfv /var/lib/engelsystem/storage/cache/*
182           ${cfg.package}/bin/migrate
184           echo ${cfg.package.version} > "$versionFile"
185         fi
186       '';
187       after = [ "engelsystem-init.service" "mysql.service" ];
188     };
189     systemd.services."phpfpm-engelsystem".after =
190       [ "engelsystem-migrate.service" ];
192     users.users.engelsystem = {
193       isSystemUser = true;
194       createHome = true;
195       home = "/var/lib/engelsystem/storage";
196       group = "engelsystem";
197     };
198     users.groups.engelsystem = { };
199   };