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.