🏗️ Архитектура — global-prod-main

Веб/ERP-узел ЕвроТранса: монолитный Docker-стек (фронтенды Nuxt + PHP-бэкенды 8.1/5.6 + три БД + VPN + почта + cron-интеграции) на одной ВМ
Хост: vm-evrotrans-yandex-global-1749891880453
Дата: 2026-06-05 / 06
ОС: Ubuntu 20.04.6 LTS (Focal) · ядро 5.4.0-216
CPU / RAM: 8 ядер · 7.9 GiB (swap занят ~3.4 GiB ⚠️)
Docker: 24.0.2 / Compose v2.18.1
Внешние IP: 89.111.137.188 · 31.44.10.106
Платформа: Yandex Cloud + Acronis Cyber Protect
Каталог стека: /home/evrotrans/stable · проект stable
🔗 См. также: аудит этого же сервера (AUDIT.html) · общая карта инфраструктуры ЕвроТранса
Содержание
  1. Назначение сервера
  2. Аппаратура и платформа
  3. Точки входа и сетевая топология
  4. Архитектура (слои)
  5. Карта контейнеров (18 шт.)
  6. Домены и маршрутизация nginx
  7. Бэкенды PHP (два поколения)
  8. Фронтенды (Node/Nuxt)
  9. Базы данных
  10. Служебные сервисы
  11. Cron-конвейер
  12. Тома и данные на хосте
  13. Безопасность и гигиена
  14. Заметки по эксплуатации
  15. Типовые команды

1. Назначение сервера

Монолитный Docker Compose-стек, разворачивающий всю инфраструктуру компании ЕвроТранс (логистика / автобусные перевозки / продажа билетов) на одной ВМ. Всё в одной bridge-сети network-evrotrans-stable-default (подсеть 172.19.0.0/16), наружу торчит только nginx (80/443) и openvpn (1194).

🌐 1. Фронтенды
Node/Nuxt · pm2-runtime :3000

Публичный сайт (monofront3-main-site), личный кабинет (monofront3-main-personal) и ERP-фронт sakai3. Старые фронты erp3/evro3/frontv3 собраны, но отключены (replicas: 0).

⚙️ 2. PHP-бэкенды
PHP-FPM :9000 · два поколения

php8 (8.1.17) — «новый» контур (api3, sales, partnerstickets). php5 (5.6.31, EOL) — «старый» контур (api, erp, erp2). Два параллельных поколения приложения.

🗄️ 3. Базы данных
2×MariaDB + MongoDB

Контуры ET (mysql) и PT (mysqlpt) на MariaDB 10.8.3, плюс mongo 4.4.30 для php8. У каждого MySQL-контура своя phpMyAdmin.

🔐 4. Граница и доступ
nginx + certbot + basicauth + openvpn

Единый HTTP/HTTPS-вход с TLS (Let's Encrypt), реверс-прокси и FastCGI ко всем сайтам. VPN-доступ в инфраструктуру. Админки — только через прокси + basicauth.

⏱️ 5. Фоновые задачи
crontab + autoheal

Cron-конвейер: бэкапы, очистка, PHP CLI (бизнес-логика api3) и wget-скрейперы внешних билетных/вокзальных систем. autoheal перезапускает unhealthy-контейнеры.

📧 6. Почта (через релей)
postfix выключен

Локальный postfix отключён (replicas: 0); php8 отправляет почту через внешний SMTP-релей 10.150.0.20:25 (сервер evrotrans-mailer).

Плюс инфраструктурные службы хоста: мониторинг (Zabbix agent2), резервное копирование/защита (Acronis Cyber Protect), systemd-resolved.

2. Аппаратное обеспечение и платформа

ПараметрЗначение
ПлатформаYandex Cloud + Acronis Cyber Protect (бэкап/защита)
ОСUbuntu 20.04.6 LTS (Focal) — 🟠 стандартная поддержка истекла (апр 2025), нужен план апгрейда / ESM
Ядро5.4.0-216-generic
CPU8 ядер
RAM7.9 GiB (занято ~5.0, свободно ~1.4, buff/cache ~1.5)
Swap8.0 GiB, занято ~3.4 GiB 🟠 (признак нехватки RAM)
Диск/dev/vda1 48 GiB, занято 36 GiB (75%), свободно 13 GiB — единый раздел /
Load avg1.64 / 1.76 / 1.93 (на 8 ядрах — комфортно, ~20%)
Uptime97 дней
Docker24.0.2, Compose v2.18.1
Стек на диске11 GiB. Топ папок: mysql 3.4G · web 2.6G · api3 1.3G · mongo 946M · pti3 466M · sales3 344M · openvpn 317M
⚠️ Основной риск — память: swap занят на 3.4 ГБ при ~1.4 ГБ свободной RAM. Контейнер mysql занимает 2.3 из 4 ГБ лимита и перезапускался 3 раза (остальные контейнеры — 0). На 8 ядрах CPU не является узким местом.

Прочие службы на хосте (вне Docker, из ss -tulpn):

3. Точки входа и сетевая топология

Наружу опубликованы только два сервиса:

Порт хостаСервисНазначение
80, 443nginxЕдиный HTTP/HTTPS-вход, реверс-прокси и FastCGI ко всем сайтам/сервисам
1194/tcp+udpopenvpnVPN-доступ в инфраструктуру

Внешние IP (из nginx-конфигов): 89.111.137.188, 31.44.10.106.

flowchart TB
  NET(["Интернет"]):::ext
  VPNC(["VPN-клиент"]):::ext

  subgraph BRIDGE["Docker bridge · network-evrotrans-stable-default · 172.19.0.0/16 (18 контейнеров)"]
    direction TB
    NGINX["nginx :80/443 · 172.19.0.5
реверс-прокси + FastCGI
89.111.137.188 / 31.44.10.106"]:::edge OVPN["openvpn :1194 · 172.19.0.14"]:::edge PHP8["php8 · 172.19.0.19"]:::hot CRON["crontab
network_mode: host"]:::back end SMTP(["SMTP-релей 10.150.0.20:25
(evrotrans-mailer)"]):::ext INTEG(["Внешние интеграции:
JWT · Telegram · SMS
Минтранс FTP (ПДП/ОНСИ/МР/АКТ) · GitHub"]):::ext EXTSYS(["Внешние билетные / вокзальные системы"]):::ext BKP(["Бэкап-сервер (ENV_BACKUP_SERVER_*)"]):::ext NET -->|":80/443"| NGINX VPNC -->|":1194"| OVPN PHP8 -->|"mail"| SMTP PHP8 -->|"интеграции"| INTEG CRON -->|"PHP CLI + wget"| EXTSYS CRON -->|"dump / rsync"| BKP classDef edge fill:#11202e,stroke:#4ea1ff,color:#dbe4ee classDef back fill:#241a0c,stroke:#ffb454,color:#dbe4ee classDef hot fill:#2a1416,stroke:#ff5c5c,color:#ffd9d9 classDef ext fill:#12161c,stroke:#5a6675,color:#cfd8e2
Рис. 1 — Точки входа и исходящие потоки: наружу только nginx (80/443) и openvpn (1194); php8 и crontab инициируют исходящие интеграции.

DNS-зоны: основная evrotrans.net (+ поддомены) и eprojeckt.ru (app/erp/p/trl/trlavs.eprojeckt.ru — каталоги в ./web, конфиги частью в .bak).

4. Архитектура (слои)

flowchart TB
  NET(["Интернет"]):::ext
  VPNC(["VPN-клиент"]):::ext
  SMTP(["Внешний SMTP-релей
10.150.0.20:25"]):::ext EXTAPI(["Внешние API · вокзалы
Минтранс FTP"]):::ext BKP(["Бэкап-сервер
ENV_BACKUP_SERVER_*"]):::ext subgraph HOST["ВМ vm-evrotrans (Yandex Cloud) — сеть 172.19.0.0/16"] direction TB subgraph EDGE["ГРАНИЦА"] direction TB NGINX["nginx :80/443
172.19.0.5"]:::edge CERT["certbot (TLS)
172.19.0.15"]:::edge BA["basicauth
172.19.0.3"]:::edge OVPN["openvpn :1194
172.19.0.14"]:::edge end subgraph FRONT["ФРОНТЫ · Node :3000"] direction TB SITE["monofront3-main-site
172.19.0.7"]:::front PERS["monofront3-main-personal
172.19.0.8"]:::front SAKAI["sakai3
172.19.0.6"]:::front OLDF["erp3 · evro3 · frontv3
(replicas:0)"]:::off end subgraph BACK["PHP-бэкенды :9000"] direction TB PHP8["php8 (8.1.17)
172.19.0.19 · 231% CPU"]:::hot PHP5["php5 (5.6.31, EOL)
172.19.0.18"]:::back end subgraph DATA["БАЗЫ ДАННЫХ"] direction TB MYSQL[("mysql (ET) · mariadb
172.19.0.13")]:::db MYSQLPT[("mysqlpt (PT) · mariadb
172.19.0.12")]:::db MONGO[("mongo :27017
172.19.0.9")]:::db POSTFIX["postfix (выкл. replicas:0)"]:::off end subgraph ADMIN["АДМИН / МОНИТОРИНГ"] direction TB PORT["portainer
172.19.0.10"]:::svc DOZ["dozzle
172.19.0.4"]:::svc MEXP["mongo-express
172.19.0.11"]:::svc PMA["phpmyadmin
172.19.0.17"]:::svc PMAPT["phpmyadminpt
172.19.0.16"]:::svc end subgraph OPS["ФОНОВО"] direction TB CRON["crontab
host-скрипты + PHP CLI + wget"]:::back AH["autoheal
172.19.0.2"]:::svc end DSOCK(["docker.sock"]):::ext end NET -->|":80/443"| NGINX VPNC -->|":1194"| OVPN CERT --- NGINX BA --- NGINX NGINX -->|"proxy_pass"| SITE NGINX -->|"proxy_pass"| PERS NGINX -->|"proxy_pass"| SAKAI NGINX -->|"FastCGI :9000"| PHP8 NGINX -->|"FastCGI :9000"| PHP5 NGINX -->|"proxy_pass"| PORT NGINX -->|"proxy_pass"| DOZ NGINX -->|"proxy_pass"| MEXP NGINX -->|"proxy_pass"| PMA NGINX -->|"proxy_pass"| PMAPT PHP8 --> MYSQL PHP8 --> MYSQLPT PHP8 --> MONGO PHP5 --> MYSQL PHP5 --> MYSQLPT PMA --> MYSQL PMAPT --> MYSQLPT MEXP --> MONGO PHP8 -->|"mail"| SMTP CRON --> PHP8 CRON -->|"PHP CLI + wget"| EXTAPI CRON -->|"dump / rsync"| BKP AH --> DSOCK classDef edge fill:#11202e,stroke:#4ea1ff,color:#dbe4ee classDef front fill:#0f2417,stroke:#56d364,color:#dbe4ee classDef back fill:#241a0c,stroke:#ffb454,color:#dbe4ee classDef hot fill:#2a1416,stroke:#ff5c5c,color:#ffd9d9 classDef db fill:#1d1430,stroke:#bc8cff,color:#e9def9 classDef svc fill:#10242b,stroke:#3fb6c9,color:#cfeef5 classDef ext fill:#12161c,stroke:#5a6675,color:#cfd8e2 classDef off fill:#171b21,stroke:#3a444f,color:#7d8896
Рис. 2 — Общая архитектура стека по слоям: граница (nginx/certbot/basicauth/openvpn) → фронты Nuxt и PHP-бэкенды → три БД; админки и фоновые задачи. Звёздочкой (replicas:0) отмечены отключённые сервисы.

Все сервисы стартуют декларативно с restart: always. Порядок старта: БД (healthy) → PHP (healthy) → nginx.

5. Карта контейнеров и сети (18 запущенных)

КонтейнерIP (172.19.0.x)CPURAMОбраз
nginx.52.9%44 MiBnginx:1.24.0-alpine
php8.19231% ⚠️313 MiBddan9/php8 (PHP 8.1.17)
php5.180%71 MiBddan9/php5 (PHP 5.6.31)
mysql (ET).135.7%2.34 GiB / 4 GiBmariadb:10.8.3
mysqlpt (PT).120%17 MiB / 2 GiBmariadb:10.8.3
mongo.90.3%458 MiBmongo:4.4.30
monofront3-main-site.71.7%395 / 512 MiB(build, pm2-runtime)
monofront3-main-personal.81.5%242 / 512 MiB(build, pm2-runtime)
sakai3.60%79 MiB(build, node .output)
openvpn.140.1%60 MiBddan9/openvpn-asu:2.14.1
portainer.100%13 MiBportainer:1.24.1-alpine
dozzle.45.3%55 MiBamir20/dozzle:v8.14.8
mongoexpress.110%27 MiBmongo-express:1.0.2
phpmyadmin.170%79 MiBphpmyadmin:5.1
phpmyadminpt.160%27 MiBphpmyadmin:5.1
certbot.150%4 MiBddan9/certbot
basicauth.30%1 MiBddan9/basicauth
autoheal.20%12 MiBwillfarrell/autoheal:1.2.0
📌 Переоценка php8 ~231% CPU: на хосте 8 ядер и load avg ~1.7 (≈20% общей мощности), поэтому 231% — это кратковременный всплеск одной задачи (≈2.3 ядра), скорее всего cron_php_api3_1min.sh, а не постоянная перегрузка. Стабильность не под угрозой, но скрипт стоит оптимизировать.
⚠️ Реальный сигнал давления на память: swap занят на 3.4 ГБ при ~1.4 ГБ свободной RAM. mysql занимает 2.3 из 4 ГБ лимита и перезапускался 3 раза (остальные контейнеры — 0).
📌 crontab запущен в network_mode: host, поэтому в списке сети (172.19.0.x) его нет.

6. Домены и маршрутизация (nginx)

Активные конфиги в ./nginx/conf.d/*.conf (рядом — десятки .bak-версий, в работе не участвуют). Точная маршрутизация (по fastcgi_pass/proxy_pass):

Конфиг / доменНазначениеБэкенд
evrotrans.net (+ *.evrotrans.net, default_server)главный сайтдинамический proxy_pass http://$service (по поддомену)
www.evrotrans.netглавный сайт(как выше)
api.evrotrans.netпубличный APIphp5:9000 + проксирование на api3.evrotrans.net/sales/ и /sales-api-rb/
api3.evrotrans.net (/web)API v3php8:9000
sales.evrotrans.net (/web)продажиphp8:9000 + проксирование на api3/sales/
partnerstickets.evrotrans.net (/web)партнёрские билетыphp8:9000
erp.evrotrans.netERPphp5:9000 (legacy)
erp2.evrotrans.netERP v2php5:9000 (legacy)
erp3.evrotrans.netERP-фронтдинамический proxy_pass http://$service (sakai3:3000 закомментирован)
pma / pma1.evrotrans.netадминки БДphpmyadmin:80 / phpmyadminpt:80
mde.evrotrans.netmongo-expressmongoexpress:8081
doz.evrotrans.netdozzledozzle:8080
ptr.evrotrans.netportainerportainer:9000
vpn.evrotrans.netOpenVPN adminhttps://openvpn:943
📌 Важно: «новый» контур (api3, sales, partnerstickets) работает на php8 (8.1), а «старый» (api, erp, erp2) — на php5 (5.6, EOL). Это два параллельных поколения приложения.
📌 Сайт/erp3 используют динамический upstream через переменную $service, вычисляемую из поддомена (~^(?<subdomain>.+)\.evrotrans\.net). Удобно, но без явного списка — опечатка в DNS/поддомене может увести трафик «в никуда».

Глобальные настройки nginx: worker_processes auto, worker_connections 1024, gzip on (level 6), keepalive_timeout 65.

⚠️ Rate limiting не настроен (limit_req/limit_conn отсутствуют) — нет защиты от всплесков/перебора. В старых .bak-конфигах встречаются прокси на несуществующие сервисы (caddy:3000, evro3:3000) — легаси.

6.1 Веб-корни (./web, монтируется в php5/php8/nginx как /var/www)

Отдельные document-root на каждый сайт: api.evrotrans.net, api3.evrotrans.net, erp.evrotrans.net, erp2.evrotrans.net, evrotrans.net, p.evrotrans.net, partnerstickets.evrotrans.net, sales.evrotrans.net, test.evrotrans.net, vpn.evrotrans.net, а также зоны *.eprojeckt.ru (app/eprojeckt/erp/p/trl/trlavs). Плюс служебные: html, inc, inc2, inctrl, inctrl2, deps, тестовые testmail*.php, MELAI.csv.

7. Бэкенды (PHP-FPM, порт 9000)

СервисВерсияНазначение
php8PHP 8.1.17 (NTS, OPcache)Основной бэкенд. Модули: mongodb, imagick, intl, gd, mysqli/pdo_mysql, pgsql, ldap, soap, snmp, mcrypt, bcmath, gmp, zip, xsl…
php5PHP 5.6.31 EOLLegacy-бэкенд для старого кода (api, erp, erp2)

Общие тома кода (монтируются и в nginx, и в оба PHP): ./api3, ./pti3, ./sales3, ./web. Структура backend-приложений (api3, pti3, sales3) единообразна: Dockerfile, dirs/, logs/, publish/, site/.

7.1 Интеграции php8 (из .env / compose)

8. Фронтенды (Node/Nuxt, pm2/node, порт 3000)

СервисСтатусНазначение
monofront3-main-site✅ healthy лимит 512MПубличный сайт (монорепо apps/main-site), запуск через pm2-runtime
monofront3-main-personal✅ healthy лимит 512MЛичный кабинет (apps/main-personal), pm2-runtime
sakai3✅ healthyERP-фронт SakaiERP (node .output/server)
erp3 / evro3 / frontv3⛔ replicas: 0Старые фронты (собраны, отключены)

Каждый фронт: Dockerfile + deploy/ + dist/ (готовая сборка монтируется в контейнер).

9. Базы данных

СервисОбразКонтурПеременные
mysqlmariadb:10.8.3ET (основной)ENV_MYSQL_ET_*
mysqlptmariadb:10.8.3PT (отдельный)ENV_MYSQL_ETPT_*
mongomongo:4.4.30NoSQL (для php8)ENV_MONGO_*

Каждый контур MySQL имеет свою phpMyAdmin. У обеих БД есть _DATABASE_IGNORE (исключения из бэкапа/репликации). Данные: ./mysql/database, ./mysqlpt/database, ./mongo/database.

10. Служебные сервисы

СервисРоль
certbotАвтообновление TLS (Let's Encrypt), ключи в ./certbot/keys, ACME через /.well-known/acme-challenge/
basicauthГенерация htpasswd для защиты админок (./basicauth/htaccess)
autohealПерезапуск контейнеров с label autoheal=true при unhealthy (интервал 60с)
crontabПланировщик (network_mode: host), конфиг ./crontab/config/root — см. §11
postfixSMTP-почта — выключен (replicas: 0); php8 шлёт через 10.150.0.20:25
openvpnVPN-шлюз (admin/root/user аккаунты в .env)

Мониторинг-панели за nginx+basicauth: portainer (Docker), dozzle (логи), mongo-express, две phpMyAdmin.

11. Плановые задачи (crontab, ./crontab/config/root)

Запуск через обёртки cron_admin.sh (от админа r3ddan9) и cron_user.sh (от evrotrans).

flowchart TB
  CRON["crontab (host)
config: ./crontab/config/root"]:::back ADMIN["cron_admin.sh (r3ddan9)
БЭКАПЫ И ОЧИСТКА (host/*.sh)"]:::back USER["cron_user.sh (evrotrans)"]:::back CRON --> ADMIN CRON --> USER subgraph BK["Бэкапы и очистка"] direction TB BCFG["config — 1/10/20 числа · 06:00"]:::back BDB["database — каждый час (58 * * * *)"]:::back BWEB["web — еженедельно (1/7/14/21/28 · 06:00)"]:::back BCLN["cleaner_* + logs_cleaner"]:::back end ADMIN --> BCFG ADMIN --> BDB ADMIN --> BWEB ADMIN --> BCLN BCLN -->|"rsync"| BKPSRV(["Бэкап-сервер
ENV_BACKUP_SERVER_*"]):::ext subgraph STK["СТЕК"] direction TB SCRT["certbot_renew (сб 01:00)"]:::edge SNGX["restart nginx (сб 03:35)"]:::edge SMYS["mysql_courtship (7 число)"]:::db end USER --> SCRT USER --> SNGX USER --> SMYS subgraph PHPCLI["PHP CLI · crontab-scripts-php"] direction TB P1["api3_1min ⚠️ КАЖДУЮ МИНУТУ"]:::back P2["api3_3min · 30min · 1w (пн 04:45)"]:::back end USER --> P1 USER --> P2 P1 -->|"нагрузка"| PHP8["php8
172.19.0.19 · 231% CPU"]:::hot P2 --> PHP8 subgraph WGET["WGET-скрейперы · crontab-scripts-wget/x_*"] direction TB WAPI["api / api3 (sms · telegram · actions)"]:::back WPART["партнёрские билеты (evrotrans · rosbilet)"]:::back WVED["ведомости (avgust · kpasru)"]:::back WVOK["вокзалы: artmark-mosmetro · melitopol
region-bilet · rostov · probilets
(интервалы 1 мин … 3 ч)"]:::back WCLN["x_cron-cleaner.sh — каждые 12 ч"]:::back end USER --> WAPI USER --> WPART USER --> WVED USER --> WVOK USER --> WCLN WAPI -->|"HTTP"| EXTSYS(["Внешние билетные /
вокзальные системы"]):::ext WPART -->|"HTTP"| EXTSYS WVED -->|"HTTP"| EXTSYS WVOK -->|"HTTP"| EXTSYS classDef edge fill:#11202e,stroke:#4ea1ff,color:#dbe4ee classDef back fill:#241a0c,stroke:#ffb454,color:#dbe4ee classDef hot fill:#2a1416,stroke:#ff5c5c,color:#ffd9d9 classDef db fill:#1d1430,stroke:#bc8cff,color:#e9def9 classDef ext fill:#12161c,stroke:#5a6675,color:#cfd8e2
Рис. 3 — Cron-конвейер: обёртки cron_admin/cron_user → бэкапы и очистка (rsync на бэкап-сервер), обслуживание стека, PHP CLI (нагрузка на php8) и wget-скрейперы внешних систем.

Бэкапы (./host/cron_home_backuper_*.sh) → на внешний сервер (ENV_BACKUP_SERVER_*): config — 1/10/20 числа в 06:00; database — каждый час (58 * * * *); web — раз в неделю (1/7/14/21/28 в 06:00).

Очистка (cron_backup_cleaner_*, cron_home_logs_cleaner): почасовая чистка БД-бэкапов, еженедельная чистка config/web/логов. Стек: cron_mysql_courtship (7 числа), cron_certbot_renew (сб 01:00), рестарт nginx по субботам 03:35.

PHP CLI (crontab-scripts-php/scripts/) — бизнес-логика api3: cron_php_api3_1min.shкаждую минуту ⚠️ (вероятный источник нагрузки на php8); _3min, _30min, _1w (понедельник 04:45).

WGET-скрейперы (crontab-scripts-wget/scripts/x_*.sh) — опрос внешних билетных/вокзальных систем по HTTP: x_api-evrotrans-*, x_api3-evrotrans-{sms,telegram,actions}-*; билеты партнёров: x_partners-tickets-{evrotrans,rosbilet}-*; ведомости: x_vedomosti-{avgust,kpasru}-*; вокзалы (vokzali): artmark-mosmetro, melitopol, region-bilet, rostov, probilets — с интервалами от 1 мин до 3 ч; x_cron-cleaner.sh — каждые 12 ч.

📌 Большой закомментированный блок «WGET OLD VERSION» в crontab — предыдущее поколение тех же интеграций.

12. Тома и данные на хосте

13. Безопасность и гигиена

Что сделано хорошо:
🟠 Требует внимания:
🔴 Риски безопасности этой архитектуры (управление секретами, EOL-софт, периметр доступа, гигиена конфигов) подробно разобраны в аудите сервера (AUDIT.html).

14. Заметки по эксплуатации

Из комментариев в compose видно недавнюю модернизацию:

🟠 Что проверить / держать в фокусе:
  1. Память: swap занят на 3.4 ГБ, свободно ~1.4 ГБ RAM — основной риск. Кандидаты на оптимизацию: лимит mysql (2.3/4 ГБ, 3 рестарта), всплески php8.
  2. Диск 75% (13 ГБ свободно) на едином разделе — растёт за счёт mysql (3.4 ГБ) и web (2.6 ГБ); следить, чистить логи/бэкапы.
  3. php8 cron cron_php_api3_1min.sh — источник всплесков CPU; профилировать (включён SYS_PTRACE), при возможности разнести по времени.
  4. php5 (5.6, EOL) обслуживает api/erp/erp2 — план миграции на php8.
  5. Ubuntu 20.04 — стандартная поддержка истекла; ESM или апгрейд.
  6. nginx без rate limiting — добавить limit_req для публичных API.
  7. Чистка .bak/легаси-конфигов nginx и резервных compose-файлов.
  8. Уже есть Zabbix-агент (:10050) — мониторинг логично навесить на него.

15. Типовые команды

cd /home/evrotrans/stable

docker compose ps                       # статус сервисов
docker stats --no-stream                # нагрузка
docker compose up -d                     # поднять/обновить стек
docker compose logs -f php8 nginx        # логи
docker compose build sakai3 && docker compose up -d sakai3   # пересборка фронта
docker compose restart php8              # перезапуск сервиса
docker exec stable-php8-1 php -v         # версия PHP
# хелперы хоста:
bash ./host/bash_restart_phps.sh         # рестарт PHP-контейнеров
bash ./host/cron_certbot_renew.sh        # обновить сертификаты