@@ -57,4 +57,18 @@ umount /srv && mount -o fsc /srv # remount не работает!
## Changelog
(пока нет записей)
### 2026-07-18 — медленные метаданные `/srv` на builder64
-`/srv` экспортируется с `aspetos` из ZFS `ssd1/srv` (mirror: Crucial MX500 + Samsung 870 QVO), не из NVMe `pool0`.
- Локальный `git status --porcelain --untracked-files=no` в `/srv/lav/Projects/git-eter/etersoft-admin-essential` на aspetos: **25 ms** (`refresh index` 12.7 ms). Через NFS на builder64: **15–21 s**, из них `refresh index` 19.6 s.
- Во время запуска на builder64 `GETATTR` получал ответ сервера примерно за 0.22 ms, но ждал в клиентской NFS RPC-очереди около 64 ms на запрос; `ACCESS`/`LOOKUP` ждали 89–93 ms. Это клиентская перегрузка очереди RPC/слотов, а не задержка ZFS, SATA или сети.
-`zpool status -v ssd1`: без ошибок; SMART обоих SSD passed, uncorrectable/pending/reallocated = 0; в момент измерений диск не был загружен.
- Синхронная проверка 2026-07-18: на aspetos CPU idle 67–74%, iowait 0–1%, `ssd1` ~80–84 IOPS и <1.1 MB/s; nfsd не насыщен. Серверная сторона не является узким местом.
- Возможная причина высокого клиентского backlog: на сервере включены NFSv4 delegations (`fs.leases-enable=1`), а `TEST_STATEID` растёт аномально быстро (18 885 за 10 s на aspetos; на builder64 в отдельном интервале — 96 668 за 10 s). Есть известная старая Linux NFSv4 проблема с делегациями и избытком `TEST_STATEID`; для текущих ядер 6.12.68/6.12.74 совпадение симптомов ещё не доказывает ту же bug. Не отключать delegations без согласованного окна: потребуется перезапуск NFS и контрольный замер.
### Подтверждённый workaround — 2026-07-18
- В согласованное окно на `aspetos` временно выполнены `fs.leases-enable=0` и `serv nfs-server restart`; перезапуск прошёл успешно.
- После этого на builder64 `TEST_STATEID` = **0 за 10 s**. Контроль от владельца дерева `lav`: `git status --porcelain --untracked-files=no` — **33.8 ms**, `refresh index` — **27.8 ms** (до изменения 15–21 s / 19.6 s соответственно).
- Следовательно, первопричина тормозов `/srv` — NFSv4 delegations (`TEST_STATEID` storm), не ZFS, SATA или nfsd. Состояние **временно**: `fs.leases-enable=0` не сохранён в sysctl-конфигурации и исчезнет после перезагрузки. Закреплять только по отдельному решению.
- Контроль `/home` на builder64 после отключения delegations: `/home` = `homeserver:/home`, NFSv4.2 от aspetos; обход первых 1 000 файлов от `lav` — **128 ms**, `TEST_STATEID` = **0 за 10 s**. Отдельная настройка `/home` не требуется: `fs.leases-enable` действует на все NFSv4-экспорты server-а.
-**Changelog объектов** (`memory/objects/<имя>.md`): что менялось на каждом сервере/сервисе, по дате — см. [feedback_changelog_notes.md](feedback_changelog_notes.md). Есть: vpn.eterfund.ru, vpn.office.etersoft.ru, enceladus, border, [host03.eterhost.ru](objects/host03.eterhost.ru.md)(хостинг-нода OpenVZ, инвентарь+503-инцидент soulibre, готовится миграция)
| gyle (CT 716 на border, 91.232.225.86) | `ssh root@91.232.225.86` (был .43 до 2026-05-25) |
| sip.etersoft.ru (91.232.225.18) | `ssh -p32 root@sip.etersoft.ru` (ключи добавлены 2026-04-27, lav@ тоже работает с NOPASSWD sudo) |
| iot.etersoft.ru (91.232.225.104, CT 585 на border, ALT p11, публичный «песочница») | `ssh root@iot.etersoft.ru` (shell fish) или `ssh pv@iot.etersoft.ru` (bash, sudo NOPASSWD). Клон template-CT 720, см. [reference_create_lxc_container_pve.md](reference_create_lxc_container_pve.md) |
| time.office.etersoft.ru | `ssh time` (алиас, порт 6122, lav+sudo) — НЕ работает напрямую `ssh root@time.office`, см. [reference_time_office_sessions.md](reference_time_office_sessions.md) |
| matrix.etersoft.ru (91.232.225.42, Synapse, CT 291 на border) | `ssh -p32 root@matrix.etersoft.ru` (alias `matrix`, порт 32; lav@ НЕ пускает; нужен ssh-agent), см. [lesson_matrix_etersoft_synapse_disk_telegram_bridge.md](lesson_matrix_etersoft_synapse_disk_telegram_bridge.md) |
| **lav** (192.168.0.55) | `ssh lav` — десктоп (доменный юзер lav uid 502, sss; в wheel→sudo). ⚠️ Claude-сессия обычно крутится на **builder64.office.etersoft.ru** (отдельный хост, тоже sss-auth), НЕ на lav — не путать хост/юзер. См. [lesson_pam_system_check_localuser_uid500.md](lesson_pam_system_check_localuser_uid500.md) |
- NAT-логирование (conntrack): hetzner, vpn-серверы, server — `/var/log/conntrack/nat.log`
-[reference_eterventcontrol.md](reference_eterventcontrol.md) — eterventcontrol (вентиляция офиса): код в git-eter/eterventcontrol, запущен на server (192.168.0.1), API http://192.168.0.1:8000
-[reference_eter_tv_xiaomi.md](reference_eter_tv_xiaomi.md) — телевизор Xiaomi Eter-TV (192.168.8.211, MAC 50:e4:78:f7:52:b8); SSH нет, доступ через ADB по сети
-[reference_igw_route_api.md](reference_igw_route_api.md) — Route Management API на igw (HTTP :80, самодок `/swagger`+`/api/openapi.json`): списки bypass/direct/geo, `POST /api/check` — тест домена через шлюзы, экспорт маршрутов
- NAT-логирование (conntrack): hetzner, vpn, server — `/var/log/conntrack/nat.log`
-**Home Assistant** — podman-контейнер на div.eterhost.ru; http://192.168.1.5:8123 (+ http://192.168.10.131:8123); login **lav**; creds (пароль) в rooter store: `ssh rooter@server pass show ha-divserver`
-[reference_eterventcontrol.md](reference_eterventcontrol.md) — вентиляция офиса, server 192.168.0.1:8000
-[reference_eter_tv_xiaomi.md](reference_eter_tv_xiaomi.md) — TV Xiaomi 192.168.8.211, доступ через ADB
-[reference_igw_route_api.md](reference_igw_route_api.md) — Route API на igw :80 (bypass/direct/geo, `/api/check`, экспорт)
-[reference_route_update_sh.md](reference_route_update_sh.md) — route-update.sh: per-list таблицы, pref по алфавиту, слои персистентности
-[reference_mysql_servers.md](reference_mysql_servers.md) — инвентарь MySQL/MariaDB: auth 5.5(.202) / office 8.0(.191) / fond 5.7(.81) / host03 8.0(.83); RT НЕ с MySQL 8 (баг 7693)
-[reference_ikev2_fr_tunnel.md](reference_ikev2_fr_tunnel.md) — вся система обхода claude.ai/Anthropic через Францию: route-update группа fr (pref 900, v6 unreachable) + IPsec .140↔rpi (78.193.2.190, доступ `ssh -p10338 root@anyssh.eterhost.ru`, контейнер ikev2-fr в /opt/ikev2-fr-docker); «egress=.140»=SA down; фикс `docker exec ikev2-fr swanctl --initiate --child s2s`; self-healing через autoheal
-[reference_ikev2_gr_tunnel.md](reference_ikev2_gr_tunnel.md) — Greek-эгресс gvpn: gr.egw=CT706 (.139, responder на border) ↔ parentglobal (Греция, 94.69.12.186, initiator, reverse-SSH anyssh:10337); gvpn default→.139→ipsec0(10.10.10.5/.6)→Греция; «gvpn offline»=CT706 stopped; фикс `pct start 706` + `swanctl --initiate --child s2s` с parentglobal. Параллель fr; отдельный `divserver` SA на parentglobal пока down
## Правила работы
-**`.claude/memory/` — основная память проекта.** Искать сначала туда (grep/read), туда же записывать заметки и уроки. Структура: `reference_*.md` (справочники), `feedback_*.md` (правила), `lesson_*.md` (грабли), `project_*.md` (задачи), `objects/` (changelog хостов).
-[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_cleanup_only_known.md](feedback_cleanup_only_known.md) — «почисти» = убрать ТОЛЬКО уже известное/оговорённое; не выискивать новое, не делать prune -af/userdel самовольно
-[feedback_alt_bugzilla_defaults.md](feedback_alt_bugzilla_defaults.md) — ALT Bugzilla: priority=P5, rep_platform=x86_64
-[feedback_cleanup_only_known.md](feedback_cleanup_only_known.md) — «почисти» = только оговорённое, не выискивать новое
-[feedback_verify_before_stating.md](feedback_verify_before_stating.md) — ВСЕГДА проверять, не выдумывать
-[feedback_changelog_notes.md](feedback_changelog_notes.md) — заметки по объектам после изменений
-[feedback_alt_bugzilla_defaults.md](feedback_alt_bugzilla_defaults.md) — ALT Bugzilla: P5, x86_64
-[feedback_dnsroot_danger.md](feedback_dnsroot_danger.md) — НИКОГДА не менять dnsRoot в AD crossRef
-[feedback_changelog_notes.md](feedback_changelog_notes.md) — вести заметки по объектам после изменений
-[feedback_verify_before_stating.md](feedback_verify_before_stating.md) — ВСЕГДА проверять информацию, не выдумывать
-[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_no_routes_on_remote_nat_peers.md](feedback_no_routes_on_remote_nat_peers.md) — НЕ добавлять маршруты на удалённой машине за NAT при настройке туннелей; MASQUERADE на нашей стороне достаточно
-[feedback_reverse_zone_ip_allocation.md](feedback_reverse_zone_ip_allocation.md) — При выделении IP всегда проверять файл обратной зоны и сразу записывать туда взятый IP
-[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 и повторять
-[feedback_use_epm_for_packages.md](feedback_use_epm_for_packages.md) — пакеты ТОЛЬКО через epm; есть epm — не обходить (не apt/rpm напрямую); нет — сначала поставить
-[feedback_ip_openness_tiers.md](feedback_ip_openness_tiers.md) — IP по степени открытости: 192.168.0.x (офис) / 10.20.30.x (внутр. серверы/CT) / 91.232.225.x (публичный, только если надо наружу). Не светить публичным без нужды
-[feedback_install_from_package_not_pip.md](feedback_install_from_package_not_pip.md) — на проде ставить из системных пакетов, НЕ pip-в-venv; не упаковано → упаковать, pip-venv только как обозначенный stopgap
-[feedback_build_requests_via_kanban.md](feedback_build_requests_via_kanban.md) — запросы на сборку/упаковку пакетов → Kanban (категория git-alt), НЕ GitLab issue в alt-packaging-agents
-[feedback_password_request_only.md](feedback_password_request_only.md) — пароли ТОЛЬКО через lavtomate password_request (одобрение в web UI); не читать автономно, не грепать секреты, не хранить plaintext для Claude
-[feedback_shared_passwords_rooter_store.md](feedback_shared_passwords_rooter_store.md) — пароль, нужный нескольким админам → класть в rooter password store, не в credentials.md и не plaintext в memory
-[reference_rooter_password_store.md](reference_rooter_password_store.md) — admin password store на server: чтение `ssh rooter@server pass show <name>` (gated rooter SSH), add/rm через root@server `/usr/local/sbin/admin-pass-add.sh`; `/var/lib/admin-pass/`
-[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_lavtomate_bug_create_confirmation.md](lesson_lavtomate_bug_create_confirmation.md) — bug_create теперь переиспользует approved confirmation_id при field-validation reject; можно ретраить с дополненными полями
-[lesson_dns_free_ip_check_both_zones.md](lesson_dns_free_ip_check_both_zones.md) — поиск свободного IP: проверять ОБЕ зоны (forward+reverse) и ping
-[feedback_reverse_zone_ip_allocation.md](feedback_reverse_zone_ip_allocation.md) — выделяя IP → сразу писать в обратную зону
-[feedback_no_routes_on_remote_nat_peers.md](feedback_no_routes_on_remote_nat_peers.md) — НЕ добавлять маршрут на удалённом NAT-пире; MASQUERADE у нас хватает
-[feedback_route_list_symlink_only.md](feedback_route_list_symlink_only.md) — `.list` в routes.d(6.d) igw ТОЛЬКО симлинки
-[feedback_no_bbr.md](feedback_no_bbr.md) — НЕ 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`
-[feedback_use_epm_for_packages.md](feedback_use_epm_for_packages.md) — пакеты ТОЛЬКО через epm
-[feedback_never_bypass_epm_play.md](feedback_never_bypass_epm_play.md) — НЕ обходить epm play ручной загрузкой
-[feedback_epm_install_girar_task.md](feedback_epm_install_girar_task.md) — girar-задание: `epm install <task_id>` (НЕ ручной apt-repo add)
-[feedback_upgrade_sisyphus.md](feedback_upgrade_sisyphus.md) — LXC ALT p11 → Sisyphus
-[feedback_ip_openness_tiers.md](feedback_ip_openness_tiers.md) — 192.168.0.x / 10.20.30.x / 91.232.225.x (публичный — только если надо)
-[feedback_test_servers_on_dmz.md](feedback_test_servers_on_dmz.md) — тест-серверы → 10.20.30.x (инфра), НЕ 192.168.0.x (office LAN); подтверждать сеть перед созданием
-[feedback_install_from_package_not_pip.md](feedback_install_from_package_not_pip.md) — на проде из системных пакетов, не pip-venv
-[feedback_rewrite_preserve_full_config.md](feedback_rewrite_preserve_full_config.md) — переписывая конфиг, сохраняй ПОЛНОЕ содержимое (включая Database*/пароли); маскируй только для дисплея, не для записи; cp bak → surgical sed, не heredoc из отфильтрованного вида
-[feedback_password_request_only.md](feedback_password_request_only.md) — пароли ТОЛЬКО через lavtomate password_request
-[feedback_shared_passwords_rooter_store.md](feedback_shared_passwords_rooter_store.md) — shared-пароль → rooter store
-[reference_rooter_password_store.md](reference_rooter_password_store.md) — admin pass store: `ssh rooter@server pass show <name>`
-[reference_remote_ssh_access.md](reference_remote_ssh_access.md) — reverse-SSH через anyssh.ru
-[lesson_anyssh_ru_in_91232225.md](lesson_anyssh_ru_in_91232225.md) — anyssh.ru=.8, не маршр. всю /24
-[project_iperf3_monitoring_frgr.md](project_iperf3_monitoring_frgr.md) — ЗАПЛАНИРОВАНО (вариант 1, пока не делать): iperf3 для ikev2.fr/gr через туннель на 10.10.10.6, чтобы route-health красил зелёным; нужен доступ к gr-пиру
-[project_vaultwarden_password_broker.md](project_vaultwarden_password_broker.md) — ОТЛОЖЕНО: брокер паролей password_request↔Vaultwarden; дизайн в `.claude/docs/vaultwarden-lavtomate-bridge.md`, реализация не начата
-[project_vpn_migrate_enceladus_aesni.md](project_vpn_migrate_enceladus_aesni.md) — ✅ ВЫПОЛНЕНО 2026-06-26: vpn.eterfund (CT 258) + vpn.office (VM 292) перенесены с border на enceladus, AES-NI заработал (Ryzen 9 9950X), отписано в Etersoft#16295
-[project_rarus_1c_vpn_gateway.md](project_rarus_1c_vpn_gateway.md) — изолированный PPTP-шлюз к облаку 1С-Рарус, CT 652 rca-gw (10.20.30.250). NetworkManager-pptp + MPPE 128 через NAT priv (фикс: CT-helper правило на priv), переживает ребут; ждём URL публикации 1С от Rarus для OData
-[project_rarus_1c_vpn_gateway.md](project_rarus_1c_vpn_gateway.md) — PPTP-шлюз к 1С-Рарус, ждём URL OData
-[project_pve_kerberos_spnego_gefest.md](project_pve_kerberos_spnego_gefest.md) — PVE на gefest: настоящий Kerberos SSO (SPNEGO); пользователь настраивает сам, мне — проверить после
## Десктоп lav
Документация по настройке DE, локального пользователя и локальной машины lav вынесена в отдельный проект **`~/Projects/Claude/local-admin/`** (git, перенесено из memory 2026-06-25). См. там `README.md`:
-`lav_desktop.md` — общее по машине (192.168.0.55): Deferred + Ximper, доступ, мониторы, засыпание, грабли обновления
-`hyprland.md` — Hyprland (исторический, до Niri): greetd/regreet, конфиги Ximper, hypridle
-`ssh-agent.md` — ssh-agent под Niri: systemd user service на tmpfs-сокете /run/user/$UID (ушли с NFS ~/.ssh/agent из-за коллизии общего home)
Настройка DE/локального юзера/машины lav — отдельный проект `~/Projects/Claude/local-admin/` (git). См. README: `lav_desktop.md` (192.168.0.55), `niri.md` (текущий WM), `hyprland.md` (историч.), `ssh-agent.md` (systemd user service на tmpfs-сокете).
-[reference_zclaude_glm_config.md](reference_zclaude_glm_config.md) — Claude Code+z.ai GLM: wrapper `zclaude`→`env-z.conf`, tiered routing glm-4.7/glm-5.2 (с 2026-07-06), почему квота тает быстрее Anthropic
-[lesson_clone_container_iptables.md](lesson_clone_container_iptables.md) — клонирование LXC: SNAT-правила на хосте не копируются, L3 не работает пока не добавишь
-[lesson_lxc_etcnet_to_systemd_networkd.md](lesson_lxc_etcnet_to_systemd_networkd.md) — новый LXC из etcnet-шаблона 720: PVE пишет networkd-конфиг, ставим systemd-networkd; `disable network` НЕ enough (оживает на boot) → надо `mask`
-[reference_pantum_scanner.md](reference_pantum_scanner.md) — Pantum M6700DW: sane-airscan (eSCL), native-драйвер не работает, VM нужна ручная запись в airscan.conf
-[reference_telemt_fleet_ja4_monitoring.md](reference_telemt_fleet_ja4_monitoring.md) — telemt-флот chat.eterfund.ru (e5 ALT Sisyphus, d/s/b.chat Ubuntu); JA4/beobachten, мониторинг в InfluxDB gateways
-[lesson_eterban_priv_two_wan_slots.md](lesson_eterban_priv_two_wan_slots.md) — eterban priv: ровно 2 WAN (i_interface/i_interface2), правила dynamic НЕ в /etc/sysconfig/iptables (ipset-риск); 3-й WAN — только live + sidecar
-[lesson_mail_cert_renewal_webroot_hook.md](lesson_mail_cert_renewal_webroot_hook.md) — mail LE: cron.weekly webroot, deploy-hook
-[lesson_mail_mysql_credentials.md](lesson_mail_mysql_credentials.md) — mail DB mailro/mail@%; ротация → restart postfix
-[lesson_rt_condition_perl538.md](lesson_rt_condition_perl538.md) — RT 4.4.x на p11/Perl 5.38: `RT/Condition.pm:201` без `;` = fatal, падают все scrips (на p9/Perl 5.28 молча работало); фикс — одна точка
-[lesson_sieve_domain_split.md](lesson_sieve_domain_split.md) — sieve расщепление при symlink доменов
-[reference_ruskru_telegram_notifier.md](reference_ruskru_telegram_notifier.md) — бот @ruskru на sites43
-[lesson_office_home_nfs_mount_fail.md](lesson_office_home_nfs_mount_fail.md) — office /home NFSv4 с aspetos, home.mount при загрузке
-[lesson_proxy_monitoring_functional_check.md](lesson_proxy_monitoring_functional_check.md) — мониторинг SOCKS5: curl через SOCKS, не порт :1080
-[lesson_ikev2_beget_cert_dns_fix.md](lesson_ikev2_beget_cert_dns_fix.md) — ikev2.beget: протух LE-серт, DNS курица-яйцо
-[lesson_traceroute_first.md](lesson_traceroute_first.md) — диагностика сети: сначала traceroute/mtr, не гадать по IP
-[lesson_matrix_etersoft_synapse_disk_telegram_bridge.md](lesson_matrix_etersoft_synapse_disk_telegram_bridge.md) — matrix Synapse media_store пухнет от TG-моста
-[lesson_rooter_home_pbs_restore.md](lesson_rooter_home_pbs_restore.md) — rooter home на NFS; restore через PBS
-[lesson_grafana_influxql_total_line.md](lesson_grafana_influxql_total_line.md) — Σ total на Grafana InfluxQL: серверный подзапрос sum(last()) (НЕ calculateField); byRegexp substring; Playwright MCP крошечный viewport → панели вне экрана не рендерятся
-[lesson_rt_mail_pickup_test.md](lesson_rt_mail_pickup_test.md) — тест забора RT: слать на name@etersoft.ru (Roundcube-Sieve "Not me" на @office.etersoft.ru кладёт прочее в подпапку); requestor проверять в БД (API MemberEmailAddresses врёт пустым); postfix-логи RT в journald, исходящие от noreply@etersoft.ru
-[lesson_rt_stale_stats_analyze.md](lesson_rt_stale_stats_analyze.md) — RT виснет на истории тикета (htmx /Helpers/TicketHistoryPage) после bulk-import дампа: устаревшая InnoDB-статистика → BNL full-scan Attachments (194k строк × Content-блобы); EXPLAIN rows=194225 type=ALL → после ANALYZE rows=2; fix `mariadb-check --analyze eter_rt` (helper 15с+ → 0.024с). Тот же root cause что прод #70334; подтверждено для RT 6.0
-[lesson_rt6_secure_cookies_http.md](lesson_rt6_secure_cookies_http.md) — RT 6.0 дефолтит WebSecureCookies=1 (4.4 — нет): на HTTP-only контуре (rt-test) браузер роняет secure-cookie → логин не прилипает (верный пароль принят, след. запрос = откат на логин; неверный — честная ошибка); фикс Set($WebSecureCookies,0). Прод за HTTPS — дефолт ок. + rt-fcgi socket-activated: поднимать сокеты, не сервисы напрямую
-[lesson_rt6_runtime_deps_missed.md](lesson_rt6_runtime_deps_missed.md) — RT 6.0: make testdeps и Requires пакета rt пропускают runtime-условные Perl-модули. Всплыли 3: CSS::Inliner (HTML+CSS), GraphViz2 (графы), DateTime::Set (calendar display-mode). Первые 2 собраны girar 426095; DateTime::Set уже в Сизифе (epm install). ⚠️ rt не Requires perl(DateTime/Set.pm) — пакетный баг
-[reference_rt_package_requires.md](reference_rt_package_requires.md) — spec rt 6.0.3-alt1 (#426033): DateTime/Set + Event/Recurrence + CSS/Inliner уже жёсткие Requires ✅; GraphViz2 пока опционален (%filter_from_requires стр.8-9, устарел т.к. #426095 опубликован в Сизиф) — RT требует его жёстко (RT/Graph/Tickets.pm:61), pending решение мейнтейнера. graphviz/dot доб. не надо (perl-GraphViz2 сам Depends: graphviz)
-[lesson_pam_system_check_localuser_uid500.md](lesson_pam_system_check_localuser_uid500.md) — ALT поднял порог system-check-localuser до uid>=1000 (даже legacy) → SSSD-доменные юзеры 500-999 отваливаются. Фикс dc-client/install-localuser-etersoft.sh + control etersoft. lav(192.168.0.55)/builder64/white=etersoft (2026-07-21). Внимание: хост `lav` (192.168.0.55) ≠ `builder64` (где идёт Claude-сессия) ≠ юзер `lav` (uid 502, sss)
-[lesson_restart_container_verify_autostart.md](lesson_restart_container_verify_autostart.md) — после настройки новой системы (cutover/миграция): перезапусти КОНТЕЙНЕР и перепроверь весь автозапуск (cron /etc/cron.d, timers, сервисы). В LXC crond (vixie-cron) не всегда перечитывает /etc/cron.d по inotify → RT fetchmail простой 9.5ч (2026-07-23). `/etc/cron.d` режим 0700 — пакетный, не «чинить»
### Короткие уроки (без отдельного файла)
- heredoc через SSH: `ssh host "cat > file" << 'EOF'` (кавычки вокруг маркера!)
- НЕ `iptables-restore` на работающей системе — сносит правила podman/docker
-При клонировании LXC в PVE — СНАЧАЛА поменять IP, ПОТОМ запускать
-Клонирование LXC в PVE: СНАЧАЛА поменять IP, ПОТОМ запускать
-`control ИМЯФАЙЛА РЕЖИМ` вместо chmod для suid/sgid на ALT
- epm: `-y` для неинтерактивной установки, `epm ei` для обновления
- WebFetch идёт через серверы Anthropic — для внутренних хостов использовать `curl`
- Обновление ALT: `epm release-upgrade --force`
- journald в LXC: `Storage=persistent` + `SystemMaxUse=16M`
- LXC на border: `systemd-tmpfiles-setup` status=73 → `systemd-tmpfiles --create`
- Cyrus autocreate: разделитель `|`, НЕ пробел!
- mail.etersoft.ru: postfix НЕ пишет в journald, только в `/var/log/mail/all` через rsyslog → fail2ban должен использовать `backend = polling` + `logpath = /var/log/mail/all` (не `%(postfix_log)s` из ALT defaults, который указывает на systemd)
- ALT sudo подключает **`/etc/sudo.d/`** (НЕ `/etc/sudoers.d/`!) — `cat /etc/sudoers` показывает `#includedir /etc/sudo.d`. Файлы в `/etc/sudoers.d/` игнорируются.
- eterban на priv: `/usr/bin/eterban`, не `/usr/sbin/`. Лог: `/var/log/eterban/eterban.log`, формат: `<ts> <ip> was blocked by <source>: <jail>` или `was unblocked by <source>`. ipset: `eterban_1`, `eterban_1_ipv6`
-[lesson_sip_etersoft_freeswitch.md](lesson_sip_etersoft_freeswitch.md) — sip.etersoft.ru FreeSWITCH: плоский диалплан в `/etc/freeswitch/dialplan/{local,sipnet}.xml` (БЕЗ default/), логи xz (нет zgrep), экстеншены 21/100/123/502, Grandstream за NAT priv
-[lesson_etcnet_hooks.md](lesson_etcnet_hooks.md) — etcnet ifup/ifdown хуки в `/etc/net/ifaces/<iface>/`, для зависимых интерфейсов (GRE поверх ppp0)
-[lesson_divserver_telemt_mtproxy.md](lesson_divserver_telemt_mtproxy.md) — divserver: telemt MTProxy на `0.0.0.0:443` через gre1 к 217.177.44.55 (обход блокировок Telegram)
-[lesson_dhcp_8net_dynamic_range.md](lesson_dhcp_8net_dynamic_range.md) — dhcp.office: 8/24 имеет динамический пул 8.100–8.254, 0/24 — 0.160–0.199; статика ставить вне
-[lesson_cyrus_sasl_restart.md](lesson_cyrus_sasl_restart.md) — cyrus-imapd на ALT: `serv restart` НЕ работает, нужен `systemctl restart`; SASL auxprop кэширует `sql_select` на процесс; `Hoffice` в defaultdomain — НЕ трогать; симлинк в `/var/spool/imap/domain/` опасен с autocreate
-[lesson_warp_oom_nft_deadlock.md](lesson_warp_oom_nft_deadlock.md) — warp.egw CT 703: OOM SIGKILL оставляет stale nft, чинится drop-in ExecStartPre; gre.beget CT 683 — путь до Cloudflare endpoint
-[lesson_builder_robot_gear_bad_owner_group.md](lesson_builder_robot_gear_bad_owner_group.md) — builder-robot: группа 5021 без имени (NFS /srv) → ручной gear делал etersoft.tar с безымянной группой → rpmbuild «Bad owner/group». Фикс: TMPDIR в setgid-каталоге /srv/builder-robot/tmp/gearbuild. Cron-сборки не задевает
-[lesson_roundcube_password_plugin_config.md](lesson_roundcube_password_plugin_config.md) — Roundcube password: `%c`→`%P` после 1.2, иначе DB Error 1064; не путать `password` и `password.log`
-[lesson_mail_postfix_sasl_config_path.md](lesson_mail_postfix_sasl_config_path.md) — mail.etersoft.ru: Postfix читает `/etc/postfix/sasl/smtpd.conf`, НЕ `/etc/sasl2/smtpd.conf`. Cyrus `imap=1`, Postfix `smtpauth=1`
-[lesson_mail_cert_renewal_webroot_hook.md](lesson_mail_cert_renewal_webroot_hook.md) — mail.etersoft.ru Let's Encrypt: renewal через cron.weekly (webroot, nginx должен быть UP), deploy-hook в `/etc/letsencrypt/renewal-hooks/deploy/` (НЕ `--renew-hook`) раскладывает cert в Postfix/Cyrus; инцидент 2026-07-04 — 2 причины протухания
-[lesson_rooter_home_pbs_restore.md](lesson_rooter_home_pbs_restore.md) — rooter@server доступ сломался удалением `/home/rooter` с aspetos (NFS); восстановление из PBS через `backup/restore-home.sh` (snapshot 2025-12-28); «shared-аккаунт не пускает» → проверять home на NFS-сервере
-[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_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
-[lesson_igw_telegram_ipv6_broken.md](lesson_igw_telegram_ipv6_broken.md) — igw: обход Telegram рабочий по IPv4, битый по IPv6; SOCKS-клиенты для TG должны юзать `socks5://` (локальный DNS), не `socks5h://`; `microsocks -b` ломает listener при `-i ::`
-[reference_create_lxc_container_pve.md](reference_create_lxc_container_pve.md) — создание LXC: клон template-CT 720 (ALT p11) на border, public 91.232.225.x на vmbr1, СНАЧАЛА IP потом старт
-[lesson_pptp_rarus_chap_secrets_domain.md](lesson_pptp_rarus_chap_secrets_domain.md) — pppd/PPTP с NT-доменом: name БЕЗ `DOMAIN\user` (слеш ломает chap-secrets → «No auth is possible»); MPPE через require-mppe-128 stateless; `mppe-stateless` нет такой опции; `/etc/ppp/options` в ALT-шаблоне содержит `replacedefaultroute` (крадёт default route)
-[lesson_pptp_nat_nf_conntrack_helper.md](lesson_pptp_nat_nf_conntrack_helper.md) — PPTP/FTP через Linux-NAT ломается на ядре ≥4.7 (nf_conntrack_helper=0): хелперы не пристёгиваются авто → ответный GRE не до клиента. Фикс: `iptables -t raw -A PREROUTING -p tcp --dport 1723 -j CT --helper pptp`. Диагностика tcpdump на NAT-боксе БЕЗ фильтра по client-IP (SNAT меняет адрес)
-[lesson_evpn_ikev2_strongswan_cert.md](lesson_evpn_ikev2_strongswan_cert.md) — evpn IKEv2/strongSwan: конфиг в /etc/strongswan/swanctl (НЕ /etc/swanctl), certs→fullchain.pem, restart для перечитки cert, deploy-hook, тест через charon-cmd с epm-sisyphus
-[reference_ruskru_telegram_notifier.md](reference_ruskru_telegram_notifier.md) — бот @ruskru на sites43 (CT 343, host03): спул /home/rusk/telegram-spool, send.py через SOCKS igw:1080, send_tg.sh нужен `|| exit`
-[lesson_office_home_nfs_mount_fail.md](lesson_office_home_nfs_mount_fail.md) — office build-хосты монтируют /home с homeserver=aspetos (NFSv4); home.mount падает при загрузке → ssh по ключу ломается (виден скелет с пустым authorized_keys). showmount на NFSv4 — ложный след. Фикс: примонтировать/ребут
-[reference_download_etersoft_mirror.md](reference_download_etersoft_mirror.md) — download.etersoft.ru (91.232.225.28): зеркало ALT, `ssh downloader@download`, синк `rsync_all.sh`; новый компонент апстрима → 404 пока не добавлен в синк
-[lesson_proxy_monitoring_functional_check.md](lesson_proxy_monitoring_functional_check.md) — мониторинг SOCKS5-прокси шлюзов обхода: на хосте telegraf, `check-proxies.sh` (curl через SOCKS), а не TCP-порт :1080 (порт открыт даже при мёртвом туннеле); список шлюзов править в этом скрипте
-[reference_telemt_fleet_ja4_monitoring.md](reference_telemt_fleet_ja4_monitoring.md) — telemt-флот chat.eterfund.ru (e5/.105, d.chat/divserver, s.chat/schat, b.chat/beget): обновление до 3.4.18 через epm (eepm <3.64.6x ломает repack→gzip-бинарь→`epm ei` сначала); CAP_NET_ADMIN для SYN-limiter; JA4-диагностика `beobachten`+`:9091/v1/runtime/tls-fingerprints`; мониторинг JA4 в InfluxDB(gateways)/Grafana через telegraf exec scrape
-[lesson_ikev2_beget_cert_dns_fix.md](lesson_ikev2_beget_cert_dns_fix.md) — ikev2.beget (.130) обход-шлюз: разбор почему лёг (сломан certbot urllib3 → протух LE-серт; standalone vs nginx:80 → webroot; ipsec restart для перечитки серта; пустой x509ca + новый корень ISRG Root YR; DNS «курица-яйцо» + start_action; грабли networkctl reload вычищает маршруты)
-[lesson_matrix_etersoft_synapse_disk_telegram_bridge.md](lesson_matrix_etersoft_synapse_disk_telegram_bridge.md) — matrix.etersoft.ru = Synapse на CT 291 (border), media_store пухнет от Telegram-моста mautrix-telegram (на tele.eterfund.ru, @telegrambot = 75G); диск переполнялся (pct resize +20G), мост выключен 2026-06-14; чистка через Admin API per-user или media_retention
3.`eterban_switcher.py` (main daemon in `eterban.service`) listens Redis pubsub and executes `ipset -A/-D`
4. Auto-unban: background thread in switcher checks `AutoBanManager` schedule, publishes to `unban` when ban period expires
**Why unban may fail**: if `eterban.service` is not running or not subscribed to Redis, `unban.py` silently succeeds (publish returns 0 subscribers) but ipset is NOT modified. Always verify with `eterban search` after unban.
**iptables rules** (created by switcher on startup):
- WAN interfaces: DNAT src from `eterban_1` to ban_server (91.232.225.67)
- WAN interfaces: REJECT FORWARD from `eterban_1` except ports 80,81,443
- Internal interface: DNAT dst from `eterban_1` ports 80,443 to ban_server:82
## Ban pages
- External (banned IP → our sites): http://91.232.225.67/ (port 80/81)
Все важные сведения по инфраструктуре записывай в `.claude/docs/` — файлы в репозитории, доступные всем. Заметки в session memory — только для текущей работы, не для долгосрочных справок.
### Память проекта (`.claude/memory/`)
**Основная база знаний проекта.** Перед ответом на вопросы про инфраструктуру — ищи сначала туда (`grep`/`read` по `.claude/memory/`). Новые заметки, уроки и справочники пиши туда же. Структура: