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 |       ./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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Daniel Frank
				Daniel Frank