diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
index b422c3cf058b..65abc8ac4820 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
@@ -199,6 +199,14 @@
services.xserver.displayManager.sx
+
+
+ postfixadmin,
+ a web based virtual user administration interface for Postfix
+ mail servers. Available as
+ postfixadmin.
+
+
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md
index 548008fe24bc..ae6ccf932987 100644
--- a/nixos/doc/manual/release-notes/rl-2111.section.md
+++ b/nixos/doc/manual/release-notes/rl-2111.section.md
@@ -60,6 +60,8 @@ subsonic-compatible api. Available as [navidrome](#opt-services.navidrome.enable
- [sx](https://github.com/earnestly/sx), a simple alternative to both xinit and startx for starting a Xorg server. Available as [services.xserver.displayManager.sx](#opt-services.xserver.displayManager.sx.enable)
+- [postfixadmin](https://postfixadmin.sourceforge.io/), a web based virtual user administration interface for Postfix mail servers. Available as [postfixadmin](#opt-services.postfixadmin.enable).
+
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
- The `paperless` module and package have been removed. All users should migrate to the
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 2fbab4a68739..f07de862eacd 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -460,6 +460,7 @@
./services/mail/opensmtpd.nix
./services/mail/pfix-srsd.nix
./services/mail/postfix.nix
+ ./services/mail/postfixadmin.nix
./services/mail/postsrsd.nix
./services/mail/postgrey.nix
./services/mail/spamassassin.nix
diff --git a/nixos/modules/services/mail/postfixadmin.nix b/nixos/modules/services/mail/postfixadmin.nix
new file mode 100644
index 000000000000..f5c8efb3076c
--- /dev/null
+++ b/nixos/modules/services/mail/postfixadmin.nix
@@ -0,0 +1,199 @@
+{ lib, config, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.postfixadmin;
+ fpm = config.services.phpfpm.pools.postfixadmin;
+ localDB = cfg.database.host == "localhost";
+ user = if localDB then cfg.database.username else "nginx";
+in
+{
+ options.services.postfixadmin = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable postfixadmin.
+
+ Also enables nginx virtual host management.
+ Further nginx configuration can be done by adapting services.nginx.virtualHosts.<name>.
+ See for further information.
+ '';
+ };
+
+ hostName = mkOption {
+ type = types.str;
+ example = "postfixadmin.example.com";
+ description = "Hostname to use for the nginx vhost";
+ };
+
+ adminEmail = mkOption {
+ type = types.str;
+ example = "postmaster@example.com";
+ description = ''
+ Defines the Site Admin's email address.
+ This will be used to send emails from to create mailboxes and
+ from Send Email / Broadcast message pages.
+ '';
+ };
+
+ setupPasswordFile = mkOption {
+ type = types.path;
+ description = ''
+ Password file for the admin.
+ Generate with php -r "echo password_hash('some password here', PASSWORD_DEFAULT);"
+ '';
+ };
+
+ database = {
+ username = mkOption {
+ type = types.str;
+ default = "postfixadmin";
+ description = ''
+ Username for the postgresql connection.
+ If database.host is set to localhost, a unix user and group of the same name will be created as well.
+ '';
+ };
+ host = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = ''
+ Host of the postgresql server. If this is not set to
+ localhost, you have to create the
+ postgresql user and database yourself, with appropriate
+ permissions.
+ '';
+ };
+ passwordFile = mkOption {
+ type = types.path;
+ description = "Password file for the postgresql connection. Must be readable by user nginx.";
+ };
+ dbname = mkOption {
+ type = types.str;
+ default = "postfixadmin";
+ description = "Name of the postgresql database";
+ };
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = "Extra configuration for the postfixadmin instance, see postfixadmin's config.inc.php for available options.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.etc."postfixadmin/config.local.php".text = ''
+