*Cube-Host– full cloud services!!

Running your own mail server is possible, but “it works” and “it delivers to Inbox” are two different things. Deliverability depends on your IP reputation, correct DNS (SPF/DKIM/DMARC), and reverse DNS (PTR). This guide shows a practical baseline setup: Postfix + TLS + authenticated submission + (optional) Dovecot for IMAP.
For stable performance and full control over networking (PTR/rDNS, firewall rules, ports), start with a clean Linux VPS or choose scalable VPS hosting if you expect growth and need more resources later.
Use Ubuntu 22.04/24.04 LTS (recommended). Replace example.com with your domain and mail.example.com with your server hostname.
sudo -i
apt update && apt -y upgrade
apt -y install ca-certificates curl ufw nano unzip dnsutils
# Set hostname
hostnamectl set-hostname mail.example.com
# Make sure /etc/hosts has a local mapping (adjust IP if needed)
nano /etc/hosts
# Set timezone (pick yours)
timedatectl set-timezone Europe/Kyiv
timedatectl status
Minimal safe baseline: SSH, SMTP (25) for inbound mail, and Submission (587) for authenticated sending. If you add Dovecot IMAP, open 993 too.
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
ufw allow 25/tcp
ufw allow 587/tcp
# Optional (IMAPS)
ufw allow 993/tcp
ufw enable
ufw status verbose
Install Postfix and a minimal mail utility. During setup select Internet Site and set system mail name to example.com.
apt -y install postfix mailutils
systemctl enable --now postfix
systemctl status postfix --no-pager
# See active Postfix settings
postconf -n
These settings are a practical baseline to avoid becoming an open relay and to support authenticated sending later.
postconf -e "myhostname = mail.example.com"
postconf -e "mydomain = example.com"
postconf -e "myorigin = $mydomain"
postconf -e "inet_interfaces = all"
postconf -e "inet_protocols = all"
postconf -e "mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain"
# Only local networks are trusted
postconf -e "mynetworks = 127.0.0.0/8 [::1]/128"
# IMPORTANT: relay restrictions (prevents open relay)
postconf -e "smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"
postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"
systemctl restart postfix
postconf -n | sed -n '1,120p'
For Let’s Encrypt, your DNS A-record must already point to this server. If you cannot open port 80, use DNS challenge instead; below is the simplest “standalone” flow.
# Temporarily allow port 80 for cert issuing
ufw allow 80/tcp
apt -y install certbot
certbot certonly --standalone -d mail.example.com
# Tighten firewall after issuance if you don’t host a website
ufw delete allow 80/tcp
# Configure Postfix TLS
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtp_tls_security_level = may"
postconf -e "smtpd_tls_loglevel = 1"
postconf -e "smtpd_tls_protocols = !SSLv2, !SSLv3"
postconf -e "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3"
systemctl restart postfix
Port 25 is for server-to-server mail exchange. For users/apps, use 587 with authentication + TLS. This reduces abuse and improves deliverability.
Edit /etc/postfix/master.cf and enable the submission service (and optionally smtps 465). Keep it simple: allow only authenticated users.
nano /etc/postfix/master.cf
Add or uncomment this block (adjust if it already exists):
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
If you only need sending for apps, you can skip IMAP. If you want real mailboxes (Thunderbird/Outlook/webmail), install Dovecot and use IMAPS (993).
apt -y install dovecot-imapd dovecot-pop3d
systemctl enable --now dovecot
systemctl status dovecot --no-pager
Set Maildir format and enable secure authentication:
# Mail location
nano /etc/dovecot/conf.d/10-mail.conf
# Set:
# mail_location = maildir:~/Maildir
# Authentication (recommended)
nano /etc/dovecot/conf.d/10-auth.conf
# Ensure:
# disable_plaintext_auth = yes
# auth_mechanisms = plain login
Expose Dovecot auth socket for Postfix SASL:
nano /etc/dovecot/conf.d/10-master.conf
# In the service auth section, ensure you have:
# unix_listener /var/spool/postfix/private/auth {
# mode = 0660
# user = postfix
# group = postfix
# }
Enable SASL in Postfix and restart both services:
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_sasl_auth_enable = yes"
postconf -e "smtpd_tls_auth_only = yes"
systemctl restart dovecot
systemctl restart postfix
Without correct DNS, your mail will often land in spam (or be rejected). Use the following baseline records (examples shown).
| Record | Name | Value (example) | Notes |
|---|---|---|---|
| A | 203.0.113.10 | mail.example.com → server IP | |
| MX | @ | mail.example.com | Priority 10 |
| PTR | 203.0.113.10 | mail.example.com | Set in VPS/provider panel |
| TXT (SPF) | @ | v=spf1 mx a ip4:203.0.113.10 -all | Adjust IP(s) as needed |
| TXT (DMARC) | _dmarc | v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1 | Start with p=none, then tighten |
DKIM adds a cryptographic signature to outgoing mail. Receivers use it to confirm messages are not forged and were not modified in transit.
apt -y install opendkim opendkim-tools
mkdir -p /etc/opendkim/keys/example.com
opendkim-genkey -D /etc/opendkim/keys/example.com/ -d example.com -s mail
chown -R opendkim:opendkim /etc/opendkim/keys/example.com
chmod 750 /etc/opendkim/keys/example.com
chmod 640 /etc/opendkim/keys/example.com/mail.private
Create tables for keys and signing:
nano /etc/opendkim/KeyTable
# Add:
# mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com/mail.private
nano /etc/opendkim/SigningTable
# Add:
# *@example.com mail._domainkey.example.com
nano /etc/opendkim/TrustedHosts
# Add:
# 127.0.0.1
# localhost
# *.example.com
Make OpenDKIM socket accessible for Postfix (Ubuntu smtpd is commonly chrooted). Use a socket inside Postfix spool:
mkdir -p /var/spool/postfix/opendkim
chown opendkim:postfix /var/spool/postfix/opendkim
chmod 750 /var/spool/postfix/opendkim
nano /etc/opendkim.conf
# Ensure these lines exist / match:
# Socket local:/var/spool/postfix/opendkim/opendkim.sock
# KeyTable /etc/opendkim/KeyTable
# SigningTable refile:/etc/opendkim/SigningTable
# ExternalIgnoreList /etc/opendkim/TrustedHosts
# InternalHosts /etc/opendkim/TrustedHosts
Connect the DKIM milter in Postfix:
postconf -e "milter_default_action = accept"
postconf -e "milter_protocol = 6"
postconf -e "smtpd_milters = unix:opendkim/opendkim.sock"
postconf -e "non_smtpd_milters = $smtpd_milters"
systemctl restart opendkim
systemctl restart postfix
Add DKIM DNS record: open /etc/opendkim/keys/example.com/mail.txt and publish its TXT value as mail._domainkey for your domain.
Check logs first — they tell you exactly what’s wrong.
tail -n 200 /var/log/mail.log
postqueue -p
mailq
Install swaks for clean SMTP testing (great for debugging submission 587):
apt -y install swaks
# Example (replace values). Use 587 with TLS:
swaks --to you@example.net --from test@example.com
--server mail.example.com --port 587 --tls
--auth LOGIN --auth-user testuser --auth-password 'StrongPassword'
reject_unauth_destination in restrictions)./etc/postfix, /etc/dovecot, /etc/opendkim, and your Let’s Encrypt certs.If you’re building mail infrastructure for a project, start on a stable Linux VPS (full root access and predictable resources). For scaling and upgrades without migration stress, consider VPS hosting.