1 { lib, config, pkgs, ... }:
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";
9 options.services.postfixadmin = {
10 enable = lib.mkOption {
11 type = lib.types.bool;
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.
22 hostName = lib.mkOption {
24 example = "postfixadmin.example.com";
25 description = "Hostname to use for the nginx vhost";
28 adminEmail = lib.mkOption {
30 example = "postmaster@example.com";
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.
38 setupPasswordFile = lib.mkOption {
39 type = lib.types.path;
41 Password file for the admin.
42 Generate with `php -r "echo password_hash('some password here', PASSWORD_DEFAULT);"`
47 username = lib.mkOption {
49 default = "postfixadmin";
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.
57 default = "localhost";
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
65 passwordFile = lib.mkOption {
66 type = lib.types.path;
67 description = "Password file for the postgresql connection. Must be readable by user `nginx`.";
69 dbname = lib.mkOption {
71 default = "postfixadmin";
72 description = "Name of the postgresql database";
76 extraConfig = lib.mkOption {
77 type = lib.types.lines;
79 description = "Extra configuration for the postfixadmin instance, see postfixadmin's config.inc.php for available options.";
83 config = lib.mkIf cfg.enable {
84 environment.etc."postfixadmin/config.local.php".text = ''
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;
99 systemd.tmpfiles.settings."10-postfixadmin"."/var/cache/postfixadmin/templates_c".d = {
109 forceSSL = lib.mkDefault true;
110 enableACME = lib.mkDefault true;
112 root = "${pkgs.postfixadmin}/public";
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;
127 services.postgresql = lib.mkIf localDB {
130 name = cfg.database.username;
133 # The postgresql module doesn't currently support concepts like
134 # objects owners and extensions; for now we tack on what's needed
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" ];
148 psql --port=${toString pgsql.port} "$@"
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..."
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}"
166 User = pgsql.superUser;
168 RemainAfterExit = true;
172 users.users.${user} = lib.mkIf localDB {
177 users.groups.${user} = lib.mkIf localDB {};
179 services.phpfpm.pools.postfixadmin = {
181 phpPackage = pkgs.php81;
186 settings = lib.mapAttrs (name: lib.mkDefault) {
187 "listen.owner" = "nginx";
188 "listen.group" = "nginx";
189 "listen.mode" = "0660";
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;