aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
committerMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
commitc4625b175f8200f643fd6e11010932ea44c78433 (patch)
treebce3f89888c8ac3991fa5569a878a9eab6801ccc /infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix
parent49f735974dd103039ddc4cb576bb76555164a9e7 (diff)
parentd661aa56a8843e991261510c1bb28fdc2f6975ae (diff)
Add 'infra/libkookie/' from commit 'd661aa56a8843e991261510c1bb28fdc2f6975ae'
git-subtree-dir: infra/libkookie git-subtree-mainline: 49f735974dd103039ddc4cb576bb76555164a9e7 git-subtree-split: d661aa56a8843e991261510c1bb28fdc2f6975ae
Diffstat (limited to 'infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix')
-rw-r--r--infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix243
1 files changed, 243 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix b/infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix
new file mode 100644
index 000000000000..a0bbab64985b
--- /dev/null
+++ b/infra/libkookie/nixpkgs/nixos/modules/services/mail/roundcube.nix
@@ -0,0 +1,243 @@
+{ lib, config, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.roundcube;
+ fpm = config.services.phpfpm.pools.roundcube;
+ localDB = cfg.database.host == "localhost";
+ user = cfg.database.username;
+ phpWithPspell = pkgs.php.withExtensions ({ enabled, all }: [ all.pspell ] ++ enabled);
+in
+{
+ options.services.roundcube = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable roundcube.
+
+ Also enables nginx virtual host management.
+ Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
+ See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
+ '';
+ };
+
+ hostName = mkOption {
+ type = types.str;
+ example = "webmail.example.com";
+ description = "Hostname to use for the nginx vhost";
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.roundcube;
+
+ example = literalExample ''
+ roundcube.withPlugins (plugins: [ plugins.persistent_login ])
+ '';
+
+ description = ''
+ The package which contains roundcube's sources. Can be overriden to create
+ an environment which contains roundcube and third-party plugins.
+ '';
+ };
+
+ database = {
+ username = mkOption {
+ type = types.str;
+ default = "roundcube";
+ description = ''
+ Username for the postgresql connection.
+ If <literal>database.host</literal> is set to <literal>localhost</literal>, 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
+ <literal>localhost</literal>, you have to create the
+ postgresql user and database yourself, with appropriate
+ permissions.
+ '';
+ };
+ password = mkOption {
+ type = types.str;
+ description = "Password for the postgresql connection. Do not use: the password will be stored world readable in the store; use <literal>passwordFile</literal> instead.";
+ default = "";
+ };
+ passwordFile = mkOption {
+ type = types.str;
+ description = "Password file for the postgresql connection. Must be readable by user <literal>nginx</literal>. Ignored if <literal>database.host</literal> is set to <literal>localhost</literal>, as peer authentication will be used.";
+ };
+ dbname = mkOption {
+ type = types.str;
+ default = "roundcube";
+ description = "Name of the postgresql database";
+ };
+ };
+
+ plugins = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ List of roundcube plugins to enable. Currently, only those directly shipped with Roundcube are supported.
+ '';
+ };
+
+ dicts = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ example = literalExample "with pkgs.aspellDicts; [ en fr de ]";
+ description = ''
+ List of aspell dictionnaries for spell checking. If empty, spell checking is disabled.
+ '';
+ };
+
+ maxAttachmentSize = mkOption {
+ type = types.int;
+ default = 18;
+ description = ''
+ The maximum attachment size in MB.
+
+ Note: Since roundcube only uses 70% of max upload values configured in php
+ 30% is added automatically to <xref linkend="opt-services.roundcube.maxAttachmentSize"/>.
+ '';
+ apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.3)}M";
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = "Extra configuration for roundcube webmail instance";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ # backward compatibility: if password is set but not passwordFile, make one.
+ services.roundcube.database.passwordFile = mkIf (!localDB && cfg.database.password != "") (mkDefault ("${pkgs.writeText "roundcube-password" cfg.database.password}"));
+ warnings = lib.optional (!localDB && cfg.database.password != "") "services.roundcube.database.password is deprecated and insecure; use services.roundcube.database.passwordFile instead";
+
+ environment.etc."roundcube/config.inc.php".text = ''
+ <?php
+
+ ${lib.optionalString (!localDB) "$password = file_get_contents('${cfg.database.passwordFile}');"}
+
+ $config = array();
+ $config['db_dsnw'] = 'pgsql://${cfg.database.username}${lib.optionalString (!localDB) ":' . $password . '"}@${if localDB then "unix(/run/postgresql)" else cfg.database.host}/${cfg.database.dbname}';
+ $config['log_driver'] = 'syslog';
+ $config['max_message_size'] = '${cfg.maxAttachmentSize}';
+ $config['plugins'] = [${concatMapStringsSep "," (p: "'${p}'") cfg.plugins}];
+ $config['des_key'] = file_get_contents('/var/lib/roundcube/des_key');
+ $config['mime_types'] = '${pkgs.nginx}/conf/mime.types';
+ $config['enable_spellcheck'] = ${if cfg.dicts == [] then "false" else "true"};
+ # by default, spellchecking uses a third-party cloud services
+ $config['spellcheck_engine'] = 'pspell';
+ $config['spellcheck_languages'] = array(${lib.concatMapStringsSep ", " (dict: let p = builtins.parseDrvName dict.shortName; in "'${p.name}' => '${dict.fullName}'") cfg.dicts});
+
+ ${cfg.extraConfig}
+ '';
+
+ services.nginx = {
+ enable = true;
+ virtualHosts = {
+ ${cfg.hostName} = {
+ forceSSL = mkDefault true;
+ enableACME = mkDefault true;
+ locations."/" = {
+ root = cfg.package;
+ index = "index.php";
+ extraConfig = ''
+ location ~* \.php$ {
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass unix:${fpm.socket};
+ include ${pkgs.nginx}/conf/fastcgi_params;
+ include ${pkgs.nginx}/conf/fastcgi.conf;
+ }
+ '';
+ };
+ };
+ };
+ };
+
+ services.postgresql = mkIf localDB {
+ enable = true;
+ ensureDatabases = [ cfg.database.dbname ];
+ ensureUsers = [ {
+ name = cfg.database.username;
+ ensurePermissions = {
+ "DATABASE ${cfg.database.username}" = "ALL PRIVILEGES";
+ };
+ } ];
+ };
+
+ users.users.${user} = mkIf localDB {
+ group = user;
+ isSystemUser = true;
+ createHome = false;
+ };
+ users.groups.${user} = mkIf localDB {};
+
+ services.phpfpm.pools.roundcube = {
+ user = if localDB then user else "nginx";
+ phpOptions = ''
+ error_log = 'stderr'
+ log_errors = on
+ post_max_size = ${cfg.maxAttachmentSize}
+ upload_max_filesize = ${cfg.maxAttachmentSize}
+ '';
+ settings = mapAttrs (name: mkDefault) {
+ "listen.owner" = "nginx";
+ "listen.group" = "nginx";
+ "listen.mode" = "0660";
+ "pm" = "dynamic";
+ "pm.max_children" = 75;
+ "pm.start_servers" = 2;
+ "pm.min_spare_servers" = 1;
+ "pm.max_spare_servers" = 20;
+ "pm.max_requests" = 500;
+ "catch_workers_output" = true;
+ };
+ phpPackage = phpWithPspell;
+ phpEnv.ASPELL_CONF = "dict-dir ${pkgs.aspellWithDicts (_: cfg.dicts)}/lib/aspell";
+ };
+ systemd.services.phpfpm-roundcube.after = [ "roundcube-setup.service" ];
+
+ systemd.services.roundcube-setup = mkMerge [
+ (mkIf (cfg.database.host == "localhost") {
+ requires = [ "postgresql.service" ];
+ after = [ "postgresql.service" ];
+ path = [ config.services.postgresql.package ];
+ })
+ {
+ wantedBy = [ "multi-user.target" ];
+ script = let
+ psql = "${lib.optionalString (!localDB) "PGPASSFILE=${cfg.database.passwordFile}"} ${pkgs.postgresql}/bin/psql ${lib.optionalString (!localDB) "-h ${cfg.database.host} -U ${cfg.database.username} "} ${cfg.database.dbname}";
+ in
+ ''
+ version="$(${psql} -t <<< "select value from system where name = 'roundcube-version';" || true)"
+ if ! (grep -E '[a-zA-Z0-9]' <<< "$version"); then
+ ${psql} -f ${cfg.package}/SQL/postgres.initial.sql
+ fi
+
+ if [ ! -f /var/lib/roundcube/des_key ]; then
+ base64 /dev/urandom | head -c 24 > /var/lib/roundcube/des_key;
+ # we need to log out everyone in case change the des_key
+ # from the default when upgrading from nixos 19.09
+ ${psql} <<< 'TRUNCATE TABLE session;'
+ fi
+
+ ${phpWithPspell}/bin/php ${cfg.package}/bin/update.sh
+ '';
+ serviceConfig = {
+ Type = "oneshot";
+ StateDirectory = "roundcube";
+ User = if localDB then user else "nginx";
+ # so that the des_key is not world readable
+ StateDirectoryMode = "0700";
+ };
+ }
+ ];
+ };
+}