Migrate the mail config to the nixos module
This commit is contained in:
		
					parent
					
						
							
								ad0ab2e843
							
						
					
				
			
			
				commit
				
					
						5dcbb4e2dc
					
				
			
		
					 7 changed files with 19 additions and 564 deletions
				
			
		|  | @ -10,7 +10,6 @@ | |||
|       ./hardware-configuration.nix | ||||
|       ./acme.nix | ||||
|       ./sshusers.nix | ||||
|       ./variables.nix | ||||
|       ./mailserver.nix | ||||
|       ./borgbackup.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, ... }: | ||||
| 
 | ||||
| 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 | ||||
|   imports = [  | ||||
|     ./dovecot.nix | ||||
|     ./postfix.nix | ||||
|     ./postfixadmin.nix | ||||
|     ./roundcube.nix | ||||
|     ./rspamd.nix | ||||
|     #./dovecot.nix | ||||
|     #./postfix.nix | ||||
|     #./postfixadmin.nix | ||||
|     #./roundcube.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.users."${config.variables.vmailUser}" = { | ||||
|     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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Daniel Frank
				Daniel Frank