Skip to main content

Инфраструктура проекта 1anketa.uz

Введение

Данное руководство описывает минимально достаточную, безопасную и управляемую инфраструктуру на «обычном» облачном хостинге без использования managed-LB и без кластеризации БД/кеша. Основные цели: отделить данные от фронт-части, вынести статику в S3-совместимое хранилище, навести порядок в сетевой сегментации и фаервол-правилах, не усложняя схему сверх необходимого.

Ключевые допущения: – Один публичный IP на pfSense (NAT/фильтрация). – Внутренняя подсеть 172.19.10.0/24 общая для новых ВМ. – Один Web-сервер (приложение и TLS на нём). – Отдельные ВМ для MySQL, Redis, MongoDB. – S3 провайдера (AWS-совместимый) только для статики. – Мониторинг и резервное копирование подключаются позже.

Текущий ландшафт и требования

  1. Сервер приложения (Web Service).
  2. База данных (MySQL).
  3. Кеш (Redis).
  4. Документы/медиа вынести в S3; старый сервер должен выгрузить накопленные файлы в тот же бакет.
  5. Минимум открытых портов из Интернета: всё за pfSense.
  6. VPN и базовая сетебезопасность уже настроены на уровне облака; используем их как данность.

Целевая минимальная схема

                                                 Интернет
|
[ ПУБЛИЧНЫЙ IP ]
|
+-------------------+
| pfSense (NAT) |
| Firewall / VPN |
+-------------------+
|
| (LAN: 172.19.10.1/24)
|
172.19.10.0/24 (внутренняя подсеть)
┌──────────────────────┬───────────────────────┬───────────────────────┐
│ │ │ │
+----------------+ +----------------+ +----------------+ +----------------+
| WEB #1 | | MySQL | | Redis | | MongoDB |
| 172.19.10.25 | | 172.19.10.22 | | 172.19.10.23 | | 172.19.10.24 |
| HTTPS/HTTP | | 3306/TCP | | 6379/TCP | | 27017/TCP |
+----------------+ +----------------+ +----------------+ +----------------+
|
| Исходящий 443/TCP (узкие правила egress)
V
+----------------------+
| S3 (провайдера) |
| бакет: приватный |
| versioning: ON |
| object lock: OFF |
+----------------------+

Миграция статики: [Старый сервер] --443--> S3 (тот же бакет) → WEB #1 использует S3 на чтение/запись

Объяснение компонентов (почему так)

  1. pfSense Роль единственной точки публикации (NAT 443/80 на WEB #1) и фильтрации. Входящее — только к Web-серверу. Исходящее — по белому списку (в первую очередь: S3 endpoint провайдера и системные репозитории).

  2. Web #1 Единственный публично доступный сервис за pfSense. TLS на стороне приложения (сертификат выдают разработчики). Доступ к БД/кешу/NoSQL — только по внутренним адресам. Работа со статикой — через S3 SDK/клиент; локальные медиа не накапливаем.

  3. Data-узлы (MySQL/Redis/MongoDB) Изолированы в той же подсети, но с доступом только от WEB #1 по соответствующим портам. Из Интернета не публикуются. Реплики/кластеризация на этом этапе не требуются.

  4. S3 (облачный провайдер, AWS-совместим) Бакет приватный. Версионность включена (защита от случайных перезаписей при миграции и эксплуатации). Object Lock выключен (иначе усложнит удаление/исправление артефактов). Возможна точечная политика публичного чтения для определённого префикса при необходимости.

Адресация и DNS

Адреса: – pfSense LAN: 172.19.10.1/24 – MySQL: 172.19.10.22/24 – Redis: 172.19.10.23/24 – MongoDB: 172.19.10.24/24 – WEB #1: 172.19.10.25/24

DNS: – Публичный A/AAAA → публичный IP pfSense. – Внутренние имена (любой вариант: локальный DNS на pfSense или /etc/hosts):

Публикация и NAT (pfSense)

Port Forward: – TCP 443 → 172.19.10.25:443 (WEB #1) – TCP 80 → 172.19.10.25:80 (только если нужен HTTP-01/редирект; иначе можно закрыть)

WAN Rules: – Разрешить входящие 443 (и 80 при необходимости) только к соответствующим правилам NAT. – Остальное — блокировать.

LAN Egress (минимально необходимые): – WEB #1 → S3 endpoint провайдера (443/TCP). – WEB #1 → системные репозитории/обновления (443/TCP). – Data-узлам (MySQL/Redis/MongoDB) — как минимум NTP/DNS/обновления; остальной исходящий трафик по умолчанию запрещён.

Внутрисетевые правила (основная логика)

Allow: – WEB #1 → MySQL (3306/TCP). – WEB #1 → Redis (6379/TCP). – WEB #1 → MongoDB (27017/TCP).

Deny: – Любые подключения к MySQL/Redis/MongoDB не с WEB #1. – Входящие из Интернета к Data-узлам.

SSH: – Доступ к ВМ — только через ваш существующий VPN/бастион; пароли запрещены, только ключи.

Хранилище статики (S3) — настройки

Создание бакета: – Приватный. – Версионность: включена. – Object Lock (блокировка): выключена.

Доступы: – Для приложения (WEB #1) — отдельный ключ/секрет с минимальными правами (Get/Put/Delete/List в пределах бакета или конкретного префикса). – Для старого сервера — отдельный временный ключ только на миграцию.

Использование в приложении: – Сервер-сайд: прямые операции через SDK. – При необходимости клиентских загрузок — presigned URLs; включить CORS на бакете для нужных методов и источников.

Опционально (позже): – Публичное чтение только для конкретного префикса (например, uploads/public/*) отдельной bucket-политикой.

Миграция статики со старого сервера

  1. Подключить старый сервер к тому же S3 (endpoint провайдера, ключ/секрет).
  2. Выполнить первичный sync (aws-cli или rclone) из локальной директории статики в бакет.
  3. Перевести приложение на использование S3 в «read-through» режиме.
  4. Выполнить финальный дельта-sync в момент переключения.
  5. Отключить локальные записи на старом сервере, убедиться, что новая статика пишет/читается из S3.

Мини-чеклист запуска

– pfSense: Port Forward 443/80 → WEB #1; egress на S3 и репозитории. – ВМ: статические IP; службы слушают только на 172.19.10.0/24; хост-фаервол по желанию (доп. к pfSense). – WEB #1: переменные окружения S3 (endpoint, region, bucket, ключи); приложение работает с S3. – Data-узлы: убедиться, что доступны только с WEB #1. – DNS: публичный домен указывает на публичный IP pfSense; внутренние имена разрешаются. – Тест: загрузка/чтение файла через приложение → S3; доступ к БД/кешу/NoSQL — ок; лишние пути извне закрыты.

Дальнейшее развитие (когда придёт время)

– Добавить балансировщик (Nginx/HAProxy) и второй Web-инстанс; хранить сессии в Redis. – Включить мониторинг (Zabbix или Prometheus). – Настроить резервное копирование БД/конфигов и lifecycle-политику для S3-версий. – Рассмотреть private/VPC endpoint для S3 у провайдера (если доступен), чтобы убрать исходящий трафик в Интернет для статики.


Дополнительные детали и пояснения

CORS для бакета (значения в диалоговом окне)

Если фронт на вашем домене: Allowed Origins: https://app.example.com Allowed Methods: GET, POST, PUT (при необходимости добавьте DELETE, HEAD) Allowed Headers: * Expose Headers: ETag, Content-Length, Content-Type, x-amz-request-id, x-amz-version-id Max age seconds: 3000

Если нужно быстро “на всё” (временное решение): Allowed Origins: * Allowed Methods: GET, POST, PUT Allowed Headers: * Expose Headers: ETag, Content-Length, Content-Type Max age seconds: 3000

Комментарий: выставить CORS через UI достаточно; aws-cli не обязателен. Если позже понадобится публичный доступ к части файлов, откроем публичное чтение точечно на префикс политикой бакета.

Правила для pfSense (WEB1 = 172.19.10.25)

Вход с Интернета (NAT + auto-rules на WAN):

  • Проброс 443/TCP → 172.19.10.25:443.
  • Проброс 80/TCP → 172.19.10.25:80 (только если нужен HTTP-01/редирект; можно выключить после выпуска сертификата).

Исходящий трафик (LAN egress):

  • Разрешить 172.19.10.25 → S3-эндпоинт провайдера: 443/TCP.
  • Разрешить обновления ОС (172.19.10.25 и узлам БД/кеша/NoSQL) → репозитории: 443/TCP.
  • Остальное исходящее — по умолчанию запрет (опционально, если хотите «белый список»).

Внутрисетевые правила (LAN → LAN):

  • Разрешить: 172.19.10.25 → 172.19.10.20:3306 (MySQL).
  • Разрешить: 172.19.10.25 → 172.19.10.30:6379 (Redis).
  • Разрешить: 172.19.10.25 → 172.19.10.40:27017 (MongoDB).
  • Запретить: любые другие источники → [ MySQL, Redis, MongoDB ] (все порты).
  • SSH/админка — только через уже настроенный VPN/бастион.

Подсказки:

  • Создайте Aliases: WEB1, MYSQL, REDIS, MONGO; S3_ENDPOINTS (FQDN), REPOS (сети/домены репозиториев).
  • Порядок правил важен: разрешающие — выше общего “Block”.

Рекомендуемые размеры ВМ (реалистично под ваш текущий профиль)

Дам два профиля: “Бюджетный старт” (укладывается примерно в ваши 24 ГБ суммарно) и “Умеренный запас”.

Бюджетный старт (сумма ≈ 24 ГБ RAM)

  • pfSense: 2 vCPU, 2 ГБ RAM, 20–40 ГБ SSD.

  • WEB1: 4 vCPU, 6–8 ГБ RAM, 80–160 ГБ SSD.

  • MySQL: 4 vCPU, 8 ГБ RAM, 150–300 ГБ NVMe (отдельный диск под /var/lib/mysql).

    • innodb_buffer_pool_size ≈ 4–5 ГБ (50–60% RAM узла).
  • Redis: 2 vCPU, 2–4 ГБ RAM, 20–50 ГБ SSD.

    • maxmemory выставить под рабочий объём; AOF everysec.
  • MongoDB: 4 vCPU, 6–8 ГБ RAM, 150–300 ГБ NVMe.

    • WiredTiger cache по умолчанию ~50% RAM; при 6–8 ГБ RAM это ок. При необходимости ограничить storage.wiredTiger.engineConfig.cacheSizeGB.

Умеренный запас (если увидите, что узкие места мешают)

  • WEB1: 6–8 vCPU, 8–12 ГБ RAM.
  • MySQL: 6–8 vCPU, 12–16 ГБ RAM (buffer pool 7–10 ГБ).
  • Redis: 2–4 vCPU, 4–6 ГБ RAM (под больший кеш/сессии).
  • MongoDB: 6–8 vCPU, 10–12 ГБ RAM (cache ~5–6 ГБ).

Примечания по тюнингу:

  • MySQL: включить slow query log, периодически смотреть индексы; innodb_flush_log_at_trx_commit=1 (или 2, если нужна прибавка скорости с малым риском).
  • Redis: protected-mode on, bind только на 172.19.10.0/24, пароль/ACL; save и AOF — по требованиям к персистентности.
  • MongoDB: auth включить; bind только на внутр. IP; WiredTiger по умолчанию обычно оптимально; при нехватке RAM урезать cacheSizeGB.
  • WEB1: держать статику в S3; локально — только временные файлы/кеш; следить за ulimit (nofile ≥ 65535) и net.core.somaxconn ≥ 1024.