Migrate the mail config to the nixos module
This commit is contained in:
parent
ad0ab2e843
commit
5dcbb4e2dc
|
@ -10,7 +10,6 @@
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./acme.nix
|
./acme.nix
|
||||||
./sshusers.nix
|
./sshusers.nix
|
||||||
./variables.nix
|
|
||||||
./mailserver.nix
|
./mailserver.nix
|
||||||
./borgbackup.nix
|
./borgbackup.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
|
|
164
dovecot.nix
164
dovecot.nix
|
@ -1,164 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
dovecotSQL = pkgs.writeText "dovecot-sql.conf" ''
|
|
||||||
driver = sqlite
|
|
||||||
connect = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
password_query = SELECT username AS user, password FROM mailbox WHERE username = '%Lu' AND active='1'
|
|
||||||
user_query = SELECT username AS user FROM mailbox WHERE username = '%Lu' AND active='1'
|
|
||||||
'';
|
|
||||||
dovecotConfSSL = pkgs.writeText "dovecot.conf" ''
|
|
||||||
${lib.optionalString (config.variables.useSSL) ''
|
|
||||||
ssl = yes
|
|
||||||
ssl_cert = </var/lib/acme/dovecot2.${config.variables.myFQDN}/fullchain.pem
|
|
||||||
ssl_key = </var/lib/acme/dovecot2.${config.variables.myFQDN}/key.pem
|
|
||||||
''
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
dovecotConf = pkgs.writeText "dovecot.conf" ''
|
|
||||||
sendmail_path = /run/wrappers/bin/sendmail
|
|
||||||
default_internal_user = dovecot2
|
|
||||||
default_internal_group = dovecot2
|
|
||||||
protocols = imap lmtp pop3 sieve
|
|
||||||
|
|
||||||
# commented out due to a dovecot but in the most recent release
|
|
||||||
#$ {lib.optionalString (config.variables.useSSL) '#'
|
|
||||||
# ssl = yes
|
|
||||||
# ssl_cert = </var/lib/acme/dovecot2.${config.variables.myFQDN}/fullchain.pem
|
|
||||||
# ssl_key = </var/lib/acme/dovecot2.${config.variables.myFQDN}/key.pem
|
|
||||||
# '#'
|
|
||||||
#}
|
|
||||||
!include_try /var/lib/dovecot/ssl-keys.conf
|
|
||||||
|
|
||||||
disable_plaintext_auth = yes
|
|
||||||
auth_mechanisms = plain login
|
|
||||||
|
|
||||||
userdb {
|
|
||||||
driver = sql
|
|
||||||
args = ${dovecotSQL}
|
|
||||||
}
|
|
||||||
passdb {
|
|
||||||
driver = sql
|
|
||||||
args = ${dovecotSQL}
|
|
||||||
}
|
|
||||||
mail_home = ${config.variables.vmailBaseDir}/%Lu/
|
|
||||||
mail_location = maildir:${config.variables.vmailBaseDir}/%Lu/Maildir
|
|
||||||
mail_uid = ${toString config.variables.vmailUID}
|
|
||||||
mail_gid = ${toString config.variables.vmailGID}
|
|
||||||
|
|
||||||
service auth {
|
|
||||||
unix_listener ${config.variables.dovecotAuthSocket} {
|
|
||||||
user = ${config.services.postfix.user}
|
|
||||||
group = ${config.services.postfix.group}
|
|
||||||
mode = 0600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service lmtp {
|
|
||||||
unix_listener ${config.variables.dovecotLmtpSocket} {
|
|
||||||
user = ${config.services.postfix.user}
|
|
||||||
group = ${config.services.postfix.group}
|
|
||||||
mode = 0600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service stats {
|
|
||||||
unix_listener stats-reader {
|
|
||||||
user = dovecot2
|
|
||||||
group = dovecot2
|
|
||||||
mode = 0660
|
|
||||||
}
|
|
||||||
unix_listener stats-writer {
|
|
||||||
user = dovecot2
|
|
||||||
group = dovecot2
|
|
||||||
mode = 0660
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol lmtp {
|
|
||||||
mail_plugins = sieve
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol imap {
|
|
||||||
mail_plugins = $mail_plugins imap_sieve
|
|
||||||
}
|
|
||||||
imap_idle_notify_interval = 29 mins
|
|
||||||
|
|
||||||
namespace inbox {
|
|
||||||
inbox = yes
|
|
||||||
location =
|
|
||||||
mailbox Drafts {
|
|
||||||
special_use = \Drafts
|
|
||||||
auto = subscribe
|
|
||||||
}
|
|
||||||
mailbox Junk {
|
|
||||||
special_use = \Junk
|
|
||||||
auto = subscribe
|
|
||||||
}
|
|
||||||
mailbox Sent {
|
|
||||||
special_use = \Sent
|
|
||||||
auto = subscribe
|
|
||||||
}
|
|
||||||
mailbox Trash {
|
|
||||||
special_use = \Trash
|
|
||||||
auto = subscribe
|
|
||||||
}
|
|
||||||
mailbox Archive {
|
|
||||||
special_use = \Archive
|
|
||||||
auto = subscribe
|
|
||||||
}
|
|
||||||
prefix =
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin {
|
|
||||||
sieve_after = ${(pkgs.callPackage ./sieve-after.nix {}) }
|
|
||||||
sieve_plugins = sieve_imapsieve sieve_extprograms
|
|
||||||
# From elsewhere to Spam folder
|
|
||||||
imapsieve_mailbox1_name = Junk
|
|
||||||
imapsieve_mailbox1_causes = COPY
|
|
||||||
imapsieve_mailbox1_before = file:${(pkgs.callPackage ./sieve-report-spam-ham.nix {})}/report-spam.sieve
|
|
||||||
# From Spam folder to elsewhere
|
|
||||||
imapsieve_mailbox2_name = *
|
|
||||||
imapsieve_mailbox2_from = Junk
|
|
||||||
imapsieve_mailbox2_causes = COPY
|
|
||||||
imapsieve_mailbox2_before = file:${(pkgs.callPackage ./sieve-report-spam-ham.nix {})}/report-ham.sieve
|
|
||||||
sieve_pipe_bin_dir = ${(pkgs.callPackage ./sieve-pipe-bin-dir.nix {})}
|
|
||||||
sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Configure certificates...
|
|
||||||
security = lib.mkIf config.variables.useSSL {
|
|
||||||
acme.certs."dovecot2.${config.variables.myFQDN}" = {
|
|
||||||
domain = "${config.variables.myFQDN}";
|
|
||||||
group = "certs";
|
|
||||||
postRun = "systemctl restart dovecot2.service";
|
|
||||||
# cheat by getting the webroot from another certificate configured through nginx.
|
|
||||||
webroot = config.security.acme.certs."${config.variables.myFQDN}".webroot;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
# Make sure at least the self-signed certs are available before trying to start postfix
|
|
||||||
systemd.services.dovecot2.after = [ (lib.mkIf config.variables.useSSL "acme-selfsigned-certificates.target") "vmail-setup.service" ];
|
|
||||||
# Setup dovecot
|
|
||||||
networking.firewall.allowedTCPPorts = [ 110 143 993 995 4190 ];
|
|
||||||
services.dovecot2 = {
|
|
||||||
enable = true;
|
|
||||||
configFile = "${dovecotConf}";
|
|
||||||
modules = [ pkgs.dovecot_pigeonhole ];
|
|
||||||
};
|
|
||||||
systemd.services."vmail-setup" = {
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
script = ''
|
|
||||||
mkdir -p ${config.variables.vmailBaseDir}
|
|
||||||
chown -c ${config.variables.vmailUser}:${config.variables.vmailGroup} ${config.variables.vmailBaseDir}
|
|
||||||
chmod -c 0700 ${config.variables.vmailBaseDir}
|
|
||||||
# SSL workaround for dovecot...
|
|
||||||
mkdir -p /var/lib/dovecot
|
|
||||||
cat ${dovecotConfSSL} > /var/lib/dovecot/ssl-keys.conf
|
|
||||||
chown root:root /var/lib/dovecot/ssl-keys.conf
|
|
||||||
chmod 400 /var/lib/dovecot/ssl-keys.conf
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,14 +1,28 @@
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
let mymailserver = (import <nixpkgs> {}).pkgs.fetchgit {
|
||||||
|
url = "https://codeberg.org/tokudan/nixos-mailserver.git";
|
||||||
|
rev = "15c419d488d1f4148f268d62fce0975f5a88a464";
|
||||||
|
sha256 = "111xjmcvr7gq4406yxdj87wvi8psq3dhb7shkdsj5d4bdr9kr13q";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
# Import some configuration as they are too long to be easily readable here
|
# Import some configuration as they are too long to be easily readable here
|
||||||
imports = [
|
imports = [
|
||||||
./dovecot.nix
|
#./dovecot.nix
|
||||||
./postfix.nix
|
#./postfix.nix
|
||||||
./postfixadmin.nix
|
#./postfixadmin.nix
|
||||||
./roundcube.nix
|
#./roundcube.nix
|
||||||
./rspamd.nix
|
#./rspamd.nix
|
||||||
|
"${mymailserver}/default.nix"
|
||||||
];
|
];
|
||||||
|
networking.domain = "hamburg.freifunk.net";
|
||||||
|
services.mymailserver = {
|
||||||
|
enable = true;
|
||||||
|
adminAddress = "kontakt@hamburg.freifunk.net";
|
||||||
|
mailFQDN = "mail2.hamburg.freifunk.net";
|
||||||
|
};
|
||||||
users.groups."${config.variables.vmailGroup}" = { gid = config.variables.vmailGID; };
|
users.groups."${config.variables.vmailGroup}" = { gid = config.variables.vmailGID; };
|
||||||
users.users."${config.variables.vmailUser}" = {
|
users.users."${config.variables.vmailUser}" = {
|
||||||
uid = config.variables.vmailUID;
|
uid = config.variables.vmailUID;
|
||||||
|
|
89
postfix.nix
89
postfix.nix
|
@ -1,89 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
submission_header_cleanup_regex = pkgs.writeText "submission_header_cleanup_regex" ''
|
|
||||||
/^Received:.*by ${config.variables.myFQDN} \(Postfix/ IGNORE
|
|
||||||
'';
|
|
||||||
pfvirtual_mailbox_domains = pkgs.writeText "virtual_mailbox_domains.cf" ''
|
|
||||||
dbpath = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
|
|
||||||
'';
|
|
||||||
pfvirtual_alias_maps = pkgs.writeText "virtual_alias_maps.cf" ''
|
|
||||||
dbpath = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
|
|
||||||
'';
|
|
||||||
pfvirtual_alias_domain_maps = pkgs.writeText "virtual_alias_domain_maps.cf" ''
|
|
||||||
dbpath = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = ('%u' || '@' || alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
|
|
||||||
'';
|
|
||||||
pfvirtual_alias_domain_catchall_maps = pkgs.writeText "virtual_alias_domain_catchall_maps.cf" ''
|
|
||||||
dbpath = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = ('@' || alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
|
|
||||||
'';
|
|
||||||
pfvirtual_mailbox_maps = pkgs.writeText "virtual_mailbox_maps.cf" ''
|
|
||||||
dbpath = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
|
|
||||||
'';
|
|
||||||
pfvirtual_alias_domain_mailbox_maps = pkgs.writeText "virtual_alias_domain_mailbox_maps.cf" ''
|
|
||||||
dbpath = ${config.variables.pfadminDataDir}/postfixadmin.db
|
|
||||||
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = ('%u' || '@' || alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Configure Postfix to support SQLite
|
|
||||||
nixpkgs.config.packageOverrides = pkgs: { postfix = pkgs.postfix.override { withSQLite = true; }; };
|
|
||||||
# SSL/TLS specific configuration
|
|
||||||
security = lib.mkIf config.variables.useSSL {
|
|
||||||
# Configure the certificates...
|
|
||||||
acme.certs."postfix.${config.variables.myFQDN}" = {
|
|
||||||
domain = "${config.variables.myFQDN}";
|
|
||||||
group = "certs";
|
|
||||||
postRun = "systemctl restart postfix.service";
|
|
||||||
# cheat by getting some settings from another certificate configured through nginx.
|
|
||||||
webroot = config.security.acme.certs."${config.variables.myFQDN}".webroot;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
systemd = lib.mkIf config.variables.useSSL {
|
|
||||||
# Make sure at least the self-signed certs are available before trying to start postfix
|
|
||||||
services.postfix.after = [ "acme-selfsigned-certificates.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Setup Postfix
|
|
||||||
networking.firewall.allowedTCPPorts = [ 25 587 ];
|
|
||||||
services.postfix = {
|
|
||||||
enable = true;
|
|
||||||
enableSmtp = true;
|
|
||||||
enableSubmission = true;
|
|
||||||
config = {
|
|
||||||
mydestination = "";
|
|
||||||
myhostname = config.variables.myFQDN;
|
|
||||||
mynetworks_style = "host";
|
|
||||||
recipient_delimiter = "+";
|
|
||||||
relay_domains = "";
|
|
||||||
smtpd_milters = "unix:${config.variables.rspamdMilterSocket}";
|
|
||||||
non_smtpd_milters = "unix:${config.variables.rspamdMilterSocket}";
|
|
||||||
smtpd_sasl_path = config.variables.dovecotAuthSocket;
|
|
||||||
smtpd_sasl_type = "dovecot";
|
|
||||||
smtpd_tls_auth_only = "yes";
|
|
||||||
smtpd_tls_chain_files = lib.mkIf config.variables.useSSL "/var/lib/acme/postfix.${config.variables.myFQDN}/full.pem";
|
|
||||||
smtpd_tls_loglevel = "1";
|
|
||||||
smtpd_tls_received_header = "yes";
|
|
||||||
smtpd_tls_security_level = "may";
|
|
||||||
smtp_tls_loglevel = "1";
|
|
||||||
smtp_tls_security_level = "may";
|
|
||||||
virtual_alias_maps = "proxy:sqlite:${pfvirtual_alias_maps}, proxy:sqlite:${pfvirtual_alias_domain_maps}, proxy:sqlite:${pfvirtual_alias_domain_catchall_maps}";
|
|
||||||
virtual_mailbox_domains = "proxy:sqlite:${pfvirtual_mailbox_domains}";
|
|
||||||
virtual_mailbox_maps = "proxy:sqlite:${pfvirtual_mailbox_maps}, proxy:sqlite:${pfvirtual_alias_domain_mailbox_maps}";
|
|
||||||
virtual_transport = "lmtp:unix:${config.variables.dovecotLmtpSocket}";
|
|
||||||
};
|
|
||||||
masterConfig.submission.args = [ "-o" "cleanup_service_name=submission_cleanup" ];
|
|
||||||
masterConfig."submission_cleanup" = {
|
|
||||||
command = "cleanup";
|
|
||||||
args = [ "-o" "header_checks=regexp:${submission_header_cleanup_regex}" ];
|
|
||||||
private = false;
|
|
||||||
maxproc = 0;
|
|
||||||
};
|
|
||||||
rootAlias = config.variables.mailAdmin;
|
|
||||||
postmasterAlias = config.variables.mailAdmin;
|
|
||||||
};
|
|
||||||
}
|
|
101
postfixadmin.nix
101
postfixadmin.nix
|
@ -1,101 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
phppoolName = "postfixadmin_pool";
|
|
||||||
pfaGroup = config.variables.pfaGroup;
|
|
||||||
pfaUser = config.variables.pfaUser;
|
|
||||||
postfixadminpkg = config.variables.postfixadminpkg;
|
|
||||||
pfadminDataDir = config.variables.pfadminDataDir;
|
|
||||||
cacheDir = config.variables.postfixadminpkgCacheDir;
|
|
||||||
phpfpmHostPort = config.variables.pfaPhpfpmHostPort;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Setup the user and group
|
|
||||||
users.groups."${pfaGroup}" = { };
|
|
||||||
users.users."${pfaUser}" = {
|
|
||||||
isSystemUser = true;
|
|
||||||
group = "${pfaGroup}";
|
|
||||||
extraGroups = [ "dovecot2" ];
|
|
||||||
description = "PHP User for postfixadmin";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Setup nginx
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."${config.variables.pfaDomain}" = {
|
|
||||||
forceSSL = config.variables.useSSL;
|
|
||||||
enableACME = config.variables.useSSL;
|
|
||||||
root = "${postfixadminpkg}/public";
|
|
||||||
extraConfig = ''
|
|
||||||
charset utf-8;
|
|
||||||
|
|
||||||
etag off;
|
|
||||||
add_header etag "\"${builtins.substring 11 32 postfixadminpkg}\"";
|
|
||||||
add_header Permissions-Policy "interest-cohort=()" always;
|
|
||||||
|
|
||||||
index index.php;
|
|
||||||
|
|
||||||
location ~* \.php$ {
|
|
||||||
add_header Permissions-Policy "interest-cohort=()" always;
|
|
||||||
# Zero-day exploit defense.
|
|
||||||
# http://forum.nginx.org/read.php?2,88845,page=3
|
|
||||||
# Won't work properly (404 error) if the file is not stored on this
|
|
||||||
# server, which is entirely possible with php-fpm/php-fcgi.
|
|
||||||
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on
|
|
||||||
# another machine. And then cross your fingers that you won't get hacked.
|
|
||||||
try_files $uri =404;
|
|
||||||
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
||||||
# With php5-cgi alone:
|
|
||||||
fastcgi_pass unix:${config.services.phpfpm.pools."${phppoolName}".socket};
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
|
||||||
fastcgi_param SERVER_SOFTWARE nginx;
|
|
||||||
fastcgi_param QUERY_STRING $query_string;
|
|
||||||
fastcgi_param REQUEST_METHOD $request_method;
|
|
||||||
fastcgi_param CONTENT_TYPE $content_type;
|
|
||||||
fastcgi_param CONTENT_LENGTH $content_length;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
|
||||||
fastcgi_param REQUEST_URI $request_uri;
|
|
||||||
fastcgi_param DOCUMENT_URI $document_uri;
|
|
||||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
|
||||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
|
||||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
|
||||||
fastcgi_param REMOTE_PORT $remote_port;
|
|
||||||
fastcgi_param SERVER_ADDR $server_addr;
|
|
||||||
fastcgi_param SERVER_PORT $server_port;
|
|
||||||
fastcgi_param SERVER_NAME $server_name;
|
|
||||||
fastcgi_param HTTP_PROXY "";
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
systemd.services."postfixadmin-setup" = {
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
script = ''
|
|
||||||
# Setup the data directory with the database and the cache directory
|
|
||||||
mkdir -p ${pfadminDataDir}
|
|
||||||
chmod -c 751 ${pfadminDataDir}
|
|
||||||
chown -c ${pfaUser}:${pfaGroup} ${pfadminDataDir}
|
|
||||||
|
|
||||||
mkdir -p ${cacheDir}/templates_c
|
|
||||||
chown -Rc ${pfaUser}:${pfaGroup} ${cacheDir}/templates_c
|
|
||||||
chmod -Rc 751 ${cacheDir}/templates_c
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
services.phpfpm.pools."${phppoolName}" = {
|
|
||||||
user = "${pfaUser}";
|
|
||||||
group = "${pfaGroup}";
|
|
||||||
settings = {
|
|
||||||
"pm" = "dynamic";
|
|
||||||
"pm.max_children" = 75;
|
|
||||||
"pm.min_spare_servers" = 5;
|
|
||||||
"pm.max_spare_servers" = 20;
|
|
||||||
"pm.max_requests" = 10;
|
|
||||||
"catch_workers_output" = 1;
|
|
||||||
"listen.owner" = "nginx";
|
|
||||||
"listen.group" = "nginx";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
136
roundcube.nix
136
roundcube.nix
|
@ -1,136 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
poolName = "roundcube_pool";
|
|
||||||
|
|
||||||
roundcube = (pkgs.callPackage ./pkg-roundcube.nix {
|
|
||||||
conf = pkgs.writeText "roundcube-config.inc.php" ''
|
|
||||||
<?php
|
|
||||||
$config = array();
|
|
||||||
$config['db_dsnw'] = 'sqlite:///${config.variables.roundcubeDataDir}/roundcube.sqlite?mode=0600';
|
|
||||||
$config['default_host'] = 'tls://${config.variables.myFQDN}';
|
|
||||||
$config['smtp_server'] = 'tls://${config.variables.myFQDN}';
|
|
||||||
$config['smtp_port'] = 587;
|
|
||||||
$config['smtp_user'] = '%u';
|
|
||||||
$config['smtp_pass'] = '%p';
|
|
||||||
$config['product_name'] = 'Webmail';
|
|
||||||
$config['des_key'] = file_get_contents("${config.variables.roundcubeDataDir}/des_key");;
|
|
||||||
$config['cipher_method'] = 'AES-256-CBC';
|
|
||||||
$config['plugins'] = array(
|
|
||||||
'archive',
|
|
||||||
'managesieve',
|
|
||||||
'zipdownload',
|
|
||||||
);
|
|
||||||
$config['skin'] = 'larry';
|
|
||||||
'';
|
|
||||||
temp = "${config.variables.roundcubeDataDir}/temp";
|
|
||||||
logs = "${config.variables.roundcubeDataDir}/logs";
|
|
||||||
} );
|
|
||||||
in
|
|
||||||
{
|
|
||||||
services.nginx.virtualHosts."${config.variables.roundcubeFQDN}" = {
|
|
||||||
forceSSL = config.variables.useSSL;
|
|
||||||
enableACME = config.variables.useSSL;
|
|
||||||
root = "${roundcube}/public_html";
|
|
||||||
extraConfig = ''
|
|
||||||
access_log off;
|
|
||||||
add_header Permissions-Policy "interest-cohort=()" always;
|
|
||||||
'';
|
|
||||||
locations."~ ^/favicon.ico/.*$" = {
|
|
||||||
extraConfig = ''
|
|
||||||
try_files $uri kins/larry/images/$uri;
|
|
||||||
add_header Permissions-Policy "interest-cohort=()" always;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
locations."/" = {
|
|
||||||
extraConfig = ''
|
|
||||||
index index.php;
|
|
||||||
try_files $uri /public/$uri /index.php$is_args$args;
|
|
||||||
etag off;
|
|
||||||
add_header etag "\"${builtins.substring 11 32 roundcube}\"";
|
|
||||||
add_header Permissions-Policy "interest-cohort=()" always;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
locations."~ [^/]\.php(/|$)" = {
|
|
||||||
extraConfig = ''
|
|
||||||
etag off;
|
|
||||||
add_header etag "\"${builtins.substring 11 32 roundcube}\"";
|
|
||||||
add_header Permissions-Policy "interest-cohort=()" always;
|
|
||||||
|
|
||||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
|
||||||
if (!-f $document_root$fastcgi_script_name) {
|
|
||||||
return 404;
|
|
||||||
}
|
|
||||||
|
|
||||||
fastcgi_pass unix:${config.services.phpfpm.pools."${poolName}".socket};
|
|
||||||
fastcgi_index index.php;
|
|
||||||
|
|
||||||
fastcgi_param QUERY_STRING $query_string;
|
|
||||||
fastcgi_param REQUEST_METHOD $request_method;
|
|
||||||
fastcgi_param CONTENT_TYPE $content_type;
|
|
||||||
fastcgi_param CONTENT_LENGTH $content_length;
|
|
||||||
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
|
||||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
||||||
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
|
||||||
fastcgi_param REQUEST_URI $request_uri;
|
|
||||||
fastcgi_param DOCUMENT_URI $document_uri;
|
|
||||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
|
||||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
|
||||||
|
|
||||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
|
||||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
|
||||||
|
|
||||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
|
||||||
fastcgi_param REMOTE_PORT $remote_port;
|
|
||||||
fastcgi_param SERVER_ADDR $server_addr;
|
|
||||||
fastcgi_param SERVER_PORT $server_port;
|
|
||||||
fastcgi_param SERVER_NAME $server_name;
|
|
||||||
|
|
||||||
fastcgi_param HTTPS $https;
|
|
||||||
fastcgi_param HTTP_PROXY "";
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
systemd.services.roundcube-install = {
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
script = ''
|
|
||||||
mkdir -p ${config.variables.roundcubeDataDir}/temp ${config.variables.roundcubeDataDir}/logs
|
|
||||||
chown -Rc ${config.variables.roundcubeUser}:${config.variables.roundcubeGroup} ${config.variables.roundcubeDataDir}
|
|
||||||
chmod -c 700 ${config.variables.roundcubeDataDir}
|
|
||||||
# Regenerate the key every now and then. This invalidates all sessions, but during reboot should be good enough.
|
|
||||||
[ -f "${config.variables.roundcubeDataDir}/des_key" ] && ${pkgs.coreutils}/bin/shred "${config.variables.roundcubeDataDir}/des_key"
|
|
||||||
${pkgs.coreutils}/bin/dd if=/dev/urandom bs=32 count=1 2>/dev/null | ${pkgs.coreutils}/bin/base64 > "${config.variables.roundcubeDataDir}/des_key"
|
|
||||||
chown -c "${config.variables.roundcubeUser}":${config.variables.roundcubeGroup} "${config.variables.roundcubeDataDir}/des_key"
|
|
||||||
chmod -c 400 "${config.variables.roundcubeDataDir}/des_key"
|
|
||||||
if [ -s "${config.variables.roundcubeDataDir}/roundcube.sqlite" ]; then
|
|
||||||
# Just go ahead and remove the sessions, the key to decrypt them has just been destroyed anyway.
|
|
||||||
${pkgs.sqlite}/bin/sqlite3 "${config.variables.roundcubeDataDir}/roundcube.sqlite" "DELETE FROM session;"
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
services.phpfpm.pools."${poolName}" = {
|
|
||||||
user = "${config.variables.roundcubeUser}";
|
|
||||||
group = "${config.variables.roundcubeUser}";
|
|
||||||
settings = {
|
|
||||||
"pm" = "dynamic";
|
|
||||||
"pm.max_children" = 75;
|
|
||||||
"pm.min_spare_servers" = 5;
|
|
||||||
"pm.max_spare_servers" = 20;
|
|
||||||
"pm.max_requests" = 10;
|
|
||||||
"catch_workers_output" = 1;
|
|
||||||
"listen.owner" = "nginx";
|
|
||||||
"listen.group" = "nginx";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
users.extraUsers."${config.variables.roundcubeUser}" = { };
|
|
||||||
users.extraGroups."${config.variables.roundcubeUser}" = { };
|
|
||||||
users.groups."${config.variables.roundcubeGroup}" = { };
|
|
||||||
users.users."${config.variables.roundcubeUser}" = {
|
|
||||||
isSystemUser = true;
|
|
||||||
group = "${config.variables.roundcubeGroup}";
|
|
||||||
description = "PHP User for roundcube";
|
|
||||||
};
|
|
||||||
}
|
|
68
rspamd.nix
68
rspamd.nix
|
@ -1,68 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
rspamdExtraConfig = pkgs.writeText "rspamd-extra.conf" ''
|
|
||||||
secure_ip = [::1]
|
|
||||||
options {
|
|
||||||
filters: "chartable,dkim,dkim_signing,spf,surbl,regexp,fuzzy_check"
|
|
||||||
}
|
|
||||||
milter_headers {
|
|
||||||
extended_spam_headers = true;
|
|
||||||
}
|
|
||||||
classifier {
|
|
||||||
bayes {
|
|
||||||
autolearn = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dkim_signing {
|
|
||||||
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
|
|
||||||
check_pubkey = true;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
#networking.firewall.allowedTCPPorts = [ 110 143 993 995 ];
|
|
||||||
environment.systemPackages = [
|
|
||||||
(pkgs.writeShellScriptBin "dkim-generate" ''
|
|
||||||
if [ $# -ne 1 ]; then
|
|
||||||
echo Usage: dkim-generate DOMAIN >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rspamd=${pkgs.rspamd}/bin/rspamadm
|
|
||||||
mkdir -p /var/lib/rspamd/dkim
|
|
||||||
$rspamd dkim_keygen -b 2048 -d "$1" -s dkim | ${pkgs.gawk}/bin/awk '/^-/ {KEY= ! KEY; print; next} KEY {print} !KEY {print > "/dev/stderr"}' >/var/lib/rspamd/dkim/"$1".dkim.key 2>/var/lib/rspamd/dkim/"$1".dkim.dns
|
|
||||||
ls -l /var/lib/rspamd/dkim/"$1".dkim.key /var/lib/rspamd/dkim/"$1".dkim.dns
|
|
||||||
'') ];
|
|
||||||
services.rspamd = {
|
|
||||||
enable = true;
|
|
||||||
# Just shove our own configuration up rspamd's rear end with high prio as the default configuration structure is a mess
|
|
||||||
extraConfig = ''
|
|
||||||
.include(try=true,priority=10,duplicate=merge) "${rspamdExtraConfig}"
|
|
||||||
'';
|
|
||||||
workers = {
|
|
||||||
controller = {
|
|
||||||
enable = true;
|
|
||||||
extraConfig = ''
|
|
||||||
secure_ip = [::1]
|
|
||||||
'';
|
|
||||||
bindSockets = [
|
|
||||||
"[::1]:11334"
|
|
||||||
{ mode = "0666"; owner = config.variables.vmailUser; socket = "/run/rspamd/worker-controller.socket"; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
rspamd_proxy = {
|
|
||||||
enable = true;
|
|
||||||
type = "rspamd_proxy";
|
|
||||||
count = 5; # TODO: match with postfix limits
|
|
||||||
extraConfig = ''
|
|
||||||
upstream "local" {
|
|
||||||
self_scan = yes; # Enable self-scan
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
bindSockets = [
|
|
||||||
{ socket = config.variables.rspamdMilterSocket; mode = "0600"; owner = config.services.postfix.user; group = config.services.rspamd.group; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in a new issue