Build mail server on ubuntu 22.04

this article will show you how to install mail server on ubuntu linux 22.04 with postfix, dovecot, mariadb, letsencrypt, and opendkim

hope this article help you


Step by step

  1. install package
  2. configure mariadb
  3. configure letsencrypt
  4. configure postfix
  5. configure dovecot
  6. configure opendkim

1. install package

apt install mariadb-server mariadb-client postfix postfix-mysql dovecot-core dovecot-pop3d dovecot-imapd dovecot-mysql certbot opendkim opendkim-tools


2. configure mariadb

run this command below
mysql_secure_installation
then answer all quistion, look like this
Enter current password for root (enter for none):
Set root password? [Y/n] Y
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

create database email
create database email;
GRANT ALL PRIVILEGES ON email.* TO "dbmail"@"localhost" IDENTIFIED BY "your_password";

create table email
CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) );
CREATE TABLE forwardings (source varchar(80) NOT NULL, destination TEXT NOT NULL, PRIMARY KEY (source) );
CREATE TABLE users (email varchar(80) NOT NULL, password varchar(20) NOT NULL, PRIMARY KEY (email) );
CREATE TABLE transport ( domain varchar(128) NOT NULL default '', transport varchar(128) NOT NULL default '', UNIQUE KEY domain (domain) );


3. configure letsencrypt

run this command below
certbot certonly --standalone -d mail.truedevidtofa.my.id


4. configure postfix

create file /etc/postfix/mysql-virtual_domains.cf
user = dbmail
password = your_password
dbname = email
query = SELECT domain AS virtual FROM domains WHERE domain='%s'
hosts = 127.0.0.1

create file /etc/postfix/mysql-virtual_email2email.cf
user = dbmail
password = your_password
dbname = email
query = SELECT email FROM users WHERE email='%s'
hosts = 127.0.0.1

create file /etc/postfix/mysql-virtual_forwardings.cf
user = dbmail
password = your_password
dbname = email
query = SELECT destination FROM forwardings WHERE source='%s'
hosts = 127.0.0.1

create file /etc/postfix/mysql-virtual_mailboxes.cf
user = dbmail
password = your_password
dbname = email
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'
hosts = 127.0.0.1

edit file /etc/postfix/master.cf
remove hashtag, for this line
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no

edit file /etc/postfix/main.cf
myhostname = mail.truedevidtofa.my.id
mydomain = truedevidtofa.my.id
myorigin = $myhostname
inet_interfaces = all

add this on the bottom of file
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.truedevidtofa.my.id/cert.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.truedevidtofa.my.id/privkey.pem
smtpd_tls_security_level = encrypt
smtp_tls_security_level = encrypt
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_loglevel = 2

virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_base = /home/vmail

#SASL
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes

#Limit
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

restart postfix systemctl restart postfix


5. configure dovecot

create folder for mail
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m
chown -R vmail.vmail /home/vmail

edit file /etc/dovecot/conf.d/10-mail.conf
find "namespace inbox", then edit look like this
separator = .
mail_location = maildir:/home/vmail/%d/%n/Maildir

edit file /etc/dovecot/conf.d/10-auth.conf look like this
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

edit file /etc/dovecot/conf.d/10-master.conf look like this
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}

edit file /etc/dovecot/conf.d/10-ssl.conf look like this
ssl = yes
ssl_cert = </etc/letsencrypt/live/mail.truedevidtofa.my.id/cert.pem
ssl_key = </etc/letsencrypt/live/mail.truedevidtofa.my.id/privkey.pem

edit file /etc/dovecot/conf.d/15-mailboxes.conf look like this
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Junk {
auto = subscribe
special_use = \Junk
}
mailbox Trash {
auto = subscribe
special_use = \Trash
}

create file /etc/dovecot/dovecot-sql.conf.ext look like this
user_query = SELECT ('5000') as 'uid',('5000') as 'gid'
driver = mysql
connect = host=127.0.0.1 dbname=email user=dbmail password=your_password
default_pass_scheme = SHA256-CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';

edit file /etc/dovecot/conf.d/10-master.conf look like this
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
group = postfix
user = postfix
}
}

restart dovecot service dovecot restart


6. configure opendkim

edit file /etc/opendkim.conf look like this
AutoRestart Yes
AutoRestartRate 10/1h
UMask 002
Syslog yes
SyslogSuccess Yes
LogWhy Yes

Canonicalization relaxed/simple

ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable

Mode sv
PidFile /var/run/opendkim/opendkim.pid
SignatureAlgorithm rsa-sha256

UserID opendkim:opendkim

Socket inet:12301@localhost

edit file /etc/default/opendkim and add following line look like this
SOCKET="inet:12301@localhost"

edit file /etc/postfix/main.cf add following line look like this
#opendkim
milter_protocol = 2
milter_default_action = accept
smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301
non_smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

create directory
mkdir /etc/opendkim
mkdir /etc/opendkim/keys

edit file /etc/opendkim/TrustedHosts
127.0.0.1
localhost
192.168.0.1/24
*.truedevidtofa.my.id

edit file /etc/opendkim/KeyTable
mail._domainkey.truedevidtofa.my.id truedevidtofa.my.id:mail:/etc/opendkim/keys/truedevidtofa.my.id/mail.private

edit file /etc/opendkim/SigningTable
*@truedevidtofa.my.id mail._domainkey.truedevidtofa.my.id

change directory
cd /etc/opendkim/keys
mkdir truedevidtofa.my.id
create opendkim key
opendkim-genkey -s mail -d truedevidtofa.my.id
chown opendkim:opendkim mail.private

add public key to your dns record
cat mail.txt
copy to your dns entry type txt

restart postfix service postfix restart

restart dovecot service dovecot restart

restart opendkim service opendkim restart

thats it

i dont create the image, i got from d1nhio0ox7pgb.cloudfront.net