Commit 5b905842 authored by Vitaly Lipatov's avatar Vitaly Lipatov

Add referenced memory files

parent 78ba638f
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
## Правила работы ## Правила работы
- [feedback_no_unauthorized_actions.md](feedback_no_unauthorized_actions.md) — НЕ самовольничать на серверах - [feedback_no_unauthorized_actions.md](feedback_no_unauthorized_actions.md) — НЕ самовольничать на серверах
- [feedback_clarify_ambiguous_no.md](feedback_clarify_ambiguous_no.md) — Короткое «нет X» ≠ «делай Y». При multi-choice уточнять, не интерпретировать самостоятельно
- [feedback_no_manual_override.md](feedback_no_manual_override.md) — НЕ вмешиваться в автоматику - [feedback_no_manual_override.md](feedback_no_manual_override.md) — НЕ вмешиваться в автоматику
- [feedback_alt_bugzilla_defaults.md](feedback_alt_bugzilla_defaults.md) — ALT Bugzilla: priority=P5, rep_platform=x86_64 - [feedback_alt_bugzilla_defaults.md](feedback_alt_bugzilla_defaults.md) — ALT Bugzilla: priority=P5, rep_platform=x86_64
- [feedback_dnsroot_danger.md](feedback_dnsroot_danger.md) — НИКОГДА не менять dnsRoot в AD crossRef - [feedback_dnsroot_danger.md](feedback_dnsroot_danger.md) — НИКОГДА не менять dnsRoot в AD crossRef
...@@ -47,6 +48,10 @@ ...@@ -47,6 +48,10 @@
- [feedback_upgrade_sisyphus.md](feedback_upgrade_sisyphus.md) — обновление LXC ALT p11 → Sisyphus - [feedback_upgrade_sisyphus.md](feedback_upgrade_sisyphus.md) — обновление LXC ALT p11 → Sisyphus
- [feedback_skill_confirmation_direct.md](feedback_skill_confirmation_direct.md) — подтверждения от skill'ов спрашивать напрямую, не через lavtomate - [feedback_skill_confirmation_direct.md](feedback_skill_confirmation_direct.md) — подтверждения от skill'ов спрашивать напрямую, не через lavtomate
- [feedback_no_routes_on_remote_nat_peers.md](feedback_no_routes_on_remote_nat_peers.md) — НЕ добавлять маршруты на удалённой машине за NAT при настройке туннелей; MASQUERADE на нашей стороне достаточно - [feedback_no_routes_on_remote_nat_peers.md](feedback_no_routes_on_remote_nat_peers.md) — НЕ добавлять маршруты на удалённой машине за NAT при настройке туннелей; MASQUERADE на нашей стороне достаточно
- [feedback_no_bbr.md](feedback_no_bbr.md) — НЕ включать TCP BBR; оставлять cubic. Не трогать tcp_reordering
- [feedback_lxc_via_ssh_not_pct.md](feedback_lxc_via_ssh_not_pct.md) — В LXC ходить через `ssh root@<ct-ip>`, не через `pct exec` с PVE-host
- [feedback_never_bypass_epm_play.md](feedback_never_bypass_epm_play.md) — НИКОГДА не обходить `epm play` ручной загрузкой бинарей — фиксить prerequisites и повторять
- [reference_remote_ssh_access.md](reference_remote_ssh_access.md) — Доступ к удалённым хостам через reverse-SSH на anyssh.ru: parentglobal=:10337/etersoft, rpi=:10338/root и др.
- [lesson_anyssh_ru_in_91232225.md](lesson_anyssh_ru_in_91232225.md) — anyssh.ru = 91.232.225.8, не маршрутизировать всю /24 через туннель - [lesson_anyssh_ru_in_91232225.md](lesson_anyssh_ru_in_91232225.md) — anyssh.ru = 91.232.225.8, не маршрутизировать всю /24 через туннель
- [lesson_lavtomate_bug_create_confirmation.md](lesson_lavtomate_bug_create_confirmation.md) — bug_create сломан: НЕ ретраить, проверять через confirmation_check - [lesson_lavtomate_bug_create_confirmation.md](lesson_lavtomate_bug_create_confirmation.md) — bug_create сломан: НЕ ретраить, проверять через confirmation_check
- [lesson_dns_free_ip_check_both_zones.md](lesson_dns_free_ip_check_both_zones.md) — поиск свободного IP: проверять ОБЕ зоны (forward+reverse) и ping - [lesson_dns_free_ip_check_both_zones.md](lesson_dns_free_ip_check_both_zones.md) — поиск свободного IP: проверять ОБЕ зоны (forward+reverse) и ping
...@@ -96,3 +101,6 @@ ...@@ -96,3 +101,6 @@
- [lesson_sieve_domain_split.md](lesson_sieve_domain_split.md) — sieve расщепление при symlink доменов: managesieve пишет по login-домену, доставка читает по spool-symlink → правила Roundcube не применяются - [lesson_sieve_domain_split.md](lesson_sieve_domain_split.md) — sieve расщепление при symlink доменов: managesieve пишет по login-домену, доставка читает по spool-symlink → правила Roundcube не применяются
- [lesson_lavtomate_master_active_empty.md](lesson_lavtomate_master_active_empty.md) — Lavtomate пишет пустой master active.script без `include "roundcube"` → правила Roundcube глохнут; ручной workaround + задание в lavtomate/docs/task-sieve-master-include.md - [lesson_lavtomate_master_active_empty.md](lesson_lavtomate_master_active_empty.md) — Lavtomate пишет пустой master active.script без `include "roundcube"` → правила Roundcube глохнут; ручной workaround + задание в lavtomate/docs/task-sieve-master-include.md
- [lesson_chat_eterfund_telemt_oom.md](lesson_chat_eterfund_telemt_oom.md) — chat.eterfund.ru: round-robin .43 (CT 691 telemt TLS-прокси на enceladus) + 217.12.37.55 (beget); инцидент 2026-05-25 — gyle CT 716 захватывал .43, перенесли gyle на .86 - [lesson_chat_eterfund_telemt_oom.md](lesson_chat_eterfund_telemt_oom.md) — chat.eterfund.ru: round-robin .43 (CT 691 telemt TLS-прокси на enceladus) + 217.12.37.55 (beget); инцидент 2026-05-25 — gyle CT 716 захватывал .43, перенесли gyle на .86
- [lesson_bind_dynamic_zone_freeze_thaw.md](lesson_bind_dynamic_zone_freeze_thaw.md) — BIND dynamic (DDNS) zones игнорируют `rndc reload` для изменений в zone file; нужен `rndc freeze` → edit → `rndc reload``rndc thaw`. Проверка: `rndc zonestatus ZONE in VIEW`
- [lesson_nf_conntrack_table_full.md](lesson_nf_conntrack_table_full.md) — Загадочные drops на NAT-шлюзе при сохранении старых сессий: `dmesg | grep conntrack`. Default `nf_conntrack_max=8192` — мало, поднять до 524288 + `_buckets=131072`
- [lesson_telemt_middle_proxy_egress_match.md](lesson_telemt_middle_proxy_egress_match.md) — telemt middle-proxy ME pool init работает только если src_ip (NAT'd) совпадает с registered у @MTProxybot. Без ME — direct-DC, **в 4× больше памяти**. Решение: telemt на самом egress-узле или satellite через туннель к egress с тем же ad_tag
---
name: feedback-clarify-ambiguous-no
description: "Короткие ответы пользователя («нет», «не хочу», «не надо») в контексте многовариантного выбора ВСЕГДА уточнять, не принимать как «делай оставшийся вариант»"
metadata:
node_type: memory
type: feedback
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## Правило
Когда я предложил пользователю несколько вариантов и он отвечает коротко («нет», «не хочу», «не надо»), **обязательно уточнить какой именно вариант он отверг и хочет ли он что-то ещё делать**.
**НЕ** интерпретировать «нет X» как «делай Y» (где Y — оставшийся вариант). По умолчанию короткое «нет» = «не делай ничего из обсуждаемого», а не «делай альтернативу».
## Why
2026-05-28: я предложил CT 691 три варианта решения media-проблемы:
- (1) IPsec/strongSwan CT 691 ↔ egw2 — новый прямой туннель
- (2) WireGuard — то же
- (3) Откатить policy на CT 691 (revert middle-proxy через egw2 в direct-DC)
- (4) Host-level GRE на enceladus
- (5) Убрать CT 691 из chat.eterfund.ru apex
Пользователь написал: «нет прямой не хочу».
Моя интерпретация: «нет варианта (1)/(2), значит делай (3)». Я выполнил откат: убрал systemd unit `route-via-egw2`, flush'нул rules и routes, отключил `use_middle_proxy`. Без подтверждения.
Реальный смысл пользователя: «не хочу делать прямой туннель» — то есть «не делай (1)/(2)», но без указания «делай (3)». Скорее всего: «не делай **ничего из этих радикальных вариантов**, обсудим дальше».
Пользователь обнаружил мои изменения: «Я не просил ничего менять вообще-то». Пришлось делать обратный откат через 5 минут.
## How to apply
- Короткие «нет/не хочу» в multi-choice контексте → задать вопрос: «Тогда какой вариант: A/B/C, или ничего пока не делать?»
- Действовать **только при явном «да» / «делай X»**, а не при отрицательных уточнениях
- Также применимо к: «не надо ad_tag менять», «не сейчас», «не сегодня» — всё это не означает «сделай что-то другое»
- Если есть сомнение, ВСЕГДА уточнить устно, до выполнения
- Особенно критично для **destructive операций** (удаление rules, отключение сервисов, restart telemt)
## Связано
- [[feedback-no-unauthorized-actions]] — НЕ самовольничать
- CLAUDE.md «ведёшь себя осмотрительно и спрашиваешь»
---
name: feedback-lxc-via-ssh-not-pct
description: "Для работы с LXC-контейнерами на PVE использовать ssh напрямую внутрь CT, а не pct exec с host'а"
metadata:
node_type: memory
type: feedback
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## Правило
Доступ в LXC контейнеры — через **ssh внутрь CT** (`ssh root@<ct-ip>`), а не через `pct exec NNN` с PVE-хоста.
## Why
2026-05-29: я наткнулся на `Insecure $ENV{ENV}` taint-ошибку pct.pm на enceladus (вызвана `ENV=$HOME/.bashrc` в `/root/.bashrc`), пытался воркэраундить через `unset ENV; pct exec ...`, потом предложил фиксить host'овый bashrc. User сказал «тебе не нужен pct exec» — то есть в эти контейнеры можно (и нужно) заходить ssh напрямую, не делать крюк через PVE host.
## How to apply
- Для CT с известным IP — `ssh root@<ct-ip>` напрямую (предварительно проверить known_hosts актуальность)
- `pct exec` оставлять для случаев когда **нет** сети внутри CT или CT не запущен
- НЕ предлагать править host-level конфиги (типа `/root/.bashrc` на PVE-хосте) ради того чтобы `pct exec` работал — это не та проблема которую стоит решать
- Если есть выбор между `ssh root@enceladus 'pct exec 691 ...'` и `ssh root@91.232.225.43 ...` — выбирать второе
## Связано
- [[feedback-no-unauthorized-actions]]
- enceladus: `/root/.bashrc:20` экспортирует `ENV` → ломает `pct exec`, но это не наша проблема
---
name: feedback-never-bypass-epm-play
description: "НИКОГДА не обходить ошибки `epm play` ручной загрузкой бинарей фиксить prerequisites и повторять epm play"
metadata:
node_type: memory
type: feedback
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## Правило
Если `epm play <package>` падает (нет зависимостей, недостающие репозитории, GPG keys и т.п.) — **обязательно**:
1. Прочитать ошибку
2. Установить недостающие prerequisites (`epm ei p7zip tar xz`, `dnf install epel-release`, импорт GPG ключей и т.д.)
3. Повторить `epm play`
**НЕЛЬЗЯ** в ответ на ошибку:
- Скачать бинарь напрямую (curl/wget) с upstream releases
- Скопировать в `/opt/<pkg>/` руками
- Создать systemd unit вручную
## Why
User feedback 2026-05-29: «Очень плохо, что ты как сделал. Запомни никогда не обходить ошибки установки через epm play.»
Контекст: я предположил (ошибочно) что бинарь telemt на schat был скопирован вручную из-за того что `epm play telemt` ранее падал на AlmaLinux. Реально оказалось — `epm play` справился, бинарь правильный. Но **сам принцип** — что в случае ошибки нужно фиксить prereqs, а не обходить вручную — пользователь подтвердил как важный.
Последствия ручного обхода (гипотетические):
- Бинарь не отслеживается package manager'ом → не обновится `epm Upgrade`, не получит security fix
- Невозможно `rpm -V` проверить целостность
- Hosts диверджат между собой (одни через epm, другие вручную)
- При расследовании багов «почему ведёт себя по-разному» — съедается много времени
## How to apply
- Если `epm play X` падает: прочитать что ругается, поставить недостающее (`epm ei p7zip tar`, `dnf install epel-release`, импорт GPG keys), повторить
- **Никогда не скачивать бинарь вручную** в ответ на provisioning ошибку
- Если действительно нет другого пути (upstream not packaged) — **попросить сборщика пакетов** собрать ALT RPM ([alt-packaging-agents](https://gitlab.eterfund.ru/etersoft/alt-packaging-agents))
- Все хосты в одной роли должны иметь **тот же** package source
## Замечание про `epm play` на non-ALT
На AlmaLinux/Rocky/Debian `epm play` использует upstream-сборки (через prescription `/etc/eepm/play.d/<pkg>.sh`), а не ALT RPM. Поэтому бинарь может отличаться от ALT-сборки — это **нормально** и **не** считается «ручной установкой».
## Связано
- [[feedback-no-unauthorized-actions]]
- CLAUDE.md «Используй всегда команды epm»
---
name: feedback-no-bbr
description: Не включать TCP BBR (net.ipv4.tcp_congestion_control=bbr) на серверах Etersoft — оставлять cubic
metadata:
node_type: memory
type: feedback
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## Правило
**Не включать BBR** на серверах. Использовать `cubic` (default ядра). Также не трогать `tcp_reordering` без явного запроса.
## Why
2026-05-29: я предложил BBR + reordering tweaks для оптимизации schat / egw2 / enceladus (telemt media transfer). После применения user сказал «ну и не надо bbr» — отказал. Эффект BBR на этих proxy-узлах не проявился, а вмешательство в kernel TCP стек без согласования — лишний риск.
## How to apply
- Не включать BBR без явного «да» от пользователя
- Если уже включил по своей инициативе — откатить (`sysctl -w net.ipv4.tcp_congestion_control=cubic`, очистить /etc/sysctl.d/99-tcp-tuning.conf)
- TCP buffer-related tweaks (`tcp_rmem`/`tcp_wmem`/`netdev_max_backlog`/`rmem_max`) считать дискуссионными — спрашивать
- Не путать с conntrack tuning (нужен на NAT-шлюзах — [[lesson-nf-conntrack-table-full]])
## Связано
- [[feedback-no-unauthorized-actions]]
- [[lesson-telemt-middle-proxy-egress-match]] — реальное решение media-проблемы было middle-proxy, не BBR
# Lesson: BIND dynamic (DDNS) zones — `rndc reload` does NOT load file edits
## Симптом
Отредактировал zone file (например `/var/lib/bind/zone/dyn/dyn-div-all.eterhost.ru`),
поднял serial, сделал `rndc reload``named-checkzone` OK, "server reload successful".
Но публичные резолверы продолжают видеть старый IP **с обновляющимся TTL** (т.е. они
получают свежие ответы, просто с теми же старыми значениями).
`dig @ns1 zone SOA` показывает старый serial.
`rndc zonestatus zone in VIEW` показывает `dynamic: yes`, `last loaded: <старая дата>`.
## Причина
Зоны с `allow-update { key ... };` (DDNS) хранят актуальное состояние **в памяти + journal (.jnl)**.
При `rndc reload` BIND **игнорирует изменения в текстовом zone file**, считая файл лишь начальной
точкой — реальные данные в журнале/памяти.
## Решение
Использовать **freeze/thaw** (или freeze/reload/thaw):
```bash
rndc freeze ZONE in VIEW # запретить апдейты, сбросить журнал в файл
# теперь файл = текущее состояние; можно его редактировать
rndc reload ZONE in VIEW # перечитать с диска
rndc thaw ZONE in VIEW # разрешить апдейты снова, журнал стартует с нуля
rndc zonestatus ZONE in VIEW # убедиться что serial обновился и last loaded — сейчас
```
Для div.eterhost.ru это `rndc freeze div.eterhost.ru in all` и т.д.
## Чек-лист DNS-правок на ns1.etersoft.ru
1. Проверить тип зоны: `rndc zonestatus ZONE in VIEW | grep dynamic`
2. Если `dynamic: yes`**обязательно** freeze/thaw, не просто reload
3. После операции **всегда** `rndc zonestatus` — проверить `serial:` и `last loaded:`
4. `dig @91.232.225.10 ZONE SOA +short +norec` — должен показать новый serial
## Контекст
- 2026-05-27, div.eterhost.ru, переключение публичного A с 146.158.10.185 на 46.148.53.122
- Изначально сделал sed + rndc reload — публичные DNS не подхватили, потерял ~10 минут на диагностику
- Помогло: `rndc zonestatus` показал old serial и `dynamic: yes`
- После freeze/reload/thaw — всё ОК, propagation пошла нормально
---
name: lesson-builder-tmp-cleanup
description: "builder64 /tmp чистит systemd-tmpfiles (10d), а не stmpclean (старая схема, локально отключена для /tmp)"
metadata:
node_type: memory
type: reference
originSessionId: 63af8818-b0da-4106-adf4-419d088b7bfe
---
На **builder** (builder64.office.etersoft.ru) /tmp очищает **только** systemd-tmpfiles, не stmpclean.
## Активная схема
- `systemd-tmpfiles-clean.timer` (enabled, active), запуск раз в сутки
- Правило `/usr/lib/tmpfiles.d/tmp.conf` (пакет `systemd-tmpfiles-common`):
- `q /tmp 1777 root root 10d`
- `q /var/tmp 1777 root root 30d`
- Удаляет файлы, у которых **latest** из atime/btime/ctime/mtime старше указанного срока
## Старая схема (stmpclean) — отключена для /tmp
- `/etc/cron.daily/stmpclean` локально модифицирован (rpm -V: `S.5....T.`)
- Строка `stmpclean -t 30d /tmp/` закомментирована — `/tmp` НЕ чистит
- Чистит только `/var/tmp` (30d)
- Рядом `/etc/cron.daily/stmpclean.rpmnew` (с 2023-01-11) — пакет хотел вернуть чистку /tmp, но локальные правки не дали обновить
## Как изменить срок для /tmp
Создать override `/etc/tmpfiles.d/tmp.conf`:
```
q /tmp 1777 root root 30d
```
(или другой срок). Файл в `/etc/` перекрывает одноимённый из `/usr/lib/`.
---
name: chat-eterfund-ru-architecture-and-gyle-ip-collision
description: chat.eterfund.ru DNS-балансировка через .43 (telemt CT 691 как TLS-прокси) + beget 217.12.37.55; бэкенд переехал на enceladus; разобран инцидент ARP-конфликта с gyle CT 716
metadata:
node_type: memory
type: project
originSessionId: 1547b826-cc7d-4cd6-af29-b5ad765e9187
---
## Текущая архитектура chat.eterfund.ru (на 2026-05-25)
`chat.eterfund.ru`**делегированная подзона** на ns1, файлы:
- `/var/lib/bind/etc/zone/chat.eterfund.ru.all` (public view)
- `/var/lib/bind/etc/zone/chat.eterfund.ru.trusted` (внутренний view)
Записи (упрощённо):
```
chat IN A 91.232.225.43 ; CT 691 telemt (TLS-прокси)
chat IN A 217.12.37.55 ; beget shared
e IN A 91.232.225.3 ; telemt MTProxy для Telegram
e4 IN A 91.232.225.43 ; chat node на CT 691 eth1
b IN A 217.12.37.55 ; beget
d IN CNAME div.eterhost.ru.
```
PTR `43 IN PTR e4.chat.eterfund.ru.``225.232.91.in-addr.arpa`).
**Бэкенд chat (Matrix/Synapse) переехал на enceladus** (`192.168.0.17`, ssh root@enceladus порт **22**).
CT 691 telemt с `tls_domain = "chat.eterfund.ru"` (см. `/etc/telemt/config.toml`) транспарентно
проксирует TLS-handshake chat на бэкенд. Тот же telemt одновременно даёт MTProxy для
Telegram (`telemt.eterfund.ru` = .3).
После переезда бэкенда: на CT 691 telemt уже не «весит» 2.7G — наблюдалось 25.5M
памяти, нет OOM, swap 0. То есть прежняя OOM-проблема ушла вместе с переносом.
## Инцидент 2026-05-25: gyle CT 716 перехватывал ARP для .43
**Симптом:** `chat.eterfund.ru` периодически недоступен (50% запросов в таймаут).
**Причина:** gyle (LXC CT 716 на border, ALT Hypericum) был сконфигурирован с тем же
`91.232.225.43/24` на `net0=breth0,bridge=vmbr1`, что и `eth1` CT 691 на той же ноде и
том же бридже vmbr1. Это устроило ARP-race: чей GARP последний — того и MAC у upstream-gw.
Когда побеждал gyle — на `.43:443` chat не отдавался (gyle ничего по chat не слушал),
запросы валились с reset/timeout. Когда побеждал CT 691 — chat работал.
Подсказки при диагностике:
- SSH host key на одном IP меняется между сессиями (две разные машины отвечают на :22)
- `pct config 716` на border: `net0 ... ip=91.232.225.43/24` совпадает с `pct config 691` `net1`
- В `ip neigh show 91.232.225.43` на priv видно, чей MAC выиграл (CT 691 eth1
MAC `bc:24:11:1d:ce:7a` vs gyle `BC:24:11:F9:7B:F9`)
**Фикс:** перенесли gyle на `91.232.225.86` (свободный IP):
```bash
ssh root@border 'pct set 716 -net0 name=breth0,bridge=vmbr1,firewall=0,gw=91.232.225.1,hwaddr=BC:24:11:F9:7B:F9,ip=91.232.225.86/24,type=veth'
ssh root@border 'env -u ENV -u BASH_ENV pct exec 716 -- ip addr add 91.232.225.86/24 dev breth0'
ssh root@border 'env -u ENV -u BASH_ENV pct exec 716 -- ip addr del 91.232.225.43/24 dev breth0'
ssh -p32 priv.etersoft.ru 'sudo ip neigh flush to 91.232.225.43'
```
После этого ARP на priv корректно резолвит `.43 → bc:24:11:1d:ce:7a` (eth1 CT 691),
`curl chat → .43` = HTTP 200.
DNS трогать не пришлось: `.43` всё это время оставался назначен CT 691 (только ARP
у upstream-gw был «отравлен» gyle); после снятия .43 с gyle никаких других изменений
не потребовалось.
## Why / How to apply
**Why:** на одном бридже несколько контейнеров с одним IP — гарантированный ARP-flap;
а если ещё и SNI-проксирование (`tls_domain` у telemt) — диагноз не очевиден: «chat
работает через какие-то IP», «иногда отваливается».
**How to apply:**
- Если жалуются на `chat.eterfund.ru` — проверить `ip neigh show 91.232.225.43` на priv,
убедиться что MAC = `bc:24:11:1d:ce:7a` (CT 691 eth1). Если другой — конфликт IP.
- При добавлении нового CT на border (vmbr1) — `grep -r "ip=91\.232\.225\." /etc/pve/lxc/`
на предмет дублирующих IP до запуска.
- `pct exec` из bash через ssh падает с `Insecure $ENV{ENV}` (taint mode) — использовать
`env -u ENV -u BASH_ENV pct exec ...`.
## Связанные
- [lesson_divserver_telemt_mtproxy.md](lesson_divserver_telemt_mtproxy.md) — telemt на divserver
- [lesson_lavtomate_master_active_empty.md](lesson_lavtomate_master_active_empty.md) — другой пример «двух хозяев конфига»
---
name: lavtomate-master-active-script-roundcube
description: "Lavtomate генерирует пустой master active.script (без include \"roundcube\") и перетирает defaultbc active.bc правила Roundcube перестают применяться. Чинится вручную, постоянное решение fix в lavtomate (см. docs/task-sieve-master-include.md)."
metadata:
node_type: memory
type: project
originSessionId: 54ee3593-700c-4737-9e78-474f6992e3f8
---
## Симптом
Пользователь правит фильтры в Roundcube — UI работает, правила
сохраняются в `roundcube.script`. На входящей почте правила НЕ
применяются: спам не отделяется, NotMe не работает, списки не разводятся.
В отличие от старой проблемы расщепления доменов
([[lesson_sieve_domain_split]]) — оба каталога уже сведены, sieve лежит
в одном месте, но всё равно не работает.
## Архитектура поломки
После того как Lavtomate взял управление sieve'ом, каталог
`/var/lib/imap/sieve/domain/o/office.etersoft.ru/l/<user>/` выглядит так:
```
active.script # 168 B — только комментарии, НИ require, НИ include
active.bc # компилят пустого мастера
defaultbc -> active.bc
lavtomate.script # `keep;` заглушка
lavtomate.bc
roundcube.script # 4 KB реальных правил
roundcube.bc
```
Cyrus при доставке смотрит `defaultbc``active.bc` → ничего не делает.
`roundcube.bc` валяется рядом, но никто его не включает.
Lavtomate должен был генерировать master с `include :personal "roundcube"`,
но в реальной active.script (бэкап 168 B) этого include нет. Код
`generate_master_script` в lavtomate когда-то получил `original_script=None`
и с тех пор `_find_original_script` его не восстанавливает: видит активным
свой же master, парсит его, не находит ничего — и снова генерирует
без include. Замкнутый круг.
## Чинить вручную (одноразово, до фикса в Lavtomate)
```bash
ssh -p32 root@mail.etersoft.ru
cd /var/lib/imap/sieve/domain/o/office.etersoft.ru/l/<USER>
cp -a active.script active.script.bak.$(date +%Y%m%d-%H%M%S)
cp -a active.bc active.bc.bak.$(date +%Y%m%d-%H%M%S)
cat > active.script <<'SIEVE'
# Master Sieve script generated by Lavtomate
# This script includes other scripts using the include extension
# Do not edit manually - changes will be overwritten
require ["include"];
# External user scripts first — their `stop;` short-circuits the fallback below
include :personal "roundcube";
# Lavtomate own rules last — its `keep;` is the fallback for unmatched mail
include :personal "lavtomate";
SIEVE
chown cyrus:cyrus active.script && chmod 600 active.script
/usr/lib/cyrus/sievec active.script active.bc.new
chown cyrus:cyrus active.bc.new && chmod 600 active.bc.new
mv active.bc.new active.bc
```
`defaultbc` не трогать, оно уже на `active.bc`.
**ВАЖНО — порядок include'ов:** roundcube ПЕРВЫМ, lavtomate ПОСЛЕДНИМ.
Обратный порядок ломает: `keep;` lavtomate сработает первым → письмо
ляжет в INBOX, потом правила roundcube ещё раз положат копию в Junk/etc.
Дубли.
**Why:** при следующем sync'е Lavtomate перезапишет `active.script` и
поломка вернётся. Это временная заплатка до фикса в самом Lavtomate.
**How to apply:** при жалобах "фильтры Roundcube не работают" на
mail.etersoft.ru — ПЕРВЫМ ДЕЛОМ читать содержимое `active.script` в
пользовательском sieve-каталоге. Если в нём только комментарии или нет
`include :personal "roundcube"` — это эта проблема. Чинить руками по
рецепту выше, проверять, что Lavtomate не пересинхронит и не сломает
обратно.
## Постоянное решение
Задание для разработчика Lavtomate:
`/srv/lav/Projects/git-eter/lavtomate/docs/task-sieve-master-include.md`
Три бага в `lavtomate/sieve/`:
1. `converter.py:142-172` — порядок include'ов в master перевёрнут
(lavtomate должен быть ПОСЛЕДНИМ, а сейчас он первый).
2. Поддержка только одного external script — нужен список.
3. `manager.py:114-157` `_find_original_script` не восстанавливает
external'ы, если master уже активен и пуст — нужен пересканинг
каталога.
## Связано
- [[lesson_sieve_domain_split]] — другая sieve-проблема: расщепление
доменов между `e/etersoft.ru` и `o/office.etersoft.ru` (исправлена
2026-05-13).
- [[lesson_cyrus_sasl_restart]] — общий контекст cyrus-imapd на
mail.etersoft.ru.
- 2026-05-21 22:13: применил ручной workaround для `lav@office.etersoft.ru`,
бэкапы — `active.{script,bc}.bak.20260521-221318` в каталоге пользователя.
---
name: lesson-mail-postfix-sasl-config-path
description: "mail.etersoft.ru: Postfix читает /etc/postfix/sasl/smtpd.conf, НЕ /etc/sasl2/smtpd.conf три SASL-конфига с разными фильтрами"
metadata:
node_type: memory
type: feedback
originSessionId: 402cfb91-8293-494b-a5d6-9c9b52cd6044
---
На mail.etersoft.ru три SASL-конфига для разных служб, каждый со своим фильтром `sql_select`:
| Файл | Кто читает | Фильтр |
|---|---|---|
| `/etc/sasl2/Cyrus.conf` | cyrus-imapd (IMAP, POP3, sieve) | `imap = 1` |
| `/etc/sasl2/smtpd.conf` | **никто** (легаси-файл) | (неважно) |
| `/etc/postfix/sasl/smtpd.conf` | Postfix smtpd (submission 587, smtps 465) | `smtpauth = 1` |
Postfix по `smtpd_sasl_path = smtpd` НЕ ходит в `/etc/sasl2/`, а в `/etc/postfix/sasl/`. Это конфигурируется при сборке cyrus-sasl2 (`SASL_PATH` env или `--with-configdir`). На ALT-mail это не дефолт, специально настроено.
**Why:** Я потерял ~30 минут в баге #19044 пытаясь поменять фильтр SMTP submission в `/etc/sasl2/smtpd.conf` — изменения никак не влияли, Postfix их не видит. В реальном `/etc/postfix/sasl/smtpd.conf` фильтр уже был `smtpauth = 1` с самого начала.
**How to apply:** Прежде чем менять SASL-конфиг под Postfix — всегда проверять `grep -rl smtpauth /etc/postfix /etc/sasl2`. В отличие от типичных гайдов в интернете, Postfix здесь читает не `/etc/sasl2/`.
Для отладки SASL: `sql_verbose: yes` + `log_level: 7` в нужном файле, потом смотреть `/var/log/mail/all`.
См. также [[lesson-cyrus-sasl-restart]] (про кэш sql_select в процессах), [[project-mail-password-hash-migration]].
---
name: lesson-nf-conntrack-table-full
description: "Загадочные drops/timeout'ы на NAT-шлюзе при сохранении старых сессий почти всегда переполнение conntrack table. Проверять dmesg и nf_conntrack_max."
metadata:
node_type: memory
type: lesson
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## Симптомы
На NAT-шлюзе (gateway с MASQUERADE/SNAT) неожиданно ломается связность:
- **Существующие SSH-сессии продолжают работать** (запись в conntrack создана давно, packets ходят)
- **Новые соединения дропаются**: `ssh: connect to host X port 22: Connection timed out`
- **Ping** к хосту 100% loss (новый ICMP-track не создаётся)
- **GRE/IPsec туннели** интермиттентно теряют пакеты — те же conntrack-проблемы
- В `dmesg`: `nf_conntrack: nf_conntrack: table full, dropping packet` + `net_ratelimit: N callbacks suppressed`
## Корень
`nf_conntrack_max` имеет очень маленький default на свежеустановленных системах (нередко **8192**). Активный NAT-router с прокси-трафиком (telemt, GRE-tunnels, etc.) забивает таблицу за минуты, особенно при churn-нагрузке (короткие коннекты → много TIME_WAIT).
## Диагностика
```bash
cat /proc/sys/net/netfilter/nf_conntrack_max # лимит
cat /proc/sys/net/netfilter/nf_conntrack_count # текущая загрузка
conntrack -L | awk '{print $1}' | sort | uniq -c | sort -rn # по протоколам
conntrack -L | awk '{print $4}' | sort | uniq -c | sort -rn # по TCP state (TIME_WAIT часто доминирует)
dmesg -T | grep -i conntrack
```
Если `count` близок к `max` (особенно если `max` = 8192/65536), то это оно.
## Фикс
```bash
# runtime
sysctl -w net.netfilter.nf_conntrack_max=524288
sysctl -w net.netfilter.nf_conntrack_buckets=131072 # ~= max/4 для хеша
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=60 # default 120, можно ужать
# persist
tee /etc/sysctl.d/99-conntrack.conf <<EOF
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_buckets = 131072
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 60
EOF
```
## Урок (применённый 2026-05-28 на vdska)
vdska (NAT для divserver/gre.vdska.egw/IPsec) весь день казался «нестабильным» — то отвечает, то нет. Я ошибочно списал утреннее падение на свой `netplan apply` и потратил часы на ребут/восстановление. Реальная причина — `nf_conntrack_max=8192` забит до отказа (8188/8192 entries, 99.9% TCP NAT-потоков).
**Правило:** при загадочных «mixed» drops на NAT-шлюзе — `dmesg | grep conntrack` **первым делом**, до диагностики netplan/firewall/routes.
---
name: lesson-roundcube-password-plugin-config
description: "Roundcube password plugin: `%c` placeholder удалён в 1.2+, заменён на `%P`; конфиг при апгрейдах нужно править вручную"
metadata:
node_type: memory
type: feedback
originSessionId: 402cfb91-8293-494b-a5d6-9c9b52cd6044
---
Если смена пароля в Roundcube «не работает» (молча валится, в `/var/log/roundcube/errors.log``DB Error: [1064] You have an error in your SQL syntax ... near '%c WHERE username = ...'`), смотри `/usr/share/roundcube/plugins/password/config.inc.php` на устаревшие плейсхолдеры.
**Why:** В Roundcube 1.2+ SQL-драйвер плагина `password` (`drivers/sql.php`) распознаёт только `%P/%O/%p/%o/%l/%d/%u/%h`. Старые `%c`, `%n`, `%q` (вместе с `password_crypt_hash` и `password_hash_algorithm`) — deprecated и просто уходят в SQL литералом. Конфиг при апгрейдах никто не обновляет, поэтому древние установки тихо ломаются.
**How to apply:** Минимальная правка:
- `%c``%P` в `password_query`
- Установить `password_algorithm = 'sha512-crypt'` (или `'sha256-crypt'`)
- `password_algorithm_prefix = ''` — пустая строка, иначе хэш в БД получит обёртку `{SHA512-CRYPT}...`, которую `crypt(plain, stored)` SASL'а не разберёт
- Закомментировать `password_crypt_hash`, `password_hash_algorithm` (для чистоты)
В CT 366 (roundcube.eterhost.ru, 10.20.30.66, доступ через `border`) файл не из rpm — создан вручную, безопасно править на месте. PHP-плагин логирует успешные смены в `/var/log/roundcube/password.log` (файл создаётся apache2; не путать с `password` без `.log`).
Связь: [[project-mail-password-hash-migration]].
---
name: Cyrus sieve расщепление при symlink доменов
description: На mail.etersoft.ru sieve-каталоги НЕ ходят по spool-symlink etersoft.ru→office.etersoft.ru. Roundcube managesieve пишет в каталог по login-домену, а Cyrus при доставке читает по реальному пути spool. Логинить пользователя надо стабильно под одним доменом.
type: project
originSessionId: abd39655-5450-4926-9401-ec7f682182d0
---
## Симптом
Пользователь правит фильтры в Roundcube, они сохраняются и видны — но не применяются к входящей почте.
## Архитектура (mail.etersoft.ru, CT 120)
- Spool: `/var/spool/imap/domain/e/etersoft.ru → o/office.etersoft.ru` (symlink есть)
- Sieve: `/var/lib/imap/sieve/domain/{e/etersoft.ru,o/office.etersoft.ru}/...`**симлинка НЕТ**, это две независимые папки
- SASL OR в `accountuser` принимает и `user@etersoft.ru`, и `user@office.etersoft.ru` → пользователь может залогиниться под обоими
## Что ломается
Если в Roundcube залогинились как `lav@etersoft.ru`:
- IMAP открывает почту через spool-symlink → попадает в `o/office.etersoft.ru/l/lav/` (всё ок)
- managesieve пишет sieve по login-домену → в `e/etersoft.ru/l/lav/` (тупик)
- LMTP при доставке читает sieve по реальному пути spool → `o/office.etersoft.ru/l/lav/defaultbc` — совсем другие файлы
## Чинить
**Вариант A (одноразово, чисто):** удалить чужой каталог, если пользователь логинится только под одним именем:
```bash
ssh -p32 root@mail.etersoft.ru
tar czf /root/sieve-USER-DOMAIN-backup-$(date +%Y%m%d-%H%M%S).tar.gz \
-C /var/lib/imap/sieve/domain/X/DOMAIN/N USER
rm -rf /var/lib/imap/sieve/domain/X/DOMAIN/N/USER
```
**Вариант B (надёжно на будущее):** заменить пользовательский каталог симлинком на «правильный»:
```bash
rm -rf /var/lib/imap/sieve/domain/e/etersoft.ru/l/lav
ln -s ../../../o/office.etersoft.ru/l/lav \
/var/lib/imap/sieve/domain/e/etersoft.ru/l/lav
```
(не тестировал, но логически совпадает с тем как сделан symlink для spool)
**Why:** пока симлинка для sieve нет, надо либо строго один login-домен на пользователя, либо ручной симлинк на каждого. Лучше системно: симлинк всего sieve-каталога домена `e/etersoft.ru → o/office.etersoft.ru` — но он сейчас не пуст, потребует консолидации.
**How to apply:** при жалобах «правила в Roundcube не применяются» на mail.etersoft.ru первым делом проверять обе sieve-папки `domain/e/etersoft.ru/<X>/<USER>` и `domain/o/office.etersoft.ru/<X>/<USER>`, сравнивать `defaultbc` и даты. Активный скрипт — тот, что в `o/office.etersoft.ru` (туда смотрит доставка через spool-symlink).
## Связано
- 2026-05-13: удалил `e/etersoft.ru/l/lav` (вариант A) — lav логинится только как @office
- Backup: `mail:/root/sieve-lav-etersoft.ru-backup-20260513-140504.tar.gz`
- [[lesson_lavtomate_master_active_empty]] — другая sieve-поломка: пустой
master active.script от Lavtomate глушит правила Roundcube. Симптом тот же
(«правила не применяются»), но причина другая — сначала проверь обе.
---
name: lesson-telemt-middle-proxy-egress-match
description: "Telemt middle-proxy mode (use_middle_proxy=true) запускает ME pool только если src_ip фактического upstream совпадает с registered IP у @MTProxybot иначе ME init silently fails, all traffic falls back to direct DC"
metadata:
node_type: memory
type: lesson
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## Симптомы
`use_middle_proxy = true` + `ad_tag` зарегистрирован, но в метриках:
- `telemt_me_writers_active_current = 0` (бесконечно)
- В логах: `All ME servers for DC failed at init dc=X alive=0 target_writers=N`
- `ME pool is not ready yet; retrying ... attempt=N retry_limit=unlimited`
- При этом TCP-сокеты к `:8888` ESTABLISHED видны (`ss -tn | grep :8888`)
- `RPC handshake OK` встречается в логах, но writers всё равно `0`
- Direct DC fallback работает (`upstream_connect_success_total` растёт)
Telegram явных reject не возвращает — handshakes завершаются "OK", но writers не активируются.
## Корень
Telegram ME-серверы **молчаливо отказываются** становиться "active writers" для прокси, если **`reflected_ip` upstream (= NAT'd src_ip как видит Telegram) НЕ совпадает с IP, зарегистрированным в @MTProxybot для этого ad_tag**.
Проверка через `tcpdump`/логи: смотри `local_addr_nat=X.X.X.X ... reflected_ip="X.X.X.X"` — это то, что Telegram видит. Должно совпадать с IP, который ты указал боту при `/newproxy`.
Это **НЕ** «лимит ad_tag на egress IP» (моя ранняя гипотеза). beget+schat работали несмотря на mismatch — потому что они оказались на egress IP hetzner (135.181.95.108), который не пересекался с их registered IPs. CT 691 с registered=.43 не работал — а реально шёл через hetzner.egw NAT.
## Эффект middle-proxy mode на ресурсы
Confirmed на 2026-05-28: при ~9000 клиентов
- **С работающим ME pool** (schat через egw2, 50 active writers): **1.0 GB RSS** ≈ 115 KB/client
- **Без ME pool** (e.chat / CT 691, 0 writers, fallback direct-DC): **4.3 GB RSS** ≈ 478 KB/client
**Middle-proxy уменьшает память ~в 4 раза** при равном клиентском трафике. Каждый ME writer мультиплексирует ~180 client-connections.
## Решение / архитектурный паттерн
**Вариант A — telemt прямо на egress-узле**:
- Поставить telemt на сам Hetzner-сервер (egw / egw2)
- src=public IP, без NAT
- Зарегистрировать тот же IP в @MTProxybot → ad_tag valid → ME pool работает
**Вариант B — satellite через NAT-туннель с правильным ad_tag**:
- Если есть рабочий ad_tag для X.X.X.X (зарегистрированный)
- Любой другой telemt-satellite может туннелировать upstream через тот же egress, используя **тот же ad_tag X**
- Пример: schat сейчас — bind на GRE-tunnel в egw2 → NAT → 178.105.209.27 → ad_tag `e1996de504a03a36cf5a8a21be745a57` (зарегистрирован для .27)
- ME pool работает, потому что egress src_ip = registered IP
## Чек-лист настройки нового middle-proxy telemt
1. Опредилить **egress IP** (что увидит Telegram): `curl --interface <bind_addr> -4 https://ifconfig.me` с правильно-сетапленной маршрутизацией
2. Зарегистрировать **этот** IP в @MTProxybot `/newproxy IP port secret` → ad_tag
3. В config: `use_middle_proxy = true`, `ad_tag = "..."`, при необходимости `bind_addresses = ["<tunnel-src>"]`
4. Restart (`use_middle_proxy` не подхватывается hot-reload, требует restart)
5. Проверка: через 30-60s `curl :9090/metrics | grep me_writers_active_current` — должно быть `>0`
6. В логе должны быть `reflected_ip="<registered-IP>"` (совпадает с registered)
## Нюанс — `middle_proxy_nat_ip` (override STUN)
Telemt определяет `reflected_ip` (что сообщить Telegram'у) через **STUN-пробу к публичному STUN-серверу**. STUN-пакеты идут по **default route**, **НЕ** через policy routing tables.
Это критично если у тебя гибридный egress:
- Default route → IP X (видит STUN, отдаёт telemt'у как reflected_ip)
- Policy-routed traffic к Telegram CIDRs → через туннель → IP Y (реально видит Telegram)
X ≠ Y → ME init fails (Telegram видит src=Y, telemt уверяет что мы X, ad_tag регистрирован для Y).
Пример (CT 691):
- bind=91.232.225.43, default egress=.43 (нет NAT, публичный IP офиса)
- policy `from .43 to Telegram-CIDRs lookup table142 → CT 687 → gre1 → egw2 → MASQ → 178.105.209.27`
- STUN видит .43 → telemt says reflected_ip=.43
- ad_tag зарегистрирован для .27
- **MISMATCH → ME pool пуст** несмотря на правильную маршрутизацию
**Решение:** добавить в config `[general]`:
```toml
middle_proxy_nat_ip = "178.105.209.27"
```
Telemt пропустит STUN и сообщит этот фиксированный IP. ME init проходит.
**Когда НЕ нужен:** если default route ВЕСЬ идёт через тот же туннель что и telegram-CIDR трафик (как schat — там gre3=default), STUN сам корректно определяет .27 — override не нужен.
Подтверждено 2026-05-28 на CT 691: с override `middle_proxy_nat_ip = "178.105.209.27"` ME pool активировался, память снизилась с 4297 → 1922 MB.
## Связано
- [[lesson-divserver-telemt-mtproxy]] — старая схема через GRE
- chat.eterfund.ru pool — IP в публичной round-robin записи
- [[reference-remote-ssh-access]] — доступ к remote endpoints
---
name: project-mail-password-hash-migration
description: "Etersoft#19044 миграция mail.etersoft.ru с DES crypt на SHA-512 в accountuser.password (этапы 1-3 готовы, остаётся форс-сброс 19 слабых)"
metadata:
node_type: memory
type: project
originSessionId: 402cfb91-8293-494b-a5d6-9c9b52cd6044
---
**Etersoft#19044** (NEW, P5, assigned lav@): mail.etersoft.ru — переход с DES crypt на SHA-512 в `accountuser.password` (mysql.auth.dmz.etersoft.ru, БД `mail`).
**Why:** DES crypt — 13 символов, только первые 8 байт пароля; ~21M c/s на builder64 john. Аудит 2026-04-28: 19 из 152 аккаунтов office имели слабые пароли.
**Сделано 2026-05-20/21 (этапы 1-3):**
1. БД: `ALTER TABLE accountuser MODIFY password VARCHAR(255), saved_password VARCHAR(255)` на mysql.auth.dmz.etersoft.ru.
2. SASL проверен эмпирически (imtest + тестовый пользователь с `$6$`-хэшем): cyrus-sasl2 2.1.28 + libxcrypt 4.4.36 → `$6$` хэши работают, изменений в конфигах SASL не нужно.
3. Три точки смены пароля переведены на `crypt(plain, '$6$'.bin2hex(8 random bytes))`:
- **CT 239 cyradm.eterhost.ru**: `/var/www/webapps/web-cyradm/lib/crypto.php` — методы `update()` и `encrypt()` (PHP 5.3.6, `openssl_random_pseudo_bytes`).
- **CT 251 time.office.etersoft.ru** (sec.office): `/var/www/webapps/sec/passwd/passwd.php` (PHP 7.3.33, `random_bytes`).
- **CT 366 roundcube.eterhost.ru** (10.20.30.66): `/usr/share/roundcube/plugins/password/config.inc.php``%c``%P`, `password_algorithm='sha512-crypt'`, deprecated `password_crypt_hash`/`password_hash_algorithm` закомментированы.
- Бэкапы `.bak.20260520`/`.bak.20260521` рядом с оригиналами.
**Осталось:**
- Принудительный сброс 19 слабых паролей (список — комментарий #1 в баге, пароли в `builder64:~/tmp/claude/john.pot`). При смене они автоматически перейдут на `$6$`.
- Отдельная заметка: SASL-юзер `mail`@`%` в mysql имеет `GRANT ALL PRIVILEGES ON mail.*`, при этом креды в открытом виде в `/etc/sasl2/{Cyrus,smtpd}.conf`. Сузить до `SELECT`.
См. также [[lesson-roundcube-password-plugin-config]], [[lesson-cyrus-sasl-restart]].
---
name: reference-remote-ssh-access
description: "Reverse-SSH туннели на anyssh.ru (91.232.225.8) для удалённых хостов за NAT parentglobal, rpi и др. Маппинг ports→hosts"
metadata:
node_type: memory
type: reference
originSessionId: 1531d5f1-79d0-4df9-9ede-7c62c3e675c9
---
## anyssh.ru = 91.232.225.8
Хост-relay в офисной подсети. Удалённые машины за NAT держат `ssh -R PORT:localhost:22 etersoft@anyssh.ru -N` — мы заходим обратной стороной как `ssh -p PORT user@anyssh.ru`.
## Активные обратные туннели (по состоянию 2026-05-28)
| Порт на anyssh.ru | Хост | Пользователь | Описание |
|---|---|---|---|
| 10337 | parentglobal (ALT Workstation K 11, Cosmote/Greece) | `etersoft@` | seedbox/ipsec gateway, IKEv2 к ikev2.gr.egw (.139) |
| 10338 | rpi (Raspberry Pi, Debian 13 trixie, Free.fr) | `root@` | IPsec в Docker container `ikev2-fr-client`, к ikev2.fr.egw (.140) |
| 10209 | core.localdomain | `root@` | — |
| 10210 | pue | `root@` | — |
| 10316 | ? | — | permission denied (другой ключ) |
Полный список открытых портов: `ssh root@anyssh.ru 'ss -tlnp | grep sshd'`.
## Альтернатива — через IPsec tunnel
Если у хоста IPsec к нашему ikev2.*-CT — обычно достижим через jumphost:
- parentglobal: `ssh -J root@91.232.225.139 root@10.10.10.6` (10.10.10.4/30 ipsec0 на .139)
- rpi: **НЕ работает** — sshd внутри Docker container, не доступен на host через 10.10.10.6
## Известные проблемы
- **rpi**: чтобы `ssh -J root@91.232.225.140 root@10.10.10.6` работало — нужно либо поднять sshd host'а с bind на 10.10.10.6 (но этот IP внутри Docker netns), либо `docker run -p 10.10.10.6:22:22`, либо переместить IPsec из контейнера на host.
## Связано
- [[lesson-anyssh-ru-in-91232225]] — не маршрутизировать всю 91.232.225/24 через ipsec0 на удалённой машине, иначе порвём обратный SSH-туннель
- [[feedback-no-routes-on-remote-nat-peers]] — никаких маршрутов на офисные подсети на удалённой стороне tunnel'а
---
name: reference-time-office-sessions
description: "time.office.etersoft.ru сборщик сессий пользователей (eter_time), пути к скриптам, крон, список хостов"
metadata:
node_type: memory
type: reference
originSessionId: 895e3796-6d1f-4cf6-af32-83d97ae01050
---
# time.office.etersoft.ru — сборщик сессий
**Доступ:** `ssh time` (алиас в ~/.ssh/config, порт 6122, пользователь lav, потом sudo). Внутри это CT, hostname `gitlab.eterfund.ru.local`, IP 10.20.30.2 на venet0. Прямой `ssh root@time.office.etersoft.ru` НЕ работает — только через алиас `time`.
**База:** MySQL `eter_time` на `mysql.dmz.etersoft.ru`, таблица `eter_session`. Креды лежат в `/var/www/webapps/time/python/load/config.py`.
## Сборщик сессий с рабочих станций
- **Скрипт:** `/var/www/webapps/time/python/load/load_sessions.py` (Python 2, MySQLdb)
- **Обёртка:** `/var/www/webapps/time/python/load/load_sessions.sh` — берёт last за 3 дня
- **Конфиг:** `/var/www/webapps/time/python/load/config.py` — список `remote_hosts` (с каких машин забирать) и `allow_nx_hosts` (с каких ещё и NX-сессии)
- **Крон (timeuser):** `30 0,3,9-23 * * *` — каждые ~3 часа
- **Лог рассылки уведомлений:** `/home/timeuser/tmp/xsend.last.log`
**Важно:** если сессии с какой-то машины не приходят — проверить, есть ли её hostname в `remote_hosts` в `config.py`. Список редактируется руками (sudo). Бэкап делается рядом: `config.py.bak.YYYYMMDD`.
## Прочие компоненты time
- `/var/www/webapps/time/python/notice/send_notify.py` — крон каждую минуту, отправка уведомлений
- `/var/www/webapps/time/python/notice/xsend.py` — 10:00 пн-пт, рассылка
- `/var/www/webapps/time/regular/daily_task.php` — 06:50 ежедневно
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment