From 58fd3fa17ac107227c41418d8ef586f39fb146df Mon Sep 17 00:00:00 2001 From: dttb Date: Sun, 28 Jun 2026 01:43:19 +0300 Subject: [PATCH] =?UTF-8?q?mailcow=20dttb:=20=D1=81=D0=BF=D0=B0=D0=BC-?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81,=20SSL,=20=D0=B0=D0=BF=D0=B4=D0=B5?= =?UTF-8?q?=D0=B9=D1=82=202026-05c,=20BIMI+=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D1=8C,=20Roundcube,=20=D1=81=D0=B1=D0=BE=D1=80=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=87=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - фикс входящего спама: No-SNAT на OpenWrt (видел все письма как 10.0.0.1) - SSL mail-портов: cert из NPM + cron-синхрон на Proxmox - апдейт mailcow 2026-01 -> 2026-05c; урок: forward-zone unbound обязателен (RKN режет рекурсию) - логотип UI, BIMI-SVG (Tiny PS) + хостинг, HTML-подпись - Roundcube на /rc (bind-mount, public_html) - внешний сбор почты Яндексом (IMAP/POP3) - snippets: sync-mailcow-cert.sh, dttb-mail-branding/ Co-Authored-By: Claude Opus 4.8 --- ...epagedevwidgetsservicesnextcloud-если-в.md | 33 +++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 27 +++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 29 ++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 31 ++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 29 ++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 31 ++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 30 ++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 27 +++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 30 ++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 33 +++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 35 +++++++++ ...aildttbrudomainadmin-можешь-найти-креды.md | 30 ++++++++ projects/dttb/mailcow-dttb.md | 68 +++++++++++++++++- snippets/dttb-mail-branding/dttb-bimi.svg | 8 +++ snippets/dttb-mail-branding/dttb-sig-logo.png | Bin 0 -> 9032 bytes snippets/dttb-mail-branding/signature.html | 13 ++++ snippets/sync-mailcow-cert.sh | 50 +++++++++++++ 17 files changed, 502 insertions(+), 2 deletions(-) create mode 100644 notes/claude/2026-06-27-221231-httpsgethomepagedevwidgetsservicesnextcloud-если-в.md create mode 100644 notes/claude/2026-06-27-230518-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-27-230948-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-27-235510-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-002628-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-004249-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-005559-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-010838-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-012719-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-013755-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-014038-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 notes/claude/2026-06-28-014229-httpsmaildttbrudomainadmin-можешь-найти-креды.md create mode 100644 snippets/dttb-mail-branding/dttb-bimi.svg create mode 100644 snippets/dttb-mail-branding/dttb-sig-logo.png create mode 100644 snippets/dttb-mail-branding/signature.html create mode 100644 snippets/sync-mailcow-cert.sh diff --git a/notes/claude/2026-06-27-221231-httpsgethomepagedevwidgetsservicesnextcloud-если-в.md b/notes/claude/2026-06-27-221231-httpsgethomepagedevwidgetsservicesnextcloud-если-в.md new file mode 100644 index 0000000..21097f3 --- /dev/null +++ b/notes/claude/2026-06-27-221231-httpsgethomepagedevwidgetsservicesnextcloud-если-в.md @@ -0,0 +1,33 @@ +--- +date: 2026-06-27 +type: claude-session +session_id: cf0fcbca-45e5-4c86-9af4-0126868e3b68 +started: 2026-06-26T20:32:39.557Z +ended: 2026-06-27T19:12:31.306Z +messages: 7 +tools: [AskUserQuestion, Bash, Edit, Read, TaskOutput, TaskStop, ToolSearch, Workflow, Write, mcp__ccd_session__spawn_task] +tags: [claude, session] +--- + +# https://gethomepage.dev/widgets/services/nextcloud/ если все мои сервисы собрать + +## Запрос + +https://gethomepage.dev/widgets/services/nextcloud/ если все мои сервисы собрать как думаешь? + +## Итог (последний ответ Claude, до 500 симв.) + +Готово. `dash.dttb.ru` → 200, закоммичено. + +## Группа «OpenWrt роутеры» — все 10 + +Веерный скан vault (6 читателей по регионам + сведение) собрал все OpenWrt-роутеры. Пингую каждый по NetBird с дашборда: + +**Онлайн (7):** Дом, Sergey, Lipki, Benelux, НИИКН-VM101, Бужарово Сев.лес, Знаменское-3 +**Down (3):** Olivier (Canal+), Переделки (vault помечал «возможно offline с 08.05»), Красногорск + +Каждая плитка — статус + клик на LuCI. Домашний мониторю по LAN `10.0.0.1` (его NetBird-адрес не отвечает). + + +--- +*Автосохранено из session [`cf0fcbca`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/cf0fcbca-45e5-4c86-9af4-0126868e3b68.jsonl) — 7 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, TaskOutput, TaskStop, ToolSearch, Workflow, Write, mcp__ccd_session__spawn_task* diff --git a/notes/claude/2026-06-27-230518-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-27-230518-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..4b193a7 --- /dev/null +++ b/notes/claude/2026-06-27-230518-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,27 @@ +--- +date: 2026-06-27 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T20:05:18.062Z +messages: 2 +tools: [Bash] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Подтвердилось — вот корень: + +**`@zone[0] name=lan masq=1`** — на LAN-зоне роутера включён masquerade. Входящее письмо идёт `WAN:25 → DNAT → 10.0.0.107`, пакет уходит в LAN-зону, и из-за `masq=1` роутер подменяет source на свой `10.0.0.1`. Поэтому mailcow видит `10.0.0.1` вместо реального IP отправителя — отсюда RDNS_NONE + HFILTER_HOSTNAME_UNKNOWN на всём и R_SPF_FAIL для строгих. + +То есть это **не про `support@`** — бьёт по всем входящим сервера. `support@` просто новый: Bayes не выучил ham, и + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 2 сообщ., тулы: Bash* diff --git a/notes/claude/2026-06-27-230948-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-27-230948-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..0cd4af3 --- /dev/null +++ b/notes/claude/2026-06-27-230948-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,29 @@ +--- +date: 2026-06-27 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T20:09:48.676Z +messages: 3 +tools: [Bash, Edit, Read] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Готово. Записал корень и фикс в [mailcow-dttb.md](projects/dttb/mailcow-dttb.md) (auto-sync на code-server закоммитит). + +## Итог + +**Причина:** на домашнем роутере `10.0.0.1` LAN-зона была с `masq=1` — входящая почта `WAN:25 → 10.0.0.107` SNAT'илась в `10.0.0.1`, и сервер видел этот адрес как отправителя **всех** писем. Отсюда `RDNS_NONE + HFILTER_HOSTNAME_UNKNOWN` (+10.5) на каждом входящем. Новый `support@` тонул, старый ящик вытягивал обученный Bayes. + +**Сделано:** точечное правило `No-SNAT-to + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 3 сообщ., тулы: Bash, Edit, Read* diff --git a/notes/claude/2026-06-27-235510-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-27-235510-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..3f339bd --- /dev/null +++ b/notes/claude/2026-06-27-235510-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,31 @@ +--- +date: 2026-06-27 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T20:55:10.007Z +messages: 5 +tools: [Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Готово по обоим фронтам. + +## SSL (твоя задача) +Сертификат на почтовых портах был просрочен с 2 июня — клиенты IMAP/SMTP на него и ругались. Заменил на свежий из NPM (до 1 авг), поставил авто-синхрон cron'ом, чтобы не повторилось. Все порты (25/465/587/993/995) отдают валидный cert. Web был в порядке. + +→ как соберёшься — кинь письмо с Яндекса на `support@dttb.ru`, проверю score (это с прошлой задачи про спам). + +## MEMORY.md (по требованию хука) +Индекс памяти раздулся до ~28.8 КБ (близко к лимиту + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 5 сообщ., тулы: Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-002628-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-002628-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..4237855 --- /dev/null +++ b/notes/claude/2026-06-28-002628-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,29 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T21:26:28.486Z +messages: 5 +tools: [AskUserQuestion, Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Готово. mailcow обновлён и проверен. + +## Что сделано +- **Снапшот** `pre_update_20260627` (откат: `qm rollback 107 pre_update_20260627`) — удали через недельку стабильной работы. +- **Обновление `2026-01` → `2026-05c`** через `./update.sh -f`. Перед запуском откатил локальные правки конфигов (иначе merge-конфликт), после — проверил. +- **SSL уцелел**: наш cert (до 1 авг) на всех портах, cron-синхрон жив. +- **forward-zone unbound (8.8.8.8) убрал осознанно**: новый unbound резолвит рекурсивно, а forw + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 5 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-004249-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-004249-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..3b37167 --- /dev/null +++ b/notes/claude/2026-06-28-004249-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,31 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T21:42:49.450Z +messages: 6 +tools: [AskUserQuestion, Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Готово — логотип `dttb` стоит. + +## Что сделал +- Поставил монограмму в оба слота mailcow (`MAIN_LOGO` + `MAIN_LOGO_DARK` в Redis) — она на странице входа и в шапке интерфейса. +- Взял **PNG**, а не SVG: в твоём SVG текст нарисован шрифтом `SG`, а когда mailcow грузит логотип как ``, кастомный шрифт недоступен → «dttb» отрисовался бы дефолтным шрифтом. В PNG начертание уже впечёно в растр — выглядит точно как задумано. +- Ужал 2048→1024 (лимит mailcow 1920), вес 54 КБ. + +## Проверь +Открой https: + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 6 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-005559-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-005559-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..f73c106 --- /dev/null +++ b/notes/claude/2026-06-28-005559-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,30 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T21:55:59.940Z +messages: 7 +tools: [AskUserQuestion, Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Сделал, что можно без твоего участия. Итог по двум частям: + +## 1. BIMI (лого у отправителя в инбоксе) +✅ Собрал валидный SVG (конверт, профиль **SVG Tiny PS** — без шрифта, поэтому годен; монограмма со шрифтом `SG` для BIMI не подходит) +✅ Захостил публично: https://mail.dttb.ru/bimi/dttb.svg (проверено из интернета — 200, `image/svg+xml`) +✅ DMARC у тебя `p=quarantine` — BIMI принимает + +**Осталась 1 DNS-запись** — её сам не добавлю (API Spaceweb требует сессию панели, токена нет). Добавь в `vps.sw + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 7 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-010838-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-010838-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..d239344 --- /dev/null +++ b/notes/claude/2026-06-28-010838-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,27 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T22:08:38.835Z +messages: 9 +tools: [AskUserQuestion, Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Готово. Чиню честно: **это была моя ошибка** — при апдейте я убрал forward-zone из unbound, посчитав её устаревшей. На деле она load-bearing: рекурсивный DNS на твоём провайдере режется RKN, поэтому без forward postfix перестал резолвить домены отправителей и отбивал всё входящее (`450 Domain not found`). Несколько секунд после апдейта работало из кеша — это меня и обмануло. + +## Что сделано +- Вернул `forward-zone → 8.8.8.8/1.1.1.1` в unbound + рестарт. +- Проверил: unbound резолвит, postfix прини + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 9 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-012719-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-012719-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..121b7d1 --- /dev/null +++ b/notes/claude/2026-06-28-012719-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,30 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T22:27:19.545Z +messages: 9 +tools: [AskUserQuestion, Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Готово — **Roundcube поставлен и работает.** + +## Как зайти +**https://mail.dttb.ru/rc/** — логин полным адресом + пароль (напр. `support@dttb.ru` / `1qaz!QAZ`). Скин Elastic, заголовок «dttb Mail». Вход проверил — работает. + +## Что под капотом +- Контейнер Roundcube рядом с mailcow, отдаётся **родным nginx на `/rc`** — без нового поддомена и без записи в Spaceweb DNS (wildcard `*.dttb.ru` у тебя нет, иначе пришлось бы тебя просить добавить запись). +- Своя БД, IMAP/SMTP к mailcow внутри docker-сети + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 9 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-013755-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-013755-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..55f91c3 --- /dev/null +++ b/notes/claude/2026-06-28-013755-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,33 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T22:37:55.277Z +messages: 10 +tools: [AskUserQuestion, Bash, Edit, Read, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Всё на стороне mailcow готово: `:995` (POP3S) и `:993` (IMAPS) открыты из интернета, cert валиден, у всех ящиков dttb доступ по imap/pop3 включён. Делать надо **в самом Яндексе** — он будет подключаться к `mail.dttb.ru` и забирать почту. + +## В Яндекс.Почте +Настройки (⚙️) → **Все настройки** → **«Сбор почты с других ящиков»** → добавить ящик. + +Если попросит вручную указать сервер: + +| Параметр | Значение | +|---|---| +| Протокол | **POP3** (сборщик Яндекса работает по POP3) | +| Сервер | `mail.dttb.r + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 10 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, Write* diff --git a/notes/claude/2026-06-28-014038-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-014038-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..925efd7 --- /dev/null +++ b/notes/claude/2026-06-28-014038-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,35 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T22:40:38.301Z +messages: 11 +tools: [AskUserQuestion, Bash, Edit, Read, ToolSearch, WebSearch, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Проверил — я был неправ про «только POP3». Актуально: **сборщик Яндекса работает по IMAP и даже использует его по умолчанию.** + +## IMAP-сбор — параметры (на нашей стороне всё готово) +| Параметр | Значение | +|---|---| +| Протокол | **IMAP** | +| Сервер | `mail.dttb.ru` | +| Порт | `993` | +| Шифрование | **SSL вкл.** | +| Логин | полный адрес, напр. `support@dttb.ru` | +| Пароль | пароль ящика | + +В Яндексе: ⚙️ → Все настройки → «Сбор почты с других ящиков» → ввести адрес+пароль (сервер подхватится сам, + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 11 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, ToolSearch, WebSearch, Write* diff --git a/notes/claude/2026-06-28-014229-httpsmaildttbrudomainadmin-можешь-найти-креды.md b/notes/claude/2026-06-28-014229-httpsmaildttbrudomainadmin-можешь-найти-креды.md new file mode 100644 index 0000000..ef078e0 --- /dev/null +++ b/notes/claude/2026-06-28-014229-httpsmaildttbrudomainadmin-можешь-найти-креды.md @@ -0,0 +1,30 @@ +--- +date: 2026-06-28 +type: claude-session +session_id: ac82ac49-7dd6-476e-9fd0-e10687c8867c +started: 2026-06-27T19:43:29.595Z +ended: 2026-06-27T22:42:29.835Z +messages: 12 +tools: [AskUserQuestion, Bash, Edit, Read, ToolSearch, WebSearch, Write] +tags: [claude, session] +--- + +# https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Запрос + +https://mail.dttb.ru/domainadmin/ можешь найти креды + +## Итог (последний ответ Claude, до 500 симв.) + +Сохранено в [mailcow-dttb.md](projects/dttb/mailcow-dttb.md) — раздел «Внешний сбор почты (Яндекс и др.)»: параметры IMAP/POP3, что Яндекс-сборщик по умолчанию IMAP, разница протоколов и обратное направление (Sync job с Яндекса). + +Заодно за эту сессию в той же заметке уже зафиксировано всё: +- фикс входящего спама (SNAT на роутере) +- SSL mail-портов + авто-синхрон cert из NPM +- апдейт mailcow `2026-05c` + **урок про обязательный forward-zone unbound** +- логотип UI, BIMI + подпись +- Roundcube на ` + +--- +*Автосохранено из session [`ac82ac49`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/ac82ac49-7dd6-476e-9fd0-e10687c8867c.jsonl) — 12 сообщ., тулы: AskUserQuestion, Bash, Edit, Read, ToolSearch, WebSearch, Write* diff --git a/projects/dttb/mailcow-dttb.md b/projects/dttb/mailcow-dttb.md index d82c1e7..cfaa50e 100644 --- a/projects/dttb/mailcow-dttb.md +++ b/projects/dttb/mailcow-dttb.md @@ -6,6 +6,9 @@ tags: [dttb, mail] # Mailcow dttb.ru (VM 107, 10.0.0.107) +> **Версия:** `2026-05c` (обновлено 2026-06-28 с `2026-01` через `./update.sh -f`; снапшот отката `qm snapshot 107` = `pre_update_20260627`, удалить после недели стабильной работы). +> 🚨 **УРОК АПДЕЙТА:** при апдейте откатывал tracked-правки конфигов и НЕ вернул forward-zone в unbound.conf → **почта легла** (postfix не резолвил MX/домены отправителей → reject `450 Domain not found` на всё входящее). Рекурсивный unbound на этом провайдере НЕ работает (RKN режет доступ к корневым DNS), forward-zone — **load-bearing**. Восстановлено возвратом forward-zone (см. ниже). **На будущих апдейтах unbound.conf forward-zone НЕ удалять / вернуть сразу после.** postfix-overrides (main.cf) mailcow восстанавливает сам. + ## Общая информация - **Web UI:** https://mail.dttb.ru (через NPM proxy host #25, SSL cert #106) - **Admin:** admin / 1qaz!QAZ @@ -19,6 +22,8 @@ tags: [dttb, mail] - **Ящики:** - admin@dttb.ru (пароль: 1qaz!QAZ) - noreply@dttb.ru (пароль: 1qaz!QAZ) + - support@dttb.ru (пароль: 1qaz!QAZ) + - (плюс codex1..8@umnybot.ru, assistant@umnybot.ru — контур Александра) ## Подключение - **SMTP:** mail.dttb.ru:587 (STARTTLS) или mail.dttb.ru:465 (SMTPS) @@ -31,8 +36,8 @@ tags: [dttb, mail] - **MAILCOW_HOSTNAME:** mail.dttb.ru - **SKIP_LETS_ENCRYPT:** y (SSL через NPM) - **SKIP_UNBOUND_HEALTHCHECK:** y -- **Unbound:** forward-zone к 8.8.8.8/1.1.1.1 в unbound.conf (обязательно для доставки!) -- **SSL:** self-signed cert для SMTP/IMAP (mail.dttb.ru), NPM cert для HTTPS web +- **Unbound:** ⚠️ **ОБЯЗАТЕЛЬНА forward-zone** к 8.8.8.8/1.1.1.1 в `data/conf/unbound/unbound.conf` (в самом конце файла). Рекурсивный резолвинг на этом провайдере НЕ работает (RKN режет корневые DNS) → без forward почта не доставляется (postfix reject `450 Domain not found`). Это НЕ band-aid, а необходимость. 2026-06-28 убрал по ошибке → положил почту, вернул. Минус 8.8.8.8: Spamhaus отшивает публичные резолверы, но postscreen_dnsbl_sites завязан на конкретные коды 127.0.0.x → ложных reject не даёт. После рестарта unbound даёт резолв через ~5-10 сек (не паниковать раньше). Проверка: `docker exec ...unbound... drill gmail.com @127.0.0.1` (ANSWER:>0). +- **SSL:** web (:443) — cert NPM; mail-порты (25/465/587/993/995) — тот же LE-cert из NPM, синхронизируется cron'ом (см. ниже «SSL на mail-портах») - **Docker контейнеры:** 18 шт (postfix, dovecot, rspamd, nginx, mysql, redis и др.) ## OpenWrt проброс портов → 10.0.0.107 @@ -62,6 +67,65 @@ tags: [dttb, mail] - ⚠️ **PTR отсутствует** — единственная дыра доставляемости. Strict-провайдеры (Gmail → спам, Mail.ru → reject) штрафуют письма с IP без reverse DNS. - ⚠️ **IP = OOO Istranet** (`netname istranet`, RU), не Spaceweb. PTR ставит Istranet (как интернет-провайдер по этому WAN-IP), не регистратор DNS. - 🔸 В DNS висит лишний `TXT @ "mailru-domain: 09KURdxlbSVmAm4O"` — остаток попытки привязать Mail.ru для домена; на Mailcow не влияет, можно убрать. + +## Брендинг писем — BIMI + подпись (2026-06-28) +**Цель:** логотип dttb при отправке писем со всех ящиков. + +**BIMI** (лого-аватар у отправителя в инбоксе Apple Mail и др.; Gmail/Yahoo требуют платный VMC ~$1000/год — пока без него): +- SVG (профиль **SVG Tiny PS**, конверт без текста — шрифт `SG` для BIMI не годится): `data/web/bimi/dttb.svg` на mailcow → публично `https://mail.dttb.ru/bimi/dttb.svg` (200, image/svg+xml, проверено снаружи). Исходник в `snippets/dttb-mail-branding/dttb-bimi.svg`. +- DMARC уже `p=quarantine` — BIMI-eligible. +- **ОСТАЛОСЬ (DNS, у Олега/в Spaceweb-панели vps.sweb.ru):** TXT `default._bimi.dttb.ru` = `v=BIMI1; l=https://mail.dttb.ru/bimi/dttb.svg;`. API sweb требует сессию панели (токена в vault нет) — автоматом не добавить. + +**Подпись с логотипом** (`snippets/dttb-mail-branding/signature.html`, лого-PNG `https://mail.dttb.ru/bimi/dttb-logo.png`): +- Готовый HTML-сниппет под вставку в SOGo (Preferences→Mail) и в клиенты (Thunderbird/iPhone). +- ⚠️ Серверного футера «на всех клиентов» НЕ ставил: вставка тела после DKIM-подписи Rspamd ломает DKIM. Корректный путь — footer-milter ДО Rspamd (отдельный проект, не делал). + +## Внешний сбор почты (Яндекс и др.) — 2026-06-28 +Чтобы внешний сервис (напр. Яндекс) **забирал** почту из ящика dttb.ru к себе. Настраивается **на стороне Яндекса** (он подключается к нам), на mailcow ничего не нужно — `:993`/`:995` открыты из интернета, cert валиден, imap/pop3 у всех ящиков dttb включены (`attributes.imap_access/pop3_access=1`). + +Параметры подключения для любого сборщика: +| | IMAP | POP3 | +|---|---|---| +| Сервер | `mail.dttb.ru` | `mail.dttb.ru` | +| Порт | `993` | `995` | +| Шифрование | SSL | SSL | +| Логин | полный адрес (`support@dttb.ru`) | то же | + +**Яндекс:** ⚙️ → Все настройки → «Сбор почты с других ящиков» → адрес+пароль (сервер подхватится). **Яндекс-сборщик по умолчанию IMAP** (не POP3, как было раньше). IMAP = зеркалит всю структуру папок + статусы, но нельзя выбрать целевую папку. POP3 = только Входящие, зато можно сложить в конкретную папку/метку. Первый сбор за пару минут, далее от неск. раз/час до раза в неск. дней (решает Яндекс). +Справка: https://yandex.ru/support/mail/web/preferences/collector.html + +**Обратное направление** (mailcow забирает с Яндекса в ящик dttb): mailcow UI → ящик → **Sync jobs**, IMAP `imap.yandex.ru:993`, для Яндекса нужен **пароль приложения** (не основной). + +## Roundcube — второй вебмейл (2026-06-28) +Поставлен рядом с SOGo, **на `https://mail.dttb.ru/rc/`** (родной nginx mailcow, без нового поддомена/DNS/NPM — wildcard *.dttb.ru НЕТ). Скин Elastic, заголовок «dttb Mail». +- Контейнер `roundcube-mailcow` (`roundcube/roundcubemail:latest-fpm-alpine`) через `docker-compose.override.yml`. +- БД `roundcube` в mysql-mailcow (юзер `roundcube` / `df8de490bea7641fd34904cc95b29428`), схема создаётся образом сама (`initdb.sh --update`). +- IMAP `ssl://dovecot:993`, SMTP `tls://postfix:587` (внутр. алиасы сети); cert CN=mail.dttb.ru ≠ имя контейнера → в `data/conf/roundcube/extra.php` выключена проверка cert (`imap/smtp_conn_options verify_peer=false`) — трафик внутри docker-бриджа. +- Файлы вебрута: **bind** `./data/web/rc` → `/var/www/html` (НЕ named-том: у nginx mailcow rootfs read-only, том в /web/rc не примонтировать). nginx видит их через существующий `/web`. Новый Roundcube 1.6 — вебрут в `public_html/`, поэтому в nginx alias = `/web/rc/public_html/`, SCRIPT_FILENAME = `/var/www/html/public_html/$rcfile`. +- nginx-локация: `data/conf/nginx/site.roundcube.custom` (подключается через `include site.*.custom` в sites-default). `ROUNDCUBEMAIL_REQUEST_PATH=/rc/`. +- Вход проверен (admin@dttb.ru → 302 _task=mail). Плагины: archive, zipdownload, managesieve. +- ⚠️ На апдейтах mailcow override и data/web/rc untracked — переживают; при больших обновлениях Roundcube — `docker compose pull roundcube-mailcow && up -d` (схема обновится сама). + +## Логотип UI (2026-06-28) +Кастомный логотип `dttb` (монограмма) на странице входа/в шапке. Хранится в **Redis** ключами `MAIN_LOGO` + `MAIN_LOGO_DARK` как `data:image/png;base64,...` (как делает UI → Customize). Поставлен **PNG** (не SVG: в SVG текст шрифтом `SG`, который в `` не доступен → ставится дефолтный). Источник: `~/Downloads/export/dttb-01-monogram.png` (ужат 2048→1024, лимит mailcow 1920). Сброс: UI → Customize → Reset, или `redis-cli DEL MAIN_LOGO MAIN_LOGO_DARK`. + +## SSL на mail-портах (фикс 2026-06-27) +`SKIP_LETS_ENCRYPT=y` → ACME-контейнер mailcow ничего не делает. Cert для mail-портов владеет **NPM** (`npm-106`, ECDSA LE, авто-продление). При установке (Mar 7) его положили в `data/assets/ssl/` **вручную** и забыли про продление → **cert протух 2 июня 2026**, клиенты IMAP/SMTP ругались на сертификат. +**Решение:** авто-синхрон cert из NPM в mailcow. +- Скрипт: `/root/sync-mailcow-cert.sh` на **Proxmox** `10.0.0.250` (копия в `snippets/sync-mailcow-cert.sh`). +- Берёт `pct exec 103 -- cat /data/compose/2/letsencrypt/live/npm-106/{fullchain,privkey}.pem`, сравнивает fingerprint с `10.0.0.107:/opt/mailcow-dockerized/data/assets/ssl/cert.pem`, при отличии — бэкап + замена + reload postfix/dovecot/nginx. +- SSH Proxmox→mailcow по ключу `/root/.ssh/mailcow_sync`. +- Cron: `/etc/cron.d/mailcow-cert-sync` — ежедневно 04:30, лог `/var/log/mailcow-cert-sync.log`. +- Ручной прогон: `/root/sync-mailcow-cert.sh`. +- Cert: ECDSA P-384, LE E-series; пару проверять по pubkey (`openssl rsa` на нём врёт — даёт пустой modulus). + +## ⚠️ КОРНЕВОЙ ФИКС входящего спама (2026-06-27) +Жалоба: письма на `support@dttb.ru` (новый ящик) падают в спам, на старые ящики — нет. +**Корень:** на домашнем OpenWrt (`10.0.0.1`) у LAN-зоны было `masq=1`. Входящее `WAN:25 → DNAT → 10.0.0.107` уходило в LAN-зону и **SNAT'илось в `10.0.0.1`** → postfix/rspamd видели source = `10.0.0.1` для **ВСЕХ** внешних писем. +Следствие на каждом входящем: `RDNS_NONE=2.0` + `HFILTER_HOSTNAME_UNKNOWN=8.5` (+10.5), а у строгих отправителей ещё `R_SPF_FAIL=8.0` (SPF против 10.0.0.1) → reject (так резались «Welcome to NetBird»). Бьёт по всему серверу; старый ящик спасал только обученный Bayes (ham −3..−5), новый `support@` тонул. +**Фикс (UCI, не сырой nft — грабли fw4):** на `10.0.0.1` добавлено `config nat 'No-SNAT-to-Mailcow'` (src=lan, proto=tcp, dest_ip=10.0.0.107, target=ACCEPT) + `fw4 reload`. Стоит в srcnat до masquerade. +**Проверено:** тест с внешнего `89.111.140.86` → rspamd увидел реальный `89.111.140.86` (не `10.0.0.1`). Для отправителей с нормальным PTR/MX/DKIM (Яндекс/Gmail) +10.5 больше не срабатывает. +Не трогал глобальный `lan masq=1` (на нём может висеть VPN/podkop-маршрутизация) — фикс точечный и обратимый (`uci delete firewall.@nat[0]`). - 🔸 **SSH-доступ к VM не работает ни одним ключом** (id_rsa «claude-code-matrix-project», id_ed25519, ключ Proxmox). VM клонирована с НИИКН VM 106 → несёт чужой authorized_keys. Управление возможно через web-UI (admin/1qaz!QAZ); для шелла — добавить ключ через Proxmox console. ## Вариант «почтовый шлюз через VPS» (оценка 2026-06-18) diff --git a/snippets/dttb-mail-branding/dttb-bimi.svg b/snippets/dttb-mail-branding/dttb-bimi.svg new file mode 100644 index 0000000..3dcf48e --- /dev/null +++ b/snippets/dttb-mail-branding/dttb-bimi.svg @@ -0,0 +1,8 @@ + +dttb + + + + + + diff --git a/snippets/dttb-mail-branding/dttb-sig-logo.png b/snippets/dttb-mail-branding/dttb-sig-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e1efae09ba1c01112f22516b1a7e87cf742d5daa GIT binary patch literal 9032 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 literal 0 HcmV?d00001 diff --git a/snippets/dttb-mail-branding/signature.html b/snippets/dttb-mail-branding/signature.html new file mode 100644 index 0000000..b8c828a --- /dev/null +++ b/snippets/dttb-mail-branding/signature.html @@ -0,0 +1,13 @@ + + + + + +
+ dttb + +
Олег Батлаев
+
dttb.ru
+ +
diff --git a/snippets/sync-mailcow-cert.sh b/snippets/sync-mailcow-cert.sh new file mode 100644 index 0000000..b80847f --- /dev/null +++ b/snippets/sync-mailcow-cert.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# sync-mailcow-cert.sh +# Копирует LE-сертификат mail.dttb.ru из NPM (LXC 103) в mailcow (VM 107) +# и перезагружает почтовые сервисы ТОЛЬКО при изменении сертификата. +# Причина: mailcow с SKIP_LETS_ENCRYPT=y не продлевает cert сам; cert владеет NPM. +# История: cert на mail-портах протух 2026-06-02, чинили вручную 2026-06-27. +set -euo pipefail + +NPM_CTID=103 +NPM_DIR="/data/compose/2/letsencrypt/live/npm-106" +MC_HOST="root@10.0.0.107" +MC_KEY="/root/.ssh/mailcow_sync" +MC_SSL="/opt/mailcow-dockerized/data/assets/ssl" +SSHMC="ssh -i $MC_KEY -o StrictHostKeyChecking=no -o ConnectTimeout=10 $MC_HOST" + +TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT + +pct exec "$NPM_CTID" -- cat "$NPM_DIR/fullchain.pem" > "$TMP/cert.pem" +pct exec "$NPM_CTID" -- cat "$NPM_DIR/privkey.pem" > "$TMP/key.pem" + +# sanity-проверки +openssl x509 -in "$TMP/cert.pem" -noout >/dev/null 2>&1 || { echo "$(date '+%F %T') ERR: битый cert из NPM"; exit 1; } +[ -s "$TMP/key.pem" ] || { echo "$(date '+%F %T') ERR: пустой key из NPM"; exit 1; } +CPUB=$(openssl x509 -in "$TMP/cert.pem" -noout -pubkey | openssl md5) +KPUB=$(openssl pkey -in "$TMP/key.pem" -pubout 2>/dev/null | openssl md5) +[ "$CPUB" = "$KPUB" ] || { echo "$(date '+%F %T') ERR: cert и key не пара"; exit 1; } + +NEW=$(openssl x509 -in "$TMP/cert.pem" -noout -fingerprint -sha256) +CUR=$($SSHMC "openssl x509 -in $MC_SSL/cert.pem -noout -fingerprint -sha256" 2>/dev/null || echo none) +if [ "$NEW" = "$CUR" ]; then + echo "$(date '+%F %T') cert не изменился — пропуск" + exit 0 +fi + +echo "$(date '+%F %T') обнаружен новый cert — деплой" +scp -i "$MC_KEY" -o StrictHostKeyChecking=no "$TMP/cert.pem" "$TMP/key.pem" "$MC_HOST:/tmp/" +$SSHMC " + set -e + cd /opt/mailcow-dockerized + TS=\$(date +%Y%m%d-%H%M%S) + cp $MC_SSL/cert.pem $MC_SSL/cert.pem.bak-\$TS + cp $MC_SSL/key.pem $MC_SSL/key.pem.bak-\$TS + mv /tmp/cert.pem $MC_SSL/cert.pem + mv /tmp/key.pem $MC_SSL/key.pem + chmod 644 $MC_SSL/cert.pem; chmod 600 $MC_SSL/key.pem + docker compose exec -T postfix-mailcow postfix reload >/dev/null 2>&1 || docker compose restart postfix-mailcow + docker compose exec -T dovecot-mailcow dovecot reload >/dev/null 2>&1 || docker compose restart dovecot-mailcow + docker compose exec -T nginx-mailcow nginx -s reload >/dev/null 2>&1 || true +" +echo "$(date '+%F %T') задеплоен: $NEW"