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