In this article we will walk you through the installation and configuration of a mail server with virtual domains and users using Postfix, Dovecot and OpenDKIM on Ubuntu. By using virtual domains and users, you can set up unlimited email accounts without creating system users. This should work on other Linux VPS systems as well but was tested and written for Ubuntu.
Set the Hostname & FQDN
To check the existing FQDN, run the following command
hostname -f
which should display something like localhost or host.domain.com If you see localhost, proceed with the following steps:
- Add your FQDN to the /etc/hosts file
- Add your FQDN to the /etc/hostname file and run
service hostname start
Install all the necessary packages
debconf-set-selections <<< "postfix postfix/mailname string $(hostname -f)" debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'" apt-get update apt-get install -y procmail postfix dovecot-core dovecot-pop3d dovecot-imapd opendkim opendkim-tools
Create a Virtual Email user
groupadd -g 5000 vmail useradd -u 5000 -g vmail -s /sbin/nologin -d /home/vmail -m vmail usermod -aG vmail postfix usermod -aG vmail dovecot DOMAIN="yourDomain.com" mkdir -p /var/mail/vhosts/${DOMAIN} chown -R vmail:vmail /var/mail/vhosts chmod -R 775 /var/mail/vhosts
Generate SSL Certificate
SSL_DIR="/etc/dovecot/ssl" # Certificate details; replace items in angle brackets with your own info SUBJ=" C=US ST=New York O=${DOMAIN} localityName=NYC commonName=${DOMAIN} organizationalUnitName=IT emailAddress=admin@${DOMAIN} " # Empty passphrase PASSPHRASE="" # Makedir for certs mkdir -p ${SSL_DIR} # Generate the server private key openssl genrsa -out "${SSL_DIR}/${DOMAIN}.key" 2048 # Generate the CSR openssl req \ -new \ -batch \ -subj "$(echo -n "$SUBJ" | tr "\n" "/")" \ -key "${SSL_DIR}/${DOMAIN}.key" \ -out "${SSL_DIR}/${DOMAIN}.csr" \ -passin env:PASSPHRASE # Generate the cert (good for 10 years) openssl x509 -req -days 3650 -in "${SSL_DIR}/${DOMAIN}.csr" -signkey "${SSL_DIR}/${DOMAIN}.key" -out "${SSL_DIR}/${DOMAIN}.crt"
Configure OpenDKIM
OPENDKIM_DIR="/etc/opendkim/keys/" # MY_IP MY_IP=$(ip route get 8.8.8.8 | awk '/8.8.8.8/ {print $NF}') mkdir -p ${OPENDKIM_DIR}/${DOMAIN} opendkim-genkey -r -s default -d ${DOMAIN} -D ${OPENDKIM_DIR}/${DOMAIN} cat > /etc/opendkim.conf <<EOF AutoRestart Yes UMask 002 Syslog yes AutoRestartRate 10/1h Canonicalization relaxed/simple ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts KeyTable refile:/etc/opendkim/KeyTable LogWhy Yes Mode sv PidFile /var/run/opendkim/opendkim.pid SignatureAlgorithm rsa-sha256 SigningTable refile:/etc/opendkim/SigningTable Socket inet:8891@localhost SyslogSuccess Yes TemporaryDirectory /var/tmp UserID opendkim:opendkim EOF cat > /etc/opendkim/TrustedHosts <<EOF 127.0.0.1 localhost ${DOMAIN} ${MY_IP} EOF cat > /etc/opendkim/SigningTable <<EOF *@${DOMAIN} default._domainkey.${DOMAIN} EOF cat > /etc/opendkim/KeyTable <<EOF default._domainkey.${DOMAIN} ${DOMAIN}:default:/etc/opendkim/keys/${DOMAIN}/default.private EOF chown -R opendkim: /etc/opendkim
Configure Postfix
# Configure postfix main.cf postconf -e "smtpd_banner = \$myhostname ESMTP" postconf -e "mydomain = ${DOMAIN}" postconf -e "myorigin = \$mydomain" postconf -e "mydestination = localhost, localhost.localdomain, $(hostname -f)" postconf -e "virtual_mailbox_domains = /etc/postfix/virtual_domains" postconf -e "virtual_mailbox_base = /var/mail/vhosts" postconf -e "virtual_mailbox_maps = hash:/etc/postfix/vmailbox" postconf -e "virtual_alias_maps = hash:/etc/postfix/virtual_alias" postconf -e "virtual_minimum_uid = 100" postconf -e "virtual_uid_maps = static:5000" postconf -e "virtual_gid_maps = static:5000" postconf -e "virtual_transport = virtual" postconf -e "dovecot_destination_recipient_limit = 1" postconf -e "smtpd_sasl_auth_enable = yes" postconf -e "smtpd_sasl_type = dovecot" postconf -e "smtpd_sasl_path = private/auth" postconf -e "smtpd_sasl_security_options = noanonymous" postconf -e "smtpd_sasl_local_domain = \$mydomain" postconf -e "broken_sasl_auth_clients = yes" postconf -e "smtpd_tls_security_level = may" postconf -e "smtpd_tls_auth_only = no" postconf -e "smtpd_tls_cert_file=${SSL_DIR}/${DOMAIN}.crt" postconf -e "smtpd_tls_key_file=${SSL_DIR}/${DOMAIN}.key" postconf -e "smtpd_tls_received_header = yes" postconf -e "tls_random_source = dev:/dev/urandom" postconf -e "smtpd_tls_security_level = may" postconf -e "smtp_tls_security_level = may" postconf -e "smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_invalid_hostname, reject_unknown_client, reject_rbl_client sbl-xbl.spamhaus.org" postconf -e "smtpd_sender_restrictions = permit_mynetworks, reject_unknown_address, reject_unknown_sender_domain, reject_non_fqdn_sender" postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination" postconf -e "smtpd_recipient_limit = 250" postconf -e "milter_default_action = accept" postconf -e "milter_protocol = 6" postconf -e "smtpd_milters = inet:127.0.0.1:8891" postconf -e "non_smtpd_milters = inet:127.0.0.1:8891" # Configure postfix master.cf sed -i '/^#smtpd.*/ s/^#//' /etc/postfix/master.cf vi /etc/postfix/master.cf # Add the following lines at the end: dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient} cat > /etc/postfix/virtual_alias <<EOF # Example # @${DOMAIN} admin@${DOMAIN} EOF postmap /etc/postfix/virtual_alias cat > /etc/postfix/virtual_domains <<EOF ${DOMAIN} OK EOF postmap /etc/postfix/virtual_domains touch /etc/postfix/vmailbox postmap /etc/postfix/vmailbox
Configure Dovecot
cat > /etc/dovecot/dovecot.conf <<EOF auth_mechanisms = plain login disable_plaintext_auth = no log_path = /var/log/dovecot mail_location = maildir:/var/mail/vhosts/%d/%n passdb { args = /var/mail/vhosts/%d/shadow driver = passwd-file } protocols = imap pop3 service auth { unix_listener /var/spool/postfix/private/auth { group = vmail mode = 0660 user = postfix } unix_listener auth-master { group = vmail mode = 0600 user = vmail } } ssl_cert = <${SSL_DIR}/${DOMAIN}.crt ssl_key = <${SSL_DIR}/${DOMAIN}.key userdb { args = /var/mail/vhosts/%d/passwd driver = passwd-file } protocol lda { auth_socket_path = /var/run/dovecot/auth-master hostname = $(hostname -f) mail_plugin_dir = /usr/lib/dovecot/modules mail_plugins = sieve postmaster_address = postmaster@${DOMAIN} } EOF touch /var/log/dovecot chgrp vmail /var/log/dovecot chmod 660 /var/log/dovecot
Restart all services
service dovecot restart service postfix restart service opendkim restart
That’s it! If you followed all steps correctly, your email server should be fully functional.
Adding new email accounts
You can use the following script to add a new email account. Save the script as ‘add_new_account’, use chmod to make it executable and then run it passing two parameters:
./add_new_account <email@account> <password>
#!/bin/bash # sudo ./add_new_account <email@account> <password> # Functions ok() { echo -e '\e[32m'${1}'\e[m'; } # Green die() { echo -e '\e[1;31m'${1}'\e[m'; exit 1; } # Red # Sanity check [ $(id -g) != "0" ] && die "Script must be run as root." [ $# != "2" ] && die "Usage: $(basename $0) email@account password" [ ! -f /usr/sbin/postfix ] && die "Postfix is not installed" [ ! -f /usr/bin/doveadm ] && die "Dovecot is not installed" # Variables VMAIL=vmail VMAIL_UID=5000 VMAIL_GUID=5000 ADDRESS=${1} PASSWD=${2} USERNAME=${ADDRESS%@*} DOMAIN=${ADDRESS##*@} # Get the Mailbox Base Directory BASEDIR=$(postconf virtual_mailbox_base) BASEDIR=${BASEDIR#*= } # Get the Mailbox Maps File MAPSFILE=$(postconf virtual_mailbox_maps) MAPSFILE=${MAPSFILE#*:} # Check if account exist if grep -wq "^${ADDRESS}" ${MAPSFILE} then die "The mail address ${ADDRESS} already exist" fi if [[ ( -f ${MAPSFILE} && -d ${BASEDIR} ) ]]; then echo "$ADDRESS $DOMAIN/$USERNAME/" >> ${MAPSFILE} postmap ${MAPSFILE} if [[ $? -eq 0 ]]; then echo ${ADDRESS}::${VMAIL_UID}:${VMAIL_GUID}::${BASEDIR}/${DOMAIN}/${ADDRESS} >> ${BASEDIR}/${DOMAIN}/passwd echo ${ADDRESS}":"$(doveadm pw -p $PASSWD) >> ${BASEDIR}/${DOMAIN}/shadow chown ${VMAIL}: $BASEDIR/${DOMAIN}/{passwd,shadow} chmod 775 ${BASEDIR}/${DOMAIN}/{passwd,shadow} service postfix reload ok "The email account has been addedd" fi else die "Mailbox maps file or mailbox base directory doesn't exist" fi
PS. If you liked this post please share it with your friends on the social networks or simply leave a reply below. Thanks.
Leave a Reply