vuls: init at 0.27.0 (#348530)
[NixPkgs.git] / nixos / modules / services / mail / postfixadmin.nix
blob7523fa4930abf0e2a9a2928ee515cf28e2553491
1 { lib, config, pkgs, ... }:
2 let
3   cfg = config.services.postfixadmin;
4   fpm = config.services.phpfpm.pools.postfixadmin;
5   localDB = cfg.database.host == "localhost";
6   user = if localDB then cfg.database.username else "nginx";
7 in
9   options.services.postfixadmin = {
10     enable = lib.mkOption {
11       type = lib.types.bool;
12       default = false;
13       description = ''
14         Whether to enable postfixadmin.
16         Also enables nginx virtual host management.
17         Further nginx configuration can be done by adapting `services.nginx.virtualHosts.<name>`.
18         See [](#opt-services.nginx.virtualHosts) for further information.
19       '';
20     };
22     hostName = lib.mkOption {
23       type = lib.types.str;
24       example = "postfixadmin.example.com";
25       description = "Hostname to use for the nginx vhost";
26     };
28     adminEmail = lib.mkOption {
29       type = lib.types.str;
30       example = "postmaster@example.com";
31       description = ''
32         Defines the Site Admin's email address.
33         This will be used to send emails from to create mailboxes and
34         from Send Email / Broadcast message pages.
35       '';
36     };
38     setupPasswordFile = lib.mkOption {
39       type = lib.types.path;
40       description = ''
41         Password file for the admin.
42         Generate with `php -r "echo password_hash('some password here', PASSWORD_DEFAULT);"`
43       '';
44     };
46     database = {
47       username = lib.mkOption {
48         type = lib.types.str;
49         default = "postfixadmin";
50         description = ''
51           Username for the postgresql connection.
52           If `database.host` is set to `localhost`, a unix user and group of the same name will be created as well.
53         '';
54       };
55       host = lib.mkOption {
56         type = lib.types.str;
57         default = "localhost";
58         description = ''
59           Host of the postgresql server. If this is not set to
60           `localhost`, you have to create the
61           postgresql user and database yourself, with appropriate
62           permissions.
63         '';
64       };
65       passwordFile = lib.mkOption {
66         type = lib.types.path;
67         description = "Password file for the postgresql connection. Must be readable by user `nginx`.";
68       };
69       dbname = lib.mkOption {
70         type = lib.types.str;
71         default = "postfixadmin";
72         description = "Name of the postgresql database";
73       };
74     };
76     extraConfig = lib.mkOption {
77       type = lib.types.lines;
78       default = "";
79       description = "Extra configuration for the postfixadmin instance, see postfixadmin's config.inc.php for available options.";
80     };
81   };
83   config = lib.mkIf cfg.enable {
84     environment.etc."postfixadmin/config.local.php".text = ''
85       <?php
87       $CONF['setup_password'] = file_get_contents('${cfg.setupPasswordFile}');
89       $CONF['database_type'] = 'pgsql';
90       $CONF['database_host'] = ${if localDB then "null" else "'${cfg.database.host}'"};
91       ${lib.optionalString localDB "$CONF['database_user'] = '${cfg.database.username}';"}
92       $CONF['database_password'] = ${if localDB then "'dummy'" else "file_get_contents('${cfg.database.passwordFile}')"};
93       $CONF['database_name'] = '${cfg.database.dbname}';
94       $CONF['configured'] = true;
96       ${cfg.extraConfig}
97     '';
99     systemd.tmpfiles.settings."10-postfixadmin"."/var/cache/postfixadmin/templates_c".d = {
100       inherit user;
101       group = user;
102       mode = "700";
103     };
105     services.nginx = {
106       enable = true;
107       virtualHosts = {
108         ${cfg.hostName} = {
109           forceSSL = lib.mkDefault true;
110           enableACME = lib.mkDefault true;
111           locations."/" = {
112             root = "${pkgs.postfixadmin}/public";
113             index = "index.php";
114             extraConfig = ''
115               location ~* \.php$ {
116                 fastcgi_split_path_info ^(.+\.php)(/.+)$;
117                 fastcgi_pass unix:${fpm.socket};
118                 include ${config.services.nginx.package}/conf/fastcgi_params;
119                 include ${pkgs.nginx}/conf/fastcgi.conf;
120               }
121             '';
122           };
123         };
124       };
125     };
127     services.postgresql = lib.mkIf localDB {
128       enable = true;
129       ensureUsers = [ {
130         name = cfg.database.username;
131       } ];
132     };
133     # The postgresql module doesn't currently support concepts like
134     # objects owners and extensions; for now we tack on what's needed
135     # here.
136     systemd.services.postfixadmin-postgres = let pgsql = config.services.postgresql; in lib.mkIf localDB {
137       after = [ "postgresql.service" ];
138       bindsTo = [ "postgresql.service" ];
139       wantedBy = [ "multi-user.target" ];
140       path = [
141         pgsql.package
142         pkgs.util-linux
143       ];
144       script = ''
145         set -eu
147         PSQL() {
148             psql --port=${toString pgsql.port} "$@"
149         }
151         PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${cfg.database.dbname}'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "${cfg.database.dbname}" OWNER "${cfg.database.username}"'
152         current_owner=$(PSQL -tAc "SELECT pg_catalog.pg_get_userbyid(datdba) FROM pg_catalog.pg_database WHERE datname = '${cfg.database.dbname}'")
153         if [[ "$current_owner" != "${cfg.database.username}" ]]; then
154             PSQL -tAc 'ALTER DATABASE "${cfg.database.dbname}" OWNER TO "${cfg.database.username}"'
155             if [[ -e "${config.services.postgresql.dataDir}/.reassigning_${cfg.database.dbname}" ]]; then
156                 echo "Reassigning ownership of database ${cfg.database.dbname} to user ${cfg.database.username} failed on last boot. Failing..."
157                 exit 1
158             fi
159             touch "${config.services.postgresql.dataDir}/.reassigning_${cfg.database.dbname}"
160             PSQL "${cfg.database.dbname}" -tAc "REASSIGN OWNED BY \"$current_owner\" TO \"${cfg.database.username}\""
161             rm "${config.services.postgresql.dataDir}/.reassigning_${cfg.database.dbname}"
162         fi
163       '';
165       serviceConfig = {
166         User = pgsql.superUser;
167         Type = "oneshot";
168         RemainAfterExit = true;
169       };
170     };
172     users.users.${user} = lib.mkIf localDB {
173       group = user;
174       isSystemUser = true;
175       createHome = false;
176     };
177     users.groups.${user} = lib.mkIf localDB {};
179     services.phpfpm.pools.postfixadmin = {
180       user = user;
181       phpPackage = pkgs.php81;
182       phpOptions = ''
183         error_log = 'stderr'
184         log_errors = on
185       '';
186       settings = lib.mapAttrs (name: lib.mkDefault) {
187         "listen.owner" = "nginx";
188         "listen.group" = "nginx";
189         "listen.mode" = "0660";
190         "pm" = "dynamic";
191         "pm.max_children" = 75;
192         "pm.start_servers" = 2;
193         "pm.min_spare_servers" = 1;
194         "pm.max_spare_servers" = 20;
195         "pm.max_requests" = 500;
196         "catch_workers_output" = true;
197       };
198     };
199   };