--- title: "Почтовый сервер на Debian 12: полное руководство от установки до production. Часть 2 - Postfix и Dovecot" date: 2026-03-10 draft: false description: "Установка и настройка Postfix и Dovecot. SMTP/IMAP, виртуальные ящики, авторизация через SASL. Первые тесты отправки и получения почты." tags: ["postfix", "dovecot", "smtp", "imap", "lmtp", "sasl", "Self-hosting"] categories: ["Системное администрирование", "Электронная почта"] series: ["Почтовый сервер на Debian 12"] series_order: 2 --- # Postfix + Dovecot: установка и базовая настройка Сейчас поставим два ключевых компонента почтового сервера: Postfix (прием/отправка) и Dovecot (доступ к ящикам). На выходе получишь работающую систему, через которую можно отправлять и получать почту. Без антивируса, без антиспама, без веб-морды - голый функционал. Но работающий. ## Перед началом Эта инструкция подразумевает, что у тебя: - Debian 12 с базовой настройкой безопасности - Настроены SSH, firewall, fail2ban - Система обновлена > Если еще не настроил - сделай это сейчас: {{< article link="/posts/tips-debian-12-hardening/">}} Дальше считаем, что база готова. ## Подготовка для почтового сервера ### Открываем порты в firewall Почтовому серверу нужны специфичные порты: ```bash sudo ufw allow 25/tcp comment 'SMTP' sudo ufw allow 587/tcp comment 'SMTP Submission' sudo ufw allow 143/tcp comment 'IMAP' sudo ufw allow 993/tcp comment 'IMAPS' ``` Проверь: ```bash sudo ufw status ``` Должны появиться: - 25/tcp (SMTP) - 587/tcp (Submission) - 143/tcp (IMAP) - 993/tcp (IMAPS) ### Проверяем DNS Для почтового сервера DNS - **критично**. Без правильных записей письма не пойдут или улетят в спам. **MX-запись:** ```bash dig +short MX example.com ``` Должно вернуть: ``` 10 mail.example.com. ``` **A-запись:** ```bash dig +short mail.example.com ``` Должен вернуть твой IP. **PTR (обратная зона):** ```bash host твой-IP ``` Должно вернуть: ``` твой-IP.in-addr.arpa domain name pointer mail.example.com. ``` **Если PTR не настроен** - письма будут улетать в спам. Пиши в поддержку хостера, это делается с их стороны. ## Установка Postfix ### Ставим пакет ```bash sudo apt install -y postfix ``` Установщик запустит конфигуратор. **Отменяй его** - настроим вручную. Выбери: - **General type of mail configuration:** No configuration - Нажми OK ### Создаем структуру для хранения почты Проверяем где реальная директория ```bash ls -ld /var/spool/mail ``` Если это симлинк (обычно в Debian) - работаем с /var/mail: ```bash sudo mkdir -p /var/mail/example.com ``` Замени `example.com` на свой домен. Создай системную группу и пользователя для виртуальных ящиков: ```bash sudo groupadd -g 5000 vmail sudo useradd -g vmail -u 5000 -d /var/spool/mail -s /usr/sbin/nologin vmail ``` **Что сделали:** - Создали группу `vmail` с GID 5000 - Создали пользователя `vmail` с UID 5000 - Домашняя директория `/var/spool/mail` - Запрет на логин (`/usr/sbin/nologin`) Назначь владельца: ```bash sudo chown -R vmail:vmail /var/mail sudo chmod -R 770 /var/mail ``` ### Базовая конфигурация Postfix Создай главный конфиг: ```bash sudo nano /etc/postfix/main.cf ``` Вставь: ``` # Общие параметры smtpd_banner = $myhostname ESMTP biff = no append_dot_mydomain = no readme_directory = no compatibility_level = 3.6 # Имя хоста и домен myhostname = mail.example.com mydomain = example.com myorigin = $mydomain # Сеть inet_interfaces = all inet_protocols = ipv4 # Доверенные сети mynetworks = 127.0.0.0/8 # Локальная доставка отключена mydestination = localhost local_recipient_maps = # Виртуальные домены virtual_mailbox_domains = example.com virtual_mailbox_base = /var/spool/mail virtual_mailbox_maps = hash:/etc/postfix/vmailbox virtual_alias_maps = hash:/etc/postfix/virtual virtual_minimum_uid = 100 virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 # Размер сообщений message_size_limit = 52428800 mailbox_size_limit = 0 # Очереди queue_directory = /var/spool/postfix ``` **Замени** `mail.example.com` и `example.com` на свои значения. **Что настроили:** **Общие параметры:** - `smtpd_banner` - приветствие сервера - `biff = no` - отключили уведомления comsat - `append_dot_mydomain = no` - не добавлять домен автоматически - `compatibility_level = 3.6` - уровень совместимости **Имя и домен:** - `myhostname` - полное имя сервера - `mydomain` - основной домен - `myorigin` - от какого домена идут письма **Сеть:** - `inet_interfaces = all` - слушаем на всех интерфейсах - `inet_protocols = ipv4` - только IPv4 (если есть IPv6 - используй `all`) **Доверенные сети:** - `mynetworks` - только localhost (расширим позже) **Локальная доставка:** - `mydestination = localhost` - только для локалхоста - Остальное через виртуальные домены **Виртуальные домены:** - `virtual_mailbox_domains` - список доменов (пока один) - `virtual_mailbox_base` - корневая директория почты - `virtual_mailbox_maps` - файл с ящиками - `virtual_alias_maps` - файл с псевдонимами - `virtual_uid_maps / virtual_gid_maps` - от имени кого хранить файлы **Лимиты:** - `message_size_limit` - максимальный размер письма (50 MB) - `mailbox_size_limit = 0` - без лимита на ящик ### Создаем файлы для виртуальных ящиков **Файл vmailbox** - список почтовых ящиков: ```bash sudo nano /etc/postfix/vmailbox ``` Добавь: ``` admin@example.com example.com/admin/ user@example.com example.com/user/ ``` Формат: `email путь_относительно_virtual_mailbox_base/` **Файл virtual** - псевдонимы: ```bash sudo nano /etc/postfix/virtual ``` Добавь: ``` postmaster@example.com admin@example.com abuse@example.com admin@example.com ``` Формат: `псевдоним куда_перенаправлять` **Создай hash-таблицы:** ```bash sudo postmap /etc/postfix/vmailbox sudo postmap /etc/postfix/virtual ``` Это создаст файлы `.db` - бинарные индексы для быстрого поиска. **Проверь конфиг:** ```bash sudo postfix check ``` Если ошибок нет - молчит. Если есть - исправляй. ### Запускаем Postfix ```bash sudo systemctl enable postfix sudo systemctl start postfix sudo systemctl status postfix ``` Должен быть `active (running)`. ### Проверяем порты ```bash sudo ss -tulnp | grep master ``` Должно быть: ``` tcp LISTEN 0 100 0.0.0.0:25 0.0.0.0:* users:(("master",pid=...)) ``` Postfix слушает порт 25. ## Установка Dovecot ### Ставим пакеты ```bash sudo apt install -y \ dovecot-core \ dovecot-imapd \ dovecot-lmtpd ``` **Что установили:** - `dovecot-core` - ядро - `dovecot-imapd` - IMAP сервер - `dovecot-lmtpd` - LMTP для приема почты от Postfix ### Основной конфиг Dovecot Открой: ```bash sudo nano /etc/dovecot/dovecot.conf ``` Приведи к виду: ``` # Протоколы protocols = imap lmtp # Слушаем на всех интерфейсах IPv4 listen = * # Рабочая директория base_dir = /var/run/dovecot/ # Привет от сервера login_greeting = Dovecot ready. # Отключать клиентов при перезапуске shutdown_clients = yes # Подключаем конфиги из conf.d/ !include conf.d/*.conf ``` ### Настройка аутентификации Открой: ```bash sudo nano /etc/dovecot/conf.d/10-auth.conf ``` Найди и измени: ``` # Разрешаем plaintext auth (потом включим TLS) disable_plaintext_auth = no # Механизмы аутентификации auth_mechanisms = plain login ``` В конце файла закомментируй: ``` #!include auth-system.conf.ext ``` И раскомментируй: ``` !include auth-passwdfile.conf.ext ``` **Что сделали:** - Отключили системную аутентификацию (через /etc/passwd) - Включили аутентификацию через файл паролей ### Настройка файла паролей Открой: ```bash sudo nano /etc/dovecot/conf.d/auth-passwdfile.conf.ext ``` Приведи к виду: ``` passdb { driver = passwd-file args = scheme=CRYPT username_format=%u /etc/dovecot/users } userdb { driver = static args = uid=vmail gid=vmail home=/var/spool/mail/%d/%n } ``` **Что настроили:** **passdb** - база паролей: - `driver = passwd-file` - из файла - `scheme=CRYPT` - хеширование CRYPT - `username_format=%u` - формат логина (email) - `/etc/dovecot/users` - путь к файлу **userdb** - база пользователей: - `driver = static` - статические значения для всех - `uid=vmail gid=vmail` - от имени кого работаем - `home=/var/spool/mail/%d/%n` - путь к ящику **Переменные:** - `%u` - полный email (user@example.com) - `%d` - домен (example.com) - `%n` - локальная часть (user) ### Настройка почтовых ящиков Открой: ```bash sudo nano /etc/dovecot/conf.d/10-mail.conf ``` Найди и измени: ``` # Формат и расположение почты mail_location = maildir:/var/spool/mail/%d/%n # От имени кого работаем mail_uid = vmail mail_gid = vmail # Привилегированная группа mail_privileged_group = vmail # Разрешенные chroot-директории valid_chroot_dirs = /var/spool/mail ``` **Что настроили:** - `mail_location` - формат Maildir, путь к ящикам - `mail_uid / mail_gid` - UID/GID для работы с файлами - `valid_chroot_dirs` - где можно работать ### Настройка LMTP Открой: ```bash sudo nano /etc/dovecot/conf.d/10-master.conf ``` Найди блок `service lmtp` и измени: ``` service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0600 user = postfix group = postfix } } ``` Найди блок `service auth` и добавь: ``` service auth { # Postfix SMTP AUTH unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } # Для самого Dovecot unix_listener auth-userdb { mode = 0600 user = vmail } } ``` **Что настроили:** **service lmtp:** - Создали UNIX-сокет для Postfix - Postfix будет передавать письма через него **service auth:** - Сокет для SMTP AUTH (авторизация в Postfix) - Сокет для внутренних нужд Dovecot ### Отключаем SSL (пока) Открой: ```bash sudo nano /etc/dovecot/conf.d/10-ssl.conf ``` Измени: ``` ssl = no ``` Потом включим с Let's Encrypt. Пока отключаем. ### Создаем файл пользователей ```bash sudo nano /etc/dovecot/users ``` Формат файла: ``` email:password_hash:5000:5000:: ``` Создадим пользователя `admin@example.com` с паролем `SecurePass123`: Генерируем хеш: ```bash sudo doveadm pw -s CRYPT -p SecurePass123 ``` Вернет что-то вроде: ``` {CRYPT}$6$random_salt$hash_here ``` Копируй только часть после `{CRYPT}`, т.е. `$6$random_salt$hash_here`. Запиши в `/etc/dovecot/users`: ``` admin@example.com:$6$random_salt$hash_here:5000:5000:: ``` Создай еще пользователя `user@example.com` с паролем `UserPass456`: ```bash sudo doveadm pw -s CRYPT -p UserPass456 ``` Добавь в файл: ``` admin@example.com:$6$hash1:5000:5000:: user@example.com:$6$hash2:5000:5000:: ``` **Формат строки:** ``` email:hash:uid:gid:gecos:home:shell ``` У нас `home` и `shell` пустые, т.к. используем static userdb. ### Права на файл ```bash sudo chmod 640 /etc/dovecot/users sudo chown root:dovecot /etc/dovecot/users ``` ### Запускаем Dovecot ```bash sudo systemctl enable dovecot sudo systemctl start dovecot sudo systemctl status dovecot ``` Должен быть `active (running)`. ### Проверяем порты ```bash sudo ss -tulnp | grep dovecot ``` Должно быть: ``` tcp LISTEN 0 100 0.0.0.0:143 0.0.0.0:* users:(("dovecot",pid=...)) ``` Dovecot слушает порт 143 (IMAP). ## Интеграция Postfix и Dovecot Сейчас свяжем Postfix и Dovecot, чтобы: - Postfix передавал письма в Dovecot через LMTP - Postfix использовал Dovecot для SMTP AUTH ### Настраиваем Postfix на LMTP Открой: ```bash sudo nano /etc/postfix/main.cf ``` Добавь в конец: ``` # Доставка через Dovecot LMTP virtual_transport = lmtp:unix:private/dovecot-lmtp # SMTP AUTH через Dovecot smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes smtpd_sasl_security_options = noanonymous broken_sasl_auth_clients = yes ``` **Что добавили:** **virtual_transport:** - Письма для виртуальных доменов отправляем в Dovecot через LMTP **SMTP AUTH:** - Используем Dovecot для проверки логинов/паролей - `noanonymous` - запрет анонимного доступа - `broken_sasl_auth_clients` - поддержка старых клиентов ### Настраиваем правила приема/отправки Добавь туда же: ``` # Требовать HELO/EHLO smtpd_helo_required = yes # Правила HELO smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname # Правила получателя smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_non_fqdn_recipient, reject_unknown_recipient_domain # Правила отправителя smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_sender, reject_unknown_sender_domain ``` **Что добавили:** **smtpd_helo_required:** - Требуем команду HELO при подключении **smtpd_helo_restrictions:** - `permit_mynetworks` - свои пропускаем - `permit_sasl_authenticated` - авторизованных пропускаем - `reject_invalid_helo_hostname` - отклоняем невалидные имена - `reject_non_fqdn_helo_hostname` - отклоняем неполные имена - `reject_unknown_helo_hostname` - отклоняем неизвестные имена **smtpd_recipient_restrictions:** - Свои и авторизованных пропускаем - `reject_unauth_destination` - отклоняем для чужих доменов (защита от relay) - `reject_non_fqdn_recipient` - отклоняем неполные адреса получателей - `reject_unknown_recipient_domain` - отклоняем неизвестные домены **smtpd_sender_restrictions:** - Проверяем адреса отправителей ### Настраиваем порт submission (587) Открой: ```bash sudo nano /etc/postfix/master.cf ``` Найди строку `submission` (должна быть закомментирована) и раскомментируй/измени: ``` submission inet n - y - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=may -o smtpd_sasl_auth_enable=yes -o smtpd_reject_unlisted_recipient=no -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject -o smtpd_relay_restrictions=permit_sasl_authenticated,reject ``` **Что настроили:** - Порт 587 для отправки от клиентов - Требуется авторизация - TLS опционален (пока, потом сделаем обязательным) ### Перезагружаем Postfix ```bash sudo postfix reload ``` Проверь статус: ```bash sudo systemctl status postfix ``` Проверь порты: ```bash sudo ss -tulnp | grep master ``` Должно быть: ``` tcp LISTEN 0 100 0.0.0.0:25 ... tcp LISTEN 0 100 0.0.0.0:587 ... ``` ## Первый тест Сейчас проверим, работает ли базовая функциональность. ### Тест 1: Отправка письма через telnet Подключись к SMTP: ```bash telnet localhost 25 ``` Увидишь: ``` 220 mail.example.com ESMTP ``` Выполни команды: ``` EHLO test.local MAIL FROM: RCPT TO: DATA Subject: Test mail This is a test message. . QUIT ``` **Пояснение:** - `EHLO test.local` - представляемся - `MAIL FROM` - от кого письмо - `RCPT TO` - кому письмо - `DATA` - начало тела письма - `.` (точка на отдельной строке) - конец письма - `QUIT` - завершение сессии Если все ОК, увидишь: ``` 250 2.0.0 Ok: queued as 2CAB723BB4 ``` ### Тест 2: Проверка доставки Проверь логи Postfix: ```bash sudo tail -f /var/log/mail.log ``` Ищи строки вроде этой: ``` Mar 16 19:54:34 mail postfix/lmtp[24548]: 634D423BB4: to=, relay=mail.example.com[private/dovecot-lmtp], delay=21, delays=21/0.02/0.02/0.01, dsn=2.0.0, status=sent (250 2.0.0 mPzKDMo1uGnlXwAAt3BTQQ Saved) ``` Проверь файловую систему: ```bash sudo ls -la /var/spool/mail/example.com/user/new/ ``` Должен появиться файл письма. ```bash drwx--S--- 2 vmail vmail 4096 Mar 16 19:57 . drwx--S--- 5 vmail vmail 4096 Mar 16 19:57 .. -rw------- 1 vmail vmail 537 Mar 16 19:52 '1773679952.M948512P24098.mail.example.com,S=537,W=554' -rw------- 1 vmail vmail 537 Mar 16 19:54 '1773680074.M217408P24549.mail.example.com,S=537,W=554' -rw------- 1 vmail vmail 537 Mar 16 19:57 '1773680252.M311184P24696.mail.example.com,S=537,W=554' ``` Посмотри содержимое: ```bash cat /var/spool/mail/example.com/user/new/* ``` Должен быть текст письма. Например: ```bash Return-Path: Delivered-To: user@example.com Received: from mail.example.com by mail.example.com with LMTP id /8HxEHw2uGl4YAAAt3BTQQ (envelope-from ) for ; Mon, 16 Mar 2026 19:57:32 +0300 Received: from test.local (localhost [127.0.0.1]) by mail.example.com (Postfix) with ESMTP id 06AAD23BBA for ; Mon, 16 Mar 2026 18:37:51 +0300 (MSK) Subject: Test mail Message-Id: <20260316153757.06AAD23BBA@mail.example.com> Date: Mon, 16 Mar 2026 18:37:51 +0300 (MSK) From: admin@example.com This is a test message. ``` ### Тест 3: Проверка IMAP Подключись к Dovecot: ```bash telnet localhost 143 ``` Увидишь: ``` * OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ AUTH=PLAIN AUTH=LOGIN] Dovecot ready. ``` Выполни: ``` a1 LOGIN user@example.com UserPass456 a2 SELECT INBOX a3 FETCH 1 BODY[] a4 LOGOUT ``` **Пояснение:** - `a1 LOGIN` - авторизация (логин пароль) - `a2 SELECT INBOX` - открыть папку INBOX - `a3 FETCH 1 BODY[]` - получить тело первого письма - `a4 LOGOUT` - выход Если авторизация прошла: ``` a1 OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY STATUS=SIZE SAVEDATE LITERAL+ NOTIFY SPECIAL-USE] Logged in ``` Если письмо есть: ``` * 1 FETCH (FLAGS (\Seen \Recent) BODY[] {554} Return-Path: Delivered-To: user@example.com Received: from mail.example.com by mail.example.com with LMTP id jdVeOFA1uGkiXgAAt3BTQQ (envelope-from ) for ; Mon, 16 Mar 2026 19:52:32 +0300 Received: from test.local (localhost [127.0.0.1]) by mail.example.com (Postfix) with ESMTP id 2CAB723BB4 for ; Mon, 16 Mar 2026 18:33:46 +0300 (MSK) Subject: Test mail Message-Id: <20260316153352.2CAB723BB4@mail.example.com> Date: Mon, 16 Mar 2026 18:33:46 +0300 (MSK) From: admin@example.com This is a test message. ) ``` ### Тест 4: Отправка с авторизацией Для теста SMTP AUTH нужен base64 логина и пароля. Генерируем: ```bash echo -ne '\000admin@example.com\000SecurePass123' | base64 ``` Где: - `\000` - нулевой байт (NULL, символ с кодом 0) - `username` - логин (admin@example.com) - `\000` - еще один NULL - `password` - пароль (SecurePass123) Вернет что-то вроде: ``` AGFkbWluQGV4YW1wbGUuY29tAFNlY3VyZVBhc3MxMjM= ``` Подключись к порту 587: ```bash telnet localhost 587 ``` Выполни: ``` EHLO test.local AUTH PLAIN AGFkbWluQGV4YW1wbGUuY29tAFNlY3VyZVBhc3MxMjM= MAIL FROM: RCPT TO: DATA Subject: Auth test Test with auth. . QUIT ``` Если авторизация прошла: ``` 235 2.7.0 Authentication successful ``` Письмо должно быть доставлено. ## Что получилось Сейчас у тебя: **Работает:** - Прием почты на порт 25 - Отправка почты через порт 587 с авторизацией - Доступ к ящикам через IMAP на порту 143 - Виртуальные домены и ящики - Псевдонимы **Не работает:** - Шифрование (все по открытому каналу) - Проверка на вирусы - Проверка на спам - Защита от брутфорса - Веб-интерфейс - DKIM подписи Это **рабочий прототип**, но не production-ready решение. ## Типичные проблемы ### Postfix не стартует Проверь логи: ```bash journalctl -u postfix -n 50 ``` Частые причины: - Опечатка в `main.cf` - Порт 25 занят другим процессом - Нет прав на директории Проверь конфиг: ```bash postfix check ``` ### Dovecot не стартует Проверь логи: ```bash journalctl -u dovecot -n 50 ``` Частые причины: - Опечатка в конфигах - Неправильные права на `/etc/dovecot/users` - Порт 143 занят Проверь конфиг: ```bash doveconf -n ``` ### Письма не доставляются Проверь очередь Postfix: ```bash postqueue -p ``` Если письма застряли - смотри причину: ```bash tail -f /var/log/mail.log ``` Частые причины: - Неправильный путь в `vmailbox` - Нет прав на `/var/spool/mail` - LMTP сокет не создан Проверь сокет: ```bash ls -la /var/spool/postfix/private/dovecot-lmtp ``` Должен быть. ### Письма не доставляются: Permission denied Ошибка в логах: ```bash # Permission denied (euid=5000(vmail) missing +x perm: /var/spool/mail) ``` Проверь владельца реальной директории ```bash ls -ld /var/spool/mail # Может быть симлинк ls -ld /var/mail # Реальная директория ``` Исправь права ```bash sudo chown -R vmail:vmail /var/mail sudo chmod 755 /var/mail ``` Проверь вложенные директории ```bash ls -la /var/mail/ ``` ### IMAP не работает Проверь авторизацию вручную: ```bash doveadm auth test user@example.com UserPass456 ``` Должно вернуть: ``` passdb: user@example.com auth succeeded userdb: user@example.com ``` Если не работает: - Проверь хеш пароля в `/etc/dovecot/users` - Проверь права на файл - Проверь логи Dovecot ### SMTP AUTH не работает Проверь сокет: ```bash ls -la /var/spool/postfix/private/auth ``` Должен быть с правами `666` и владельцем `postfix:postfix`. Проверь логи: ```bash grep "sasl" /var/log/mail.log ``` ## Следующий шаг В следующей части настроим защиту: - Антивирус Amavis + ClamAV - Антиспам SpamAssassin - GreyListing через Postgrey - Fail2ban против брутфорса После этого сервер станет безопаснее и перестанет пропускать вирусы и спам.