============= mail.libre.is ============= Documentation for Libre mail server. Setting up Internet mail servers is a pain. It's nothing like just setting up a web server... Main Components =============== This install is based on this guide: ``_ For more information and details about what is what, refer to that site. Dovecot ``_ MariaDB OpenDMARC ``_ ``_ Postfix ``_ DNS === Add a DNS mx record, so it returns result like this: .. code-block:: sh $ host -t mx libre.is libre.is mail is handled by 10 mail.libre.is. Set IP for mail.libre.is. Set up reverse DNS records. Debian ====== Install Debian stable (bookworm). Install rsyslog for old school convenience: .. code-block:: sh sudo apt install rsyslog Firewall ======== Open TCP ports. .. code-block:: sh # Web -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Postfix -A INPUT -p tcp --dport 25 -j ACCEPT -A INPUT -p tcp --dport 587 -j ACCEPT # Dovecot imaps -A INPUT -p tcp --dport 993 -j ACCEPT # Dovecot sieve -A INPUT -p tcp --dport 4190 -j ACCEPT Apache ====== The Apache webserver is used out of laziness as it allows easy certificate updates with certbot. A webmail server won't be running on the main mail server. .. code-block:: sh sudo apt install apache2 echo "mail.libre.is" | sudo tee /var/www/html/index.html Open up firewall ports 80 and 443. MariaDB ======= The main database server. .. code-block:: sh sudo apt install mariadb-server sudo mariadb-admin password mariadb -uroot -p Add databases. Change password to something secure. .. code-block:: sql CREATE DATABASE mailserver; GRANT ALL ON mailserver.* TO 'mailadmin'@'localhost' IDENTIFIED BY 'password'; GRANT SELECT ON mailserver.* TO 'mailserver'@'127.0.0.1' IDENTIFIED BY 'password'; USE mailserver; CREATE TABLE IF NOT EXISTS `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 `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, `quota` bigint(11) NOT NULL DEFAULT 0, 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 `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; EXIT Postfix ======= The main SMTP mail server. .. code-block:: sh sudo apt install postfix sudo apt install postfix-mysql Set up postfix to use MariaDB. Edit /etc/postfix/mysql-virtual-mailbox-domains.cf and add below, using the mailserver password used in MariaDB. .. code-block:: cfg user = mailserver password = password hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM virtual_domains WHERE name='%s' Edit /etc/postfix/mysql-virtual-mailbox-maps.cf and add below contents: .. code-block:: cfg user = mailserver password = password hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM virtual_users WHERE email='%s' Edit /etc/postfix/mysql-virtual-alias-maps.cf and add below: .. code-block:: cfg user = mailserver password = password hosts = 127.0.0.1 dbname = mailserver query = SELECT destination FROM virtual_aliases WHERE source='%s' Edit /etc/postfix/mysql-email2email.cf and add: .. code-block:: cfg user = mailserver password = password hosts = 127.0.0.1 dbname = mailserver query = SELECT email FROM virtual_users WHERE email='%s' Then run these commands: .. code-block:: sh 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 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 Redis ===== Note, the licensing of Redis has gone bad. The version in Debian is OK. But in the future, probably replace with a fork. .. code-block:: sh sudo apt install redis-server rspamd ====== Spam control. .. code-block:: sh sudo apt install rspamd Certbot ======= Encryption certificates with Let's Encrypt. Not using an Apache webserver on the mail server makes getting new certificates a bit more complex. .. code-block:: sh sudo apt install certbot ca-certificates python3-certbot-apache sudo certbot -d mail.libre.is sudo systemctl restart apache2 echo "post-hook = systemctl restart postfix dovecot apache2" | \ sudo tee /etc/letsencrypt/cli.ini Dovecot ======= Just using encrypted IMAPS, not POP. .. code-block:: sh sudo apt install dovecot-mysql dovecot-pop3d dovecot-imapd \ dovecot-managesieved dovecot-lmtpd Note, since IPv6 isn't being used, the dovecot install barfs. Edit /etc/dovecot/dovecot.conf and add this line, where appropriate: .. code-block:: sh listen = * Note, this is removing the "::" from listen, which using IPv6. Then re-run the install so the packages are happy. Note, the re-install won't overwrite the "listen" change. .. code-block:: sh sudo apt install --reinstall dovecot-mysql dovecot-pop3d dovecot-imapd \ dovecot-managesieved dovecot-lmtpd Add user and set up configs .. code-block:: sh sudo groupadd -g 5000 vmail sudo useradd -g vmail -u 5000 vmail -d /var/vmail -m sudo chown -R vmail:vmail /var/vmail sudo sed -i -e \ 's/auth_mechanisms = plain/auth_mechanisms = plain login/g' \ /etc/dovecot/conf.d/10-auth.conf sudo sed -i -e \ 's/!include auth-system.conf.ext/#!include auth-system.conf.ext/g' \ /etc/dovecot/conf.d/10-auth.conf sudo sed -i -e \ 's/#!include auth-sql.conf.ext/!include auth-sql.conf.ext/g' \ /etc/dovecot/conf.d/10-auth.conf sudo sed -i -e \ 's/^mail_location.*/mail_location = maildir:~\/Maildir/g' \ /etc/dovecot/conf.d/10-mail.conf sudo sed -i -e \ 's/#mail_plugins =/mail_plugins = quota/g' \ /etc/dovecot/conf.d/10-mail.conf Edit /etc/dovecot/conf.d/10-master.conf and add: .. code-block:: cfg # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } Edit /etc/dovecot/conf.d/10-ssl.conf, set key locations, and make it required. .. code-block:: cfg ssl = required ssl_cert = `_ Then enter the IP address of the server and fill out the form. They will send a confirmation email with a link. Go to that link and it will be immediately removed. Administration ============== Now that everything is working... Log into the database using the mailadmin databse password: .. code-block:: sh mariadb -u mailadmin -p mailserver List Virtual Domains -------------------- .. code-block:: sql SELECT * FROM virtual_domains; List Virtual Users ------------------ .. code-block:: sql SELECT * FROM virtual_users; List Virtual Aliases -------------------- .. code-block:: sql SELECT * FROM virtual_aliases; Add Virtual Domain ------------------ Add the domain: .. code-block:: sql INSERT INTO virtual_domains (name) VALUES ("example.org"); Add a Mail User --------------- Generate a password with dovecot: .. code-block:: sh sudo dovecot pw -s BLF-CRYPT Log into database as mailadmin and run this command, using the dovecot generated password string, and set the domain and user email. Note, upstream docs are missing "(" and ")" for VALUES. .. code-block:: sql INSERT INTO virtual_users (domain_id, email, password) VALUES ((SELECT id FROM virtual_domains WHERE name='example.org'), 'john@example.org','{BLF-CRYPT}$2y$05$.We…'); Add a User Alias ---------------- Example to add an alias. The first email should be the alias, the second email is where it should go to. .. code-block:: sql INSERT INTO virtual_aliases (domain_id, source, destination) VALUES ( (SELECT id FROM virtual_domains WHERE name='example.org'), 'melissa@example.org', 'juila@example.net'); Change a User Password ---------------------- Generate string for new password: .. code-block:: sh sudo dovecot pw -s BLF-CRYPT Use that string: .. code-block:: sql UPDATE virtual_users SET password='{BLF-CRYPT}$2y$05$.We…' WHERE email='email@address'; Delete Virtual Domain --------------------- .. code-block:: sql DELETE FROM virtual_domains where name='example.org'; Delete User ----------- .. code-block:: sql DELETE FROM virtual_users WHERE email='john@example.org'; Delete Alias ------------ .. code-block:: sql DELETE FROM virtual_aliases WHERE source='melissa@example.org'; Email Client Setup ================== Set up mail clients thusly. Thunderbird ----------- Example email Address: username@libre.is .. code-block:: cfg Incoming Server Hostname: mail.libre.is Protocol: IMAP Port: 993 Connection Security: SSL/TLS Authenication Method: Normal Password Username: username@libre.is (same as email address) Outgoing Server Hostname: mail.libre.is Port: 587 Connection Security: STARTTLS Authenication Method: Normal Password Username: username@libre.is (same as email address) Other ===== Perhaps these too. .. code-block:: sh apt install postfix-policyd-spf-python rspamd apt install fail2ban spamassassin sqlgrey opendkim-tools make Perhaps easier to admin with this script. ``_ OpenDMARC ========= Requires database setup. .. code-block:: sh sudo apt install opendmarc SPF === Set up SPF.