В этой статье я покажу, как настроить свой почтовый сервер для аккаунтов локальных пользователей без веб-морд, docker-ов, телеграм-помоек и LLM-высеров.

Жалкие отп^W^W Дисклеймер: я - админ локалхоста. В статье полно англицизмов и недопереведённых терминов.

Что происходит? Где я? Помогите!

Эта статья — перевод моего же поста, по сути копии вот этого немного устаревшего поста в другом блоге (архивная копия) (далее — «оригинальный гайд»), на который мне в своё время очень повезло наткнуться.

Будем настраивать почтовый сервер так, чтобы у каждого пользователя ОС была своя почта, а письма хранились в ~/Maildir.

Индигриенты ©

Понадобятся нам, собственно, сервер на arch linux с белым IP, доменное имя, сертификат и, желательно, reverse DNS.

Сервер должен быть исключительно и только на arch, на других дистрибутивах поднять почтовый сервер принципиально невозможно.

Reverse DNS нас интересует только тем, что позволяет по IP-адресу получить доменное имя, на этот адрес указывающее, а нужен он нам затем, чтобы у почтовых серверов, с которыми будет общаться наш сервер, была yet another проверка, уменьшающая вероятность попадания нашего сервера в спам-листы.

На самом по себе попадании в спам-листы мои полномочия всё, но для выхода из одного того, в который попадал я, достаточно было ткнуть мышкой одну кнопку на сайте спам-листа.

Вычитать reverse DNS для, например, 8.8.8.8 можно вот так (указывает оно на dns.google, точка в конце нас сейчас не интересует):

$ dig -x 8.8.8.8 | grep -vE "^$|^;"
8.8.8.8.in-addr.arpa.	75882	IN	PTR	dns.google.

Выставить reverse DNS можно либо в админке вашего домашнего провайдера или хостера, либо, как сделал я, написав e-mail в поддержку провайдера и попросив выставить нужное значение reverse DNS для вашего IP-адреса. ИЧСХ, мне сделали это за 15 минут без лишних вопросов, я сильно удивился.

Оригинальный гайд использует self-signed сертификат, я использую let’s encrypt, потому что мне даже думать лень о проблемах, связанных с самоподписными сертификатами. Когда-нибудь, думаю, подумаю о проблемах с let’s encrypt, но Леонид Каневский.

Перед тем, как отправлять письма со своего почтового сервера на реальные адреса внешних серверов прямо в процессе настройки своего сервера с мыслью «я, конечно, гайд не дочитал, но а вдруг оно уже работает», потренируйтесь на кошках, иначе есть риск загреметь в спам-листы.

После того как у вас всё заработает, или после последующих изменений конфигов, делайте бекапы. По крайней мере, dovecot не так давно сломал обратную совместимость конфигов. Если у вас под рукой есть бекап конфигов, вы можете откатить версию postfix/dovecot/whatever из /var/cache/pacman/pkg/, а уже потом, имея рабочую почту, спокойно разбираться с новой версией сломанного софта.

Ниже, как и в оригинальном гайде, пойдут однотипные главы с подглавами, в которых большинство содержимого — команды, показывающие значимые части конфигов, и их, команд, вывод. В оригинальном гайде, который я по сути слямзил, достаточно много поясняющих комментариев. Туда я вас за ними и приглашаю, а здесь будет минимум, необходимый для запуска сервера.

Что вообще делать со всем нижеизложенным? В каждой главе накатывать указанный софт, потом grep-ать по /etc/<tool-name>, в каких конфигах у вас лежит что-то похожее, и доводить эти конфиги до нужной кондиции.

Сертификаты

$ pacman -S certbot
$ certbot -d mydomain.name 

Если у вас это не работает или у вас нет веб-сервера, добро пожаловать в вики: https://wiki.archlinux.org/title/Certbot

Dovecot

https://wiki.archlinux.org/title/Dovecot

Установка

pacman -S dovecot

Настройка

Тип и расположение почты, «папки»

doveconf -n mail_path mail_driver namespace inbox

Вывод:

mail_path = ~/Maildir
mail_driver = maildir
namespace inbox {
  inbox = yes
  separator = /
  mailbox Drafts {
    special_use = "\\Drafts"
  }
  mailbox Junk {
    special_use = "\\Junk"
  }
  mailbox Trash {
    special_use = "\\Trash"
  }
  mailbox Sent {
    special_use = "\\Sent"
  }
  mailbox "Sent Messages" {
    special_use = "\\Sent"
  }
}

Добавляем юзера dovecot в группу mail

usermod -aG mail dovecot
id dovecot

Вывод:

uid=76(dovecot) gid=76(dovecot) groups=76(dovecot),12(mail)

SSL-сертификаты

SSL

doveconf ssl ssl_server_cert_file ssl_server_key_file ssl_server_dh_file

Вывод:

ssl = yes
ssl_server_cert_file = /etc/letsencrypt/live/kostovsky.me/fullchain.pem
ssl_server_key_file = /etc/letsencrypt/live/kostovsky.me/privkey.pem
ssl_server_dh_file = /etc/dovecot/dh.pem

Аутентификация

doveconf -n userdb passdb

Вывод (имена секций здесь выбраны случайно: с некоторой версии dovecot потребовал их, имена, добавить, я и добавил):

userdb fuck_dovecot {
  driver = passwd
}
passdb fuck_dovecot {
  driver = pam
}
cat /etc/pam.d/dovecot

Вывод:

#%PAM-1.0
auth include system-auth
account include system-auth
session include system-auth
password include system-auth

Создаём юзера

Если вдруг у вас его ещё нет. Его логин и будет использоваться в почтовом адресе. У каждого «нормального» пользователя в системе будет свой почтовый ящик, а для логина в почту будет использоваться пароль этого пользователя в ОС.

useradd nikita -m
passwd nikita

Весь итоговый конфиг

Спрятал под спойлер
doveconf -n

Output:

## 2.4.4 (8b687aa65c): /etc/dovecot/dovecot.conf
## OS: Linux 7.1.5-arch1-2 x86_64  
## Hostname: home
## 29 default setting changes since version 2.4.1
dovecot_config_version = 2.4.1
auth_mechanisms = plain
dovecot_storage_version = 2.4.1
mail_driver = maildir
mail_path = ~/Maildir
protocols {
  imap = yes
  lmtp = yes
}
passdb fuck_dovecot {
  driver = pam
}
userdb fuck_dovecot {
  driver = passwd
}
service director {
  listen = * ::
  unix_listener login/director {
  }
  fifo_listener login/proxy-notify {
  }
  unix_listener director-userdb {
  }
}
service imap-login {
  inet_listener imap {
  }
  inet_listener imaps {
  }
}
service pop3-login {
  inet_listener pop3 {
  }
  inet_listener pop3s {
  }
}
service submission-login {
  inet_listener submission {
  }
  inet_listener submissions {
  }
}
namespace inbox {
  inbox = yes
  separator = /
  mailbox Drafts {
    special_use = "\\Drafts"
  }
  mailbox Junk {
    special_use = "\\Junk"
  }
  mailbox Trash {
    special_use = "\\Trash"
  }
  mailbox Sent {
    special_use = "\\Sent"
  }
  mailbox "Sent Messages" {
    special_use = "\\Sent"
  }
}
service lmtp {
  unix_listener lmtp {
  }
}
service imap {
}
service pop3 {
}
service submission {
}
service auth {
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0666
    user = postfix
  }
}
service auth-worker {
}
service dict {
  unix_listener dict {
  }
}
ssl_server {
  cert_file = /etc/letsencrypt/live/kostovsky.me/fullchain.pem
  dh_file = /etc/dovecot/dh.pem
  key_file = /etc/letsencrypt/live/kostovsky.me/privkey.pem
}

Сервис

systemctl enable --now dovecot.service

Если вы используете ufw, загляните в оригинальный гайд, там есть дополнительные настройки и комментарии.

Инструментарий для тестирования

Postfix

https://wiki.archlinux.org/title/Postfix

Установка

pacman -S postfix

Каталоги

postconf -n | grep -E "directory\s"

Вывод:

command_directory = /usr/bin
daemon_directory = /usr/lib/postfix/bin
data_directory = /var/lib/postfix
html_directory = no
manpage_directory = /usr/share/man
meta_directory = /etc/postfix
queue_directory = /var/spool/postfix
readme_directory = /usr/share/doc/postfix
sample_directory = /etc/postfix
shlib_directory = /usr/lib/postfix

Домен

postconf -n | grep ^my

Output:

mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, mail.$mydomain
mydomain = kostovsky.me
myhostname = kostovsky.me
myorigin = $mydomain

Aliases

postconf -n | grep -E "^alias|newaliases"

Вывод:

alias_database = $alias_maps
alias_maps = lmdb:/etc/postfix/aliases
newaliases_path = /usr/bin/newaliases

Catch-all email

«Всеперехватывающий»(?) адрес. Здесь автор оригинального гайда указал пользователя, который будет получать почту (в смысле спам), адресованную несуществующим в системе пользователям. У меня здесь пусто.

postconf -n luser_relay local_recipient_maps

Output:

local_recipient_maps =

Шифруемся с помощью TLS

Получение почты:

postconf -n | grep smtpd_ | grep tls

Вывод:

smtpd_sasl_tls_security_options = noanonymous
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/letsencrypt/live/kostovsky.me/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/kostovsky.me/privkey.pem
smtpd_use_tls = yes

Отправка почты:

postconf -n | grep smtp_ | grep tls

Вывод:

smtp_tls_security_level = may

Аутентификация/авторизация

Конфиг аутентификации postfix:

postconf -n | grep ^smtpd_sasl

Вывод:

smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $mydomain
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
smtpd_sasl_type = dovecot

Интеграция с аутентификацией dovecot

doveconf -n service/auth

Вывод:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0666
    user = postfix
  }
}

Relay (шлюз?) и ограничения

postconf -n | grep -E "helo|relay"

Вывод:

smtpd_helo_required = yes
smtpd_helo_restrictions = reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

Mail submission

Я не знаю, как и есть ли смысл переводить некоторые словосочетания, но перевод “mail submission” не так уж и необходим для настройки сервера.

postconf -M submission

Вывод:

submission inet  n       -       n       -       -       smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_tls_auth_only=yes -o smtpd_reject_unlisted_recipient=no -o smtpd_relay_restrictions= -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING

DNS-запись TXT

drill -Q kostovsky.me TXT
drill -Q smtp.kostovsky.me TXT

Вывод:

"v=spf1 a mx ip4:195.234.21.24 ~all"
"v=spf1 a mx ip4:195.234.21.24 ~all"

Запись reverse DNS

drill -Q 195.234.21.24 -x

Вывод:

kostovsky.me.

Весь итоговый конфиг

Спрятал под спойлер
postconf -n

Вывод:

alias_database = $alias_maps
alias_maps = lmdb:/etc/postfix/aliases
command_directory = /usr/bin
compatibility_level = 3.11
daemon_directory = /usr/lib/postfix/bin
data_directory = /var/lib/postfix
debug_peer_level = 2
debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5
home_mailbox = Maildir/
html_directory = no
inet_protocols = ipv4
local_recipient_maps =
mail_owner = postfix
mailbox_size_limit = 512000000
mailq_path = /usr/bin/mailq
manpage_directory = /usr/share/man
message_size_limit = 512000000
meta_directory = /etc/postfix
milter_default_action = accept
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, mail.$mydomain
mydomain = kostovsky.me
myhostname = kostovsky.me
mynetworks = 10.66.66.0/24
myorigin = $mydomain
newaliases_path = /usr/bin/newaliases
non_smtpd_milters = $smtpd_milters
queue_directory = /var/spool/postfix
readme_directory = /usr/share/doc/postfix
sample_directory = /etc/postfix
sendmail_path = /usr/bin/sendmail
setgid_group = postdrop
shlib_directory = /usr/lib/postfix
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
smtp_tls_security_level = may
smtpd_banner = exim
smtpd_helo_required = yes
smtpd_helo_restrictions = reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname
smtpd_milters = inet:localhost:8891, inet:localhost:8893
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $mydomain
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
smtpd_sasl_type = dovecot
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/letsencrypt/live/kostovsky.me/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/kostovsky.me/privkey.pem
smtpd_use_tls = yes
unknown_local_recipient_reject_code = 550

Сервис

systemctl enable --now postfix.service

Если вы используете ufw, загляните в оригинальный гайд, там есть настройки и комментарии.

Инструментарий для тестирования

Особо упоротые могут быстренько проверить SMTP с помощью openssl:

openssl s_client -connect kostovsky.me:25 -starttls smtp

DomainKeys Identified Mail - DKIM

Установка

https://wiki.archlinux.org/title/OpenDKIM

pacman -S opendkim

Настройка

Минимальный конфиг

grep -v -e '^#' -e '^[[:space:]]*$' /etc/opendkim/opendkim.conf

Вывод:

Canonicalization	  relaxed/simple
Domain			  kostovsky.me
KeyFile			  /etc/opendkim/rig.private
Selector		  rig
Socket                    inet:8891@localhost
Syslog			  Yes
UserID                    opendkim:postfix

Генерация файлов ключей

Generate rig.private and rig.txt files.

opendkim-genkey --restrict --selector rig --domain kostovsky.me --directory /etc/opendkim

Интеграция с postfix

postconf -n | grep milter

Вывод:

milter_default_action = accept
non_smtpd_milters = $smtpd_milters
smtpd_milters = inet:localhost:8891, inet:localhost:8893

Общаться с postfix оно будет через сокет inet:localhost:8891.

DNS-запись TXT

cat /etc/opendkim/rig.txt

Вывод:

rig._domainkey	IN	TXT	( "v=DKIM1; k=rsa; s=email; "
          "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA8dfa8T7Hhn5/nWVivUpeBEs339fa9bCUHN7tqWxchzy5vBw/8Z3/9Pp8XIXo/0GnpOCu0Fh4P27tMnIdH5N4Sy3E/XcNHL7cRAB7gqKjEMuT2S49L7j3g19Dns7qN8rbArC7Krzq5mdHPHk1EqGsytGlv9CMD5gegpUsM7wd3QIDAQAB" )  ; ----- DKIM key rig for kostovsky.me
drill -Q rig._domainkey.kostovsky.me TXT

Вывод:

"v=DKIM1; k=rsa; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA8dfa8T7Hhn5/nWVivUpeBEs339fa9bCUHN7tqWxchzy5vBw/8Z3/9Pp8XIXo/0GnpOCu0Fh4P27tMnIdH5N4Sy3E/XcNHL7cRAB7gqKjEMuT2S49L7j3g19Dns7qN8rbArC7Krzq5mdHPHk1EqGsytGlv9CMD5gegpUsM7wd3QIDAQAB"

Сервис

systemctl enable --now opendkim.service

Инструментарий для тестирования

Domain-based Message Authentication, Reporting and Conformance - DMARC

https://wiki.archlinux.org/title/OpenDMARC

Установка

pacman -S opendmarc

Настройка

Минимальный конфиг

grep -vE "^#|^\s*$" /etc/opendmarc/opendmarc.conf

Вывод:

AuthservID HOSTNAME
IgnoreAuthenticatedClients true
Socket inet:8893@localhost
SPFSelfValidate true
UMask 002

Интеграция с postfix

postconf -n | grep milter

Вывод:

milter_default_action = accept
non_smtpd_milters = $smtpd_milters
smtpd_milters = inet:localhost:8891, inet:localhost:8893

Общаться с postfix оно будет через сокет inet:localhost:8893.

DNS-запись TXT

drill -Q _dmarc.kostovsky.me TXT

Вывод:

"v=DMARC1; p=quarantine; rua=mailto:postmaster@kostovsky.me; ruf=mailto:forensic@kostovsky.me; adkim=s; aspf=s; fo=1; pct=25"

Сервис

systemctl enable --now opendmarc.service

Инструментарий для тестирования

Настройка Thunderbird

У меня весь гуй везде на английском, так что прошу извинить.

Outgoing server

“Account Settings”->“Edit outgoing server…”

  • Server Name: kostovsky.me

  • Port: 587

  • Connection security: STARTTLS

  • Authentication method: Normal password

  • User Name: nikita

Incoming server

“Server settings” section

  • Server Type: IMAP Mail Server

  • Server Name: kostovsky.me

  • Port: 993

  • User Name: nikita

  • Connection security: SSL/TLS

  • Authentication method: Normal password

Вот, вроде бы, всё и готово, но, пожалуйста, без резких движений. Шуруйте на mail-tester или подобный сервис и добивайтесь всех (значимых, содержимое письма не в счёт) зелёных галочек из всех, прежде чем отправить своё первое письмо на реальный внешний почтовый адрес.

Комментарии (11)


  1. xenon
    13.08.2026 14:27

    К этому бы еще статью, как в 2026 сделать нормальный (и бесплатный) антиспам для входящей почты... Везде на больших почтовых провайдерах с этим уже все хорошо, но вот на своем бы научиться. Такое впечатление, что spamassassin, greylisting и DNSBL (и SURBL) - это вчерашний и позавчерашний день. Ясно сейчас как-то лучше можно. Хоть, блин, в нейронку кидай письма! :-)


    1. max9
      13.08.2026 14:27

      как в 2026 сделать нормальный (и бесплатный) антиспам для входящей почты…

      нет и никогда не было. бесплатный в контексте SA значит то, что вы его постоянно дообучаете и пишете правила руками, копаясь в спамерском говне


      1. naky Автор
        13.08.2026 14:27

        Мне кажется, без корпораций будет работать только распределённый подход вроде SponsorBlock. Недавно натыкался на некий Razor, но, к сожалению или к счастью, у меня никогда не было проблемы спама: 99% мусора режется отправкой в помойку всех писем с эмодзи в заголовке или в body, для чего достаточно простого regex-фильтра на клиенте, а у остального есть ссылка Unsubscribe. Если она редиректится через трекеры - достаточно прямого письма спамящей компании с просьбой прекратить (диких спамеров нынче не так много).

        Если нужен одноразовый аккаунт, пользуюсь temp mail.

        Иногда даже хочется, чтобы меня начали спамить, ведь тогда можно будет раскурить, наконец, системы фильтрации спама, но пока что всё довольно прозаично.


        1. max9
          13.08.2026 14:27

          Иногда даже хочется, чтобы меня начали спамить, ведь тогда можно будет раскурить, наконец, системы фильтрации спама, но пока что всё довольно прозаично.

          неблагодарное занятие, поверьте


  1. max9
    13.08.2026 14:27

    pacman -S certbot

    а в арче нет чтоли dehydrated? намного легче, ненужен петон и рут


    1. naky Автор
      13.08.2026 14:27

      а я как-то про dehydrated и не слышал

      спасибо, посмотрю


      1. max9
        13.08.2026 14:27

        как будто бы давно уже стандарт


  1. maxnoosphere
    13.08.2026 14:27

    а как с доставляемостью писем с своего сервера? в крупные почтовые сервисы кладут в спам если нет нормальной репутации у домена?


    1. naky Автор
      13.08.2026 14:27

      Насколько я знаю, ни разу за ~4 года мои письма нигде не пропадали, то есть всё, что мне нужно, всегда доходило адресатам.

      Возможно, что-то попадало кому-то в спам, но я о таком не слышал, да и кто мне будет отчитываться. По крайней мере, в гугловую почту моих знакомых всё нормально прилетает в Inbox, и на все нужные письма я всегда получал ответы.

      Наличие своего домена в спам-листах можно проверить, например, здесь, а потом, в случае чего, нагуглить процедуру выхода из соответствующего спам-листа. Именно про репутацию ничего не скажу: даже как-то и не припомню, чтобы я её отдельно проверял, но spamhaus мне сейчас показывает -1.5 (нужно почистить лишние поддомены), mail-tester - все зелёные галочки, кроме двух замечаний: короткое содержимое тестового письма и отсутствие в нём ссылки для отписки от рассылки.

      Очень часто вижу мнения о том, что с личного сервера всё будет прилетать в спам, но то ли мне очень везёт, то ли это неправда: у меня уже третий IP после двух VPS (OVH и ещё один) и второй домен - ни единого разрыва. Я бы предложил не бояться и пробовать на себе, а на случай проблем с настройкой на гитхабе есть куча готовых решений с докер-образами для ленивых.


  1. pr0l
    13.08.2026 14:27

    как будто mailcow в докер контейнере сильно проще поднять.


    1. naky Автор
      13.08.2026 14:27

      Да, проще, и, возможно, работать оно будет лучше и безопаснее, именно mailcow у меня несколько знакомых и поднимали, но у меня особые тараканы:

      • чисто эстетически не люблю докер там, где можно обойтись без него: неприятно знать о лишнем оверхеде на личном сервере. Плюс поправить свои конфиги проще, чем адаптировать чужой докер-образ под себя (или очень разные докер-образы при наличии привычки держать каждый сервис в докере).

      • люблю управлять софтом через одно место - пакетный менеджер, пусть это даже будут кастомные PKGBUILD/ebuild-ы.

      • (одна из основных причин) спортивный интерес - поднять всё самому в наши дни, когда на каждом углу заявляют, что поднять свой почтовый сервер это сложно, почти невозможно: мол, нужно курить тонны мануалов и разбираться во всех протоколах на уровне разработчика. Оказывается, не так всё и сложно.

      У докера есть свои плюсы вроде изоляции и низкого порога вхождения, но, например, от возни с DNS он вас не избавит, а это добрая половина работы по настройке, я бы сказал.

      Так что описанный в статье вариант скорее для спартанцев или любознательных, а там на вкус и цвет.