Self-Hosted E-Mail: Difference between revisions
m Made TOC float left |
m →Rainloop: Disable wiki markup on URL |
||
Line 551: | Line 551: | ||
Download Rainloop | Download Rainloop | ||
{{bc| | {{bc|<nowiki> | ||
sudo cd /srv/http/<domain> | sudo cd /srv/http/<domain> | ||
sudo wget https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip | sudo wget https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip</nowiki> | ||
}} | }} | ||
Latest revision as of 13:57, 20 June 2022
Setting up your own e-mail service from scratch can be a time-consuming task, but it also allows the ultimate control over your e-mail at no additional cost. Create any account(s) you want from any domain you own, and relieve yourself of the snooping from free e-mail service providers. All with the help of free software from Postfix, Dovecot, ISPmail (administer addresses), and Rainloop (web mail).
Do note that many, if not all, residential ISPs block port 25 to combat spam from any potentially botted customer PC on the ISP's network. SMTP by itself is not a secure protocol at all. As such, most SMTP servers are configured by default to reject unauthenticated plaintext requests to send mail from any IP that isn't localhost. The most common solution to this is to purchase Virtual Private Server (VPS) service, which can cost as little as US$3.00 per month. Another solution would be to purchase a Virtual Private Network (VPN) service with dedicated IP address and PTR record.
Prerequisites
- Firewall
- Make sure ports 25, 465, 587, 993, and 995 are open.
- Database
- Allows for the divorce of email addresses from UNIX/LDAP usernames.
- Web Server
- For web applications and Let's Encrypt SSL certificates.
- Let's Encrypt
- Allows the use of SSL-secured transmission instead of plaintext.
- Redis
- Rspamd uses this to cache recently seen mail servers and spam scores.
Required Packages
These packages are needed to set up your own e-mail service.
pacman -Syu --needed dovecot pigeonhole postfix rspamd swaks
Postfix Configuration
Create MariaDB Databases for Postfix
CREATE DATABASE MAIL; CREATE USER 'mailuser'@'localhost' IDENTIFIED BY '<password>'; CREATE USER 'mailadmin'@'localhost' IDENTIFIED BY '<password>'; GRANT ALL ON MAIL.* TO 'mailadmin'@'localhost'; GRANT SELECT ON MAIL.* TO 'mailuser'@'localhost';
CREATE TABLE IF NOT EXISTS `MAIL`.`virtual_domains` ( `id` int(11) NOT NULL auto_increment, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `MAIL`.`virtual_users` ( `id` int(11) NOT NULL auto_increment, `domain_id` int(11) NOT NULL, `email` varchar(100) NOT NULL, `password` varchar(150) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `MAIL`.`virtual_aliases` ( `id` int(11) NOT NULL auto_increment, `domain_id` int(11) NOT NULL, `source` varchar(100) NOT NULL, `destination` varchar(100) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Configure Postfix to Use MariaDB
/etc/postfix/mysql-virtual-mailbox-domains.cf
user = mailuser password = <password> hosts = unix:/run/mysqld/mysqld.sock dbname = MAIL query = SELECT 1 FROM virtual_domains WHERE name='%s'
/etc/postfix/mysql-virtual-mailbox-maps.cf
user = mailuser password = <password> hosts = unix:/run/mysqld/mysqld.sock dbname = MAIL query = SELECT 1 FROM virtual_users WHERE email='%s'
/etc/postfix/mysql-virtual-alias-maps.cf
user = mailuser password = <password> hosts = unix:/run/mysqld/mysqld.sock dbname = MAIL query = SELECT destination FROM virtual_aliases WHERE source='%s'
/etc/postfix/mysql-email2email.cf
user = mailuser password = <password> hosts = unix:/run/mysqld/mysqld.sock dbname = MAIL query = SELECT email FROM virtual_users WHERE email='%s'
sudo postconf virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf sudo postconf virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf sudo postconf virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf sudo chgrp postfix /etc/postfix/mysql-*.cf sudo chmod 640 /etc/postfix/mysql-*.cf
Configure Postfix for E-mail Filtering
Add the following lines to the end of the /etc/postfix/master.cf
file:
/etc/postfix/master.cf
... submission inet n - - - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_sasl_security_options=noanonymous -o smtpd_sender_login_maps=mysql:/etc/postfix/mysql-email2email.cf -o smtpd_sender_restrictions=reject_sender_login_mismatch -o smtpd_sasl_local_domain=$myhostname -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject ... dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
sudo postconf virtual_transport=lmtp:unix:private/dovecot-lmtp sudo postconf smtpd_sasl_type=dovecot sudo postconf smtpd_sasl_path=private/auth sudo postconf smtpd_sasl_auth_enable=yes sudo postconf smtpd_tls_security_level=may sudo postconf smtpd_tls_auth_only=yes sudo postconf smtpd_tls_cert_file=/etc/letsencrypt/live/<domain>/fullchain.pem sudo postconf smtpd_tls_key_file=/etc/letsencrypt/live/<domain>/privkey.pem sudo postconf smtp_tls_security_level=may sudo postconf smtpd_milters=inet:127.0.0.1:11332 sudo postconf non_smtpd_milters=inet:127.0.0.1:11332 sudo postconf milter_protocol=6 sudo postconf milter_mail_macros="i {mail_addr} {client_addr} {client_name} {auth_authen}"
Dovecot Configuration
sudo groupadd -g 5000 vmail sudo useradd -g vmail -u 5000 vmail -d /srv/imap -m sudo chown -R vmail:vmail /srv/mail sudo cp /usr/share/doc/dovecot/example-config/dovecot.conf /etc/dovecot sudo cp -r /usr/share/doc/dovecot/example-config/conf.d /etc/dovecot
/etc/dovecot/dovecot.conf
... # Protocols we want to be serving. # Don't include submission -- postfix does that. protocols = imap pop3 lmtp sieve .... # Add these lines to the end of the file # Or just before the include blocks service auth { unix_listener auth-client { group = postfix mode = 0660 user = postfix } unix_listener auth-master { group = vmail mode = 0660 user = vmail } user = root } service managesieve-login { inet_listener sieve { port = 4190 } } service managesieve { } protocol sieve { managesieve_max_line_length = 65536 managesieve_implementation_string = dovecot log_path = /var/log/dovecot-sieve-errors.log info_log_path = /var/log/dovecot-sieve.log } plugin { sieve = ~/dovecot.sieve sieve_global_path = /etc/dovecot/sieve/default.sieve sieve_dir = ~/sieve sieve_global_dir = /etc/dovecot/sieve/global/ } lda_mailbox_autocreate = yes lda_mailbox_autosubscribe = yes protocol lda { mail_plugins = $mail_plugins autocreate sieve quota postmaster_address = postmaster@mydomain.com hostname = mail.mydomain.com auth_socket_path = /var/run/dovecot/auth-master log_path = /var/log/dovecot-lda-errors.log info_log_path = /var/log/dovecot-lda.log } protocol lmtp { mail_plugins = $mail_plugins autocreate sieve quota log_path = /var/log/dovecot-lmtp-errors.log info_log_path = /var/log/dovecot-lmtp.log }
/etc/dovecot/conf.d/10-auth.conf
... #!include auth-system.conf.ext !include auth-sql.conf.ext ...
/etc/dovecot/conf.d/auth-sql.conf.ext
... #userdb { # driver = sql # args = /etc/dovecot/dovecot-sql.conf.ext #} ... userdb { driver = static args = uid=vmail gid=vmail home=/srv/mail/%n@%d }
/etc/dovecot/conf.d/10-mail.conf
... mail_location = maildir:/srv/mail/%n@%d/Maildir ... namespace inbox { ... separator = . ... } ...
/etc/dovecot/conf.d/10-master.conf
... service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { group = postfix mode = 0600 user = postfix } ... } ... service auth { ... # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } ... } ...
/etc/dovecot/conf.d/10-ssl.conf
... ssl = yes ... ssl_cert = </etc/letsencrypt/live/<domain>/fullchain.pem ssl_key = </etc/letsencrypt/live/<domain>/privkey.pem ... ssl_ca = </etc/letsencrypt/live/<domain>/chain.pem ...
/etc/dovecot/conf.d/15-mailboxes.conf
... mailbox INBOX.Drafts { special_use = \Drafts auto = subscribe } mailbox INBOX.Junk { special_use = \Junk auto = subscribe autoexpunge = 30d } mailbox INBOX.Trash { special_use = \Trash auto = subscribe autoexpunge = 30d } mailbox INBOX.Sent { special_use = \Sent auto = subscribe } ...
/etc/dovecot/conf.d/20-imap.conf
... protocol imap { # Space separated list of plugins to load (default is global mail_plugins). mail_plugins = $mail_plugins imap_sieve ... }
/etc/dovecot/conf.d/20-lmtp.conf
... protocol lmtp { # Space separated list of plugins to load (default is global mail_plugins). mail_plugins = $mail_plugins sieve ... }
/etc/dovecot/conf.d/90-sieve.conf
... sieve_after = /etc/dovecot/sieve-after ... sieve_plugins = sieve_imapsieve sieve_extprograms ... # From elsewhere to Junk folder imapsieve_mailbox1_name = Junk imapsieve_mailbox1_causes = COPY imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve # From Junk folder to elsewhere imapsieve_mailbox2_name = * imapsieve_mailbox2_from = Junk imapsieve_mailbox2_causes = COPY imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve sieve_pipe_bin_dir = /etc/dovecot/sieve sieve_global_extensions = +vnd.dovecot.pipe }
sudo mkdir /etc/dovecot/sieve{-after,}
/etc/dovecot/sieve-after/spam-to-folder.sieve
require ["fileinto","mailbox"]; if header :contains "X-Spam" "Yes" { fileinto :create "INBOX.Junk"; stop; }
/etc/dovecot/sieve/learn-spam.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve"]; pipe :copy "rspamd-learn-spam.sh";
/etc/dovecot/sieve/learn-ham.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve"]; pipe :copy "rspamd-learn-ham.sh";
/etc/dovecot/dovecot-sql.conf.ext
driver = mysql connect = host=/run/mysqld/mysqld.sock dbname=MAIL user=mailuser password=<password> default_pass_scheme = SHA256-CRYPT password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
/etc/dovecot/sieve/rspamd-learn-spam.sh
#!/usr/bin/env sh exec /usr/bin/rspamc learn_spam
/etc/dovecot/sieve/rspamd-learn-ham.sh
#!/usr/bin/env sh exec /usr/bin/rspamc learn_ham
sudo sievec /etc/dovecot/sieve-after/spam-to-folder.sieve sudo sievec /etc/dovecot/sieve/learn-spam.sieve sudo sievec /etc/dovecot/sieve/learn-ham.sieve sudo touch /var/log/{dovecot-lda-errors.log,dovecot-lda.log} sudo touch /var/log/{dovecot-sieve-errors.log,dovecot-sieve.log} sudo touch /var/log/{dovecot-lmtp-errors.log,dovecot-lmtp.log} sudo mkdir -p /etc/dovecot/sieve/global sudo chown vmail: -R /etc/dovecot/sieve sudo chown vmail:mail /var/log/dovecot-* sudo chown root:root /etc/dovecot/dovecot-sql.conf.ext sudo chmod 600 /etc/dovecot/dovecot-sql.conf.ext sudo chmod 600 /etc/dovecot/sieve/learn-{spam,ham}.sieve sudo chmod 700 /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh sudo chown vmail:vmail /etc/dovecot/sieve/learn-{spam,ham}.sieve sudo chown vmail:vmail /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
Rspamd Configuration
sudo mkdir /etc/rspamd/conf.d
/etc/rspamd/override.d/milter_headers.conf
extended_spam_headers = true;
/etc/rspamd/override.d/classifier-bayes.conf
autolearn = true;
sudo mkdir /var/lib/rspamd/dkim sudo chown _rspamd:_rspamd /var/lib/rspamd/dkim sudo rspamadm dkim_keygen -d <domain> -s $(date +%Y%m%d)
/var/lib/rspamd/dkim/<domain>.YYYYMMDD.key
-----BEGIN PRIVATE KEY----- [base64 key] -----END PRIVATE KEY-----
The second part of the output of rspamadm dkim_keygen
can be directly pasted into a DNS zone if you are running your own server. If you only have control of your domain name through a 3rd party:
Type | Host | Value |
---|---|---|
TXT | @ | v=spf1 a mx ip4:<ip-address> -all |
TXT | _dmarc | v=DMARC1; p=none; sp=none; rf=afrf; pct=100; ri=86400 |
TXT | YYYYMMDD._domainkey | v=DKIM1; k=rsa; p=AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789... |
/etc/rspamd/local.d/dkim_signing.conf
path = "/var/lib/rspamd/dkim/$domain.$selector.key"; selector_map = "/etc/rspamd/dkim_selectors.map";
/etc/rspamd/dkim_selectors.map
<domain> YYYYMMDD
sudo systemctl enable --now rspamd
ISPmail Admin
Start with the Non-Proxied Web Site template.
Then, in the site's root:
sudo wget 'https://www.ima.jungclaussen.com/dwn/dwn.php?v=0.9.6&f=.tar.gz' sudo tar -xvf 'dwn.php?v=0.9.6&f=.tar.gz' sudo mv ispmail*/htdocs/* ./ sudo rm -r 'dwn.php?v=0.9.6&f=.tar.gz' ispmail*
Then edit the configuration file:
<ispmail_root>/cfg/config.inc.php
<?php // @package ISPmail_Admin // @author Ole Jungclaussen // @version 0.9.0 // SHOW PHP ERRORS (DEBUGGING) // ini_set('display_startup_errors', 1); // ini_set('display_errors', 1); // error_reporting(-1); // DATABASE ACCESS define('IMA_CFG_DB_HOST', '127.0.0.1'); define('IMA_CFG_DB_PORT', '3306'); define('IMA_CFG_DB_USER', 'mailadmin'); define('IMA_CFG_DB_PASSWORD', '<password>'); define('IMA_CFG_DB_DATABASE', 'MAIL'); // PASSWORD HASHES (enable only *one*) define('IMA_CFG_USE_SHA256_HASHES', true); // define('IMA_CFG_USE_MD5_HASHES', true); // ACCESS CONTROL: uncomment the type you want to use. define('IMA_CFG_LOGIN', IMA_LOGINTYPE_ACCOUNT); // define('IMA_CFG_LOGIN', IMA_LOGINTYPE_ADM); // define('IMA_CFG_LOGIN', IMA_LOGINTYPE_ADMAUTO); // ADMINISTRATOR'S NAME AND PASSWORD define('IMA_CFG_ADM_USER', 'admin'); // admin username define('IMA_CFG_ADM_PASS', '<password>'); // admin password // LISTS // Spread long lists on multiple pages. Set number of maximum entries // per page. Changes take effect after login/logout. If not defined, // defaults to 65535. // define('IMA_LIST_MAX_ENTRIES', 200); ?>
After finalization you should now be able to log in and set up your virtual mailboxes.
Rainloop
Start with the Non-Proxied Web Site template.
Change the following sections of the nginx conf file:
/etc/nginx/sites-available/<domain>.conf
... location ~ /data { deny all; } ... location ~ \.php$ { fastcgi_pass unix:/run/php-fpm/php-fpm.sock; fastcgi_index index.php; include fastcgi.conf; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } ...
Download Rainloop
sudo cd /srv/http/<domain> sudo wget https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip
Extract the zip file
sudo unzip rainloop-community-latest.zip
Set the correct permissions on the files
sudo find . -type d -exec chmod 755 {} \; sudo find . -type f -exec chmod 644 {} \;
Set the correct owner on the whole web root
sudo chown -R http:http /srv/http/<dir>
After you finalize the setup, you should now be able to access the Admini Panel at http://<domain>/?admin
. The default login is admin:12345
From the Admin Panel, add your domain under Domains. Use the public-facing domain for the Name, and localhost
for the IMAP and SMTP servers.
Under Login, set the Default Domain to localhost
.
Optionally, you can enable contacts. You will need to manually set up a database and user, but that is the only configuration needed to do on your part.
For Security, you should enable all of the Security options. You should also change the Admin Panel Access Credentials.
Click on the power-off icon in the upper-right corner to finish with the Admin Panel.
Navigate to http://<domain>
to log in and access your mail.