Перейти к содержанию

Proxmox Mail Gateway

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

Проверено только на тестовом экземпляре

Эта интеграция была создана и проверена на Proxmox Mail Gateway 9, установленном специально для этой цели, а не на боевом. Каждый вызов — это чтение, и формы данных взяты у настоящего почтового шлюза, но никто ещё не запускал её неделями на живом почтовом шлюзе. Сообщите нам, что сломается.

Страница монитора

Помимо общих графиков, монитор Proxmox Mail Gateway показывает три панели, которые читаются из сохранённых опросом данных — открытие страницы никогда не обращается к самому шлюзу:

  • Mail queues — четыре очереди Postfix в том порядке, в котором их читает почтовый администратор: incoming (только что принято), active (доставляется), deferred (доставка не удалась, будет повторена) и hold (задержано правилом). Для каждой показано, сколько в ней сообщений, сколько доменов назначения, самый загруженный из этих доменов и как долго ждёт самое старое сообщение. Очередь, в которой просто есть почта, — нормальный трафик; очередь, удерживающая сообщение более четырёх часов, помечается как Stuck.
  • Mail filtered today — входящие и исходящие сообщения, байты, спам, вирусы, возвраты (bounces), среднее время обработки и то, что было отклонено до доставки (greylisting, чёрные списки, SPF, pregreeting). Столбец на каждый отрезок недавнего окна рисует кривую трафика без запросов к базе временных рядов. Затем три карантина с количеством сообщений и использованием диска и пойманные сегодня вирусы по названиям.
  • Gateway — сначала остановленные службы, затем члены кластера и их состояние синхронизации, затем каждый узел: аптайм, CPU, память, диск, смещение часов, базы сигнатур с их возрастом и вердиктом, сертификаты, истекающие в течение двух недель, ожидающие обновления и статус подписки.

Только количества, никогда содержимое. DumbMonit читает, сколько сообщений лежит в каждом карантине, но никогда тему, отправителя, получателя или тело. Конечные точки статистики по адресам (/statistics/sender, /statistics/receiver, /statistics/contact) не вызываются вообще.

Сегодня, а не последние двадцать четыре часа

GET /statistics/mail агрегирует по локальному дню на шлюзе: PMG игнорирует конец запрошенного окна, день выбирает только starttime. Поэтому DumbMonit запрашивает "сейчас", что даёт итоги с полуночи — ровно то, что показывает собственная панель PMG. Эти серии — gauge, которые сбрасываются в ноль в полночь, а не счётчики: не оборачивайте их в rate(). Недавняя кривая (/statistics/recent) читает сырую таблицу и действительно скользит.

Что отслеживается

Все метрики имеют префикс dumbmonit_pmg_.

Семейство Метрики Метки
Узел node_cpu_percent, node_iowait_percent, node_cpu_count, node_load1/5/15, node_memory_used/total_bytes, node_memory_used_percent, node_swap_used/total_bytes, node_rootfs_used/total/avail_bytes, node_rootfs_percent, node_uptime_seconds, node_clock_offset_seconds (положительное, когда шлюз опережает DumbMonit), node_insync, node_kernel_info, node_version_info (версия API этого узла — в кластере здесь виден тот, что отстал после последнего обновления), version_info node
Очереди queue_messages, queue_domains, queue_oldest_age_seconds queue (incoming, active, deferred, hold)
Почта сегодня mail_count_in/out, mail_bytes_in/out, mail_spam_in/out, mail_virus_in/out, mail_bounces_in/out, mail_junk_in, mail_junk_out (ваши собственные пользователи рассылают мусор: первый признак скомпрометированной учётной записи), mail_junk_percent (отсутствует в день без входящей почты), mail_greylisted, mail_spf_rejects, mail_rbl_rejects, mail_pregreet_rejects, mail_avg_processing_seconds
Пропускная способность mail_rate_in_per_minute, mail_rate_out_per_minute (по последнему полному отрезку недавней кривой)
Оценки спама spam_score_messages level (от 0 до 10; 10 объединяет всё выше)
Вирусы virus_detections (первая десятка дня) virus
Карантины quarantine_messages, quarantine_bytes, quarantine_avg_spam_level kind (spam, virus, attachment)
Службы service_running (1 или 0; серии нет вообще для неустановленного юнита) node, service
Сигнатуры signature_age_seconds, signature_count, signature_update_available node, family (virus, spam), database (main, daily, bytecode или канал SpamAssassin)
Сертификаты certificate_expires_in_seconds node, certificate
Кластер cluster_nodes, cluster_node_insync, cluster_node_healthy (все отсутствуют на автономном шлюзе) node, role
Подписка subscription_active (метки несут точный статус) node, status, level
Обновления node_updates_pending, node_updates_security_pending node
Сбор up, scrape_errors, scrape_duration_seconds

queue_oldest_age_seconds — это нижняя граница. qshape сообщает интервалы возраста (менее 5 мин, 5–10 мин, 10–20 мин и так далее, с удвоением), поэтому DumbMonit хранит нижнюю границу самого старого занятого интервала: сообщение, отнесённое к "не менее 20 минут", может быть возрастом 39 минут. Занижение означает, что оповещение сработает позже, а не раньше, и никогда — по сообщению, которое на самом деле не запоздало.

queue_domains точно на одиночном шлюзе. В кластере очереди по узлам объединяются, а подсчёт ведётся по самым загруженным доменам каждого узла, не более двадцати на узел: сверх этого значение занижено. Дедупликация здесь лучше суммирования, так как два узла одного кластера принимают почту для одних и тех же доменов.

Автономный шлюз отвечает на /config/cluster/status пустым списком. Это шлюз без кластера, а не деградировавший кластер: серия не публикуется, и ни одно правило не может сработать.

Только daily-база ClamAV оценивается по возрасту — и панелью, и правилом. main пересобирается раз или два в год, а bytecode немногим чаще: оценка их по двум дням выводила бы "out of date" круглый год на совершенно актуальном шлюзе. Они по-прежнему показывают возраст, версию и количество сигнатур — но без вердикта. Аналогично, у канала SpamAssassin, который ни разу не загружался, нет даты вообще, а "никогда не обновлялся" — это не "устарел": нет серии, нет вердикта, нет оповещения.

ClamAV записывает дату сборки в собственном формате внутри заголовка .cvd (16 Dec 2025 23-18 +0000, с дефисом там, где все остальные ставят двоеточие), и PMG передаёт её как есть. Если этот формат когда-нибудь изменится, возраст просто будет отсутствовать, а не окажется неверным на пятьдесят лет. То же правило действует везде: значение, которое API не вернул, даёт одной метрикой меньше, но никогда не ноль, выдающий себя за измерение.

Применяемые встроенные правила: Monitor unreachable, Mail queue growing, Mail stuck in the queue, Mail gateway service stopped, Virus signatures out of date, Spam rules out of date, Quarantine filling up, Mail gateway cluster degraded, Mail gateway certificate expiring, Mail gateway updates pending. Уведомления называют соответствующую очередь, службу, базу или узел.

Что подготовить в Proxmox Mail Gateway

Приведённые ниже шаги совпадают с теми, что показывает уведомление рядом с формой. Принцип: пользователь, выделенный для мониторинга, с ролью только для чтения — никогда не та учётная запись, под которой вы входите.

  1. В веб-интерфейсе: Configuration → User Management → Users → Add. Назовите учётную запись так, как указано ниже, задайте длинный пароль, нигде больше не используемый, и отметьте Enabled.

    dumbmonit@pmg
    
  2. Установите её Role в Audit. Это точный минимум только для чтения для всего, что читает DumbMonit: статус узла, службы, очереди postfix, статистика почты, количества в карантине, возраст баз ClamAV и SpamAssassin, статус кластера, сертификаты, подписка и ожидающие обновления. Audit ничего не может изменить, ничего не освобождает из карантина и не читает ни одного письма.

  3. Предпочитаете оболочку? Та же учётная запись одной командой, затем задайте пароль.

    pmgsh create /access/users --userid dumbmonit@pmg --role audit --enable 1 --comment "DumbMonit monitoring"
    
  4. В DumbMonit введите адрес шлюза, например "mail.lan" или "mail.lan:8006", затем имя пользователя этой учётной записи (включая realm) и пароль.

  5. Proxmox Mail Gateway, в отличие от Proxmox VE и Proxmox Backup Server, не выдаёт токены API: входить нужно по имени пользователя и паролю. DumbMonit открывает одну двухчасовую сессию и продлевает её, а не входит при каждом измерении.

Warning

Не используйте повторно учётную запись, под которой вы входите: роль Audit выше может только читать и не может освободить сообщение из карантина или изменить правило. Proxmox Mail Gateway также по умолчанию использует самоподписанный сертификат: если соединение отклоняется по этой причине, отметьте "Accept an unverifiable certificate" в опциях.

Адрес: 10.0.0.40, mail.lan, mail.lan:8006, [fd00::4] или полный URL. Схема https и порт 8006 добавляются, если отсутствуют.

Опции

Ключ Название По умолчанию Справка
port API port 8006 Используется, если в адресе не указан порт.
insecure_tls Accept an unverifiable certificate false Proxmox Mail Gateway по умолчанию поставляется с самоподписанным сертификатом: включите это, если соединение отклоняется по этой причине.
request_timeout_seconds Timeout per request (seconds) 15 Время, отведённое на каждый вызов API, от 1 до 120. Чтение очереди запускает на шлюзе команду Postfix и может занять несколько секунд.
node Monitored node (пусто) Имя узла кластера для мониторинга. Пусто: каждый узел, который перечисляет шлюз.
recent_hours Traffic window (hours) 12 Насколько далеко назад идёт кривая трафика, от 1 до 24. Суточные итоги всегда охватывают текущий день.
queues Watch the mail queues true Читает очереди incoming, active, deferred и hold и возраст самого старого сообщения в каждой.
quarantine Count the quarantines true Читает, сколько сообщений содержат карантины спама и вирусов и сколько диска они занимают. Только количества.
attachment_quarantine Also count the attachment quarantine false У этого карантина нет вызова подсчёта: чтобы посчитать, его нужно перечислить. По умолчанию выключено; сохраняется только число записей.
signatures Watch the signature databases true Читает возраст баз вирусов ClamAV и каналов правил SpamAssassin.
services Watch the services true Читает состояние postfix, pmg-smtp-filter, pmgpolicy и других юнитов каждого узла.
certificates Watch the certificates true Читает сертификаты, которые отдаёт веб-интерфейс, и предупреждает до их истечения.
updates Count pending updates true Перечисляет пакеты, ожидающие обновления, на каждом узле.
subscription Read the subscription true Читает статус подписки каждого узла.

Типичные ошибки

Симптом Вероятная причина
У ClamAV main огромный возраст Ожидаемо: он пересобирается раз или два в год. Вердикт несёт только daily.
Ошибка сертификата Самоподписанный сертификат: установите доверенный (ACME встроен в PMG) или включите insecure_tls.
Ошибка аутентификации Неверный realm в имени пользователя — должно быть dumbmonit@pmg, а не dumbmonit — или учётная запись не Enabled. Весь опрос признаётся неудачным, только если не удался GET /version; любой другой неудавшийся вызов учитывается в scrape_errors.
Недостаточно прав Роль учётной записи ниже Audit. quser видит только собственную почту; helpdesk не может читать ни узел, ни статистику.
Все метрики mail_* равны нулю Шлюз действительно ничего не фильтровал с полуночи. Итоги охватывают текущий локальный день на шлюзе и сбрасываются в его полночь, а не в вашу.
Нет серий service_running вообще Опция services выключена или роль не может их перечислить. Один юнит, отсутствующий в списке, просто не установлен на этом узле (например, chrony на машине с systemd-timesyncd) и намеренно не сообщается как остановленный.
Нет signature_age_seconds для канала SpamAssassin Этот канал ни разу не обновлялся, поэтому PMG не возвращает дату. Выполните sa-update на шлюзе; вторичный канал, который настроен, но ни разу не загружался, намеренно остаётся без даты.
Нет ни одной базы ClamAV ClamAV не установлен или freshclam ни разу не завершил загрузку. Конечная точка отвечает пустым списком, что не является ошибкой.
Нет метрик кластера Шлюз автономный. /config/cluster/status отвечает пустым списком, и ни одно правило кластера не может сработать.
"Mail stuck in the queue" срабатывает поздно queue_oldest_age_seconds — нижняя граница самого старого занятого интервала возраста qshape, поэтому она по замыслу занижает значение.
Отсутствует quarantine_messages{kind="attachment"} Опция attachment_quarantine выключена: у этого карантина нет конечной точки подсчёта, поэтому чтобы посчитать его, нужно его перечислить.