43 KiB
AegisOne Engineering — План миграции инфраструктуры и переписывания сервисной части
Статус: План утверждён, готов к реализации
Дата: 2026-05-17
Команда: Владелец + AI-ассистент
Примечание: Если при реализации возникнут вопросы — лучше уточнить, чем переделывать потом.
1. Текущее состояние
1.1. Публичная часть (aegisone.ru)
- Технологии: PHP 7.4, MySQL, inline CSS/JS
- Хостинг: Shared-хостинг (проблемы: HTTP 302-редирект, блокировка
/assets/, отключённыйRewriteEngine, PHP 7.4 тупик) - Страницы: Главная, услуги, блог, контакты, форма обратной связи
- SEO:
robots.txt,sitemap.xml, канонические URL - Решение: Не трогать. Перенести на VPS как есть в Docker-контейнер.
1.2. Сервисная часть (service.aegisone.ru)
- Технологии: PHP 7.4, MySQL, inline CSS/JS
- Функционал: Админ-панель (управление пользователями, объектами, SLA, опросниками, блогом, документами), расчёты (Risk Score, Object Index, SLA price), паспорта объектов
- Проблемы: PHP 7.4 ограничивает развитие, нет автоматизации отчётов, нет интеграций
- Решение: Полностью переписать на Python/FastAPI + Jinja2
1.3. Инфраструктура
- VPS: Уже есть, на нём один проект (FastAPI + Uvicorn + Celery + Nginx + PostgreSQL + Redis + Alembic)
- Хостинг: Платный, планируется отказ
- Git: Нет централизованного сервера, работа на локальной машине
- SSL: От регистратора домена (статический, неудобно для мультидомена)
- Домены:
aegisone.ru(публичная часть), планируетсяservice.aegisone.ru(админка)
2. Целевая архитектура
┌─────────────────────────────────────────────────────────────────────┐
│ VPS │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Nginx (reverse proxy + SSL) │ │
│ │ порт 80/443, Let's Encrypt │ │
│ │ │ │
│ │ aegisone.ru ──────────────► php-fpm container (порт 9000) │ │
│ │ service.aegisone.ru ─────► fastapi container (порт 8000) │ │
│ │ other-project.ru ────────► project2 container (порт 8001) │ │
│ │ git.aegisone.ru ─────────► gitea container (порт 3000) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ AegisOne PHP │ │ AegisOne Python │ │ Other Project │ │
│ │ (публичная) │ │ (админка) │ │ (FastAPI) │ │
│ │ │ │ │ │ │ │
│ │ • Главная │ │ • Аутентификация│ │ • ... │ │
│ │ • Услуги │ │ • Пользователи │ │ │ │
│ │ • Блог │ │ • Объекты │ │ │ │
│ │ • Контакты │ │ • Клиенты │ │ │ │
│ │ • FAQ │ │ • SLA │ │ │ │
│ │ • Карусель │ │ • Опросники │ │ │ │
│ │ • Форма │ │ • Расчёты │ │ │ │
│ │ │ │ • Отчёты (PDF) │ │ │ │
│ │ │ │ • Документы │ │ │ │
│ │ │ │ • Yandex Disk │ │ │ │
│ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │ │
│ └──────────┬──────────┘ │ │
│ │ │ │
│ ┌──────────▼──────────┐ ┌─────────▼────────┐ │
│ │ PostgreSQL │ │ PostgreSQL │ │
│ │ (AegisOne БД) │ │ (Project 2 БД) │ │
│ │ │ │ │ │
│ │ • users │ │ • ... │ │
│ │ • customers │ │ │ │
│ │ • objects │ │ │ │
│ │ • sla_contracts │ │ │ │
│ │ • questionnaire_* │ │ │ │
│ │ • blog_posts │ │ │ │
│ │ • cases │ │ │ │
│ │ • documents │ │ │ │
│ │ • photos │ │ │ │
│ │ • audit_log │ │ │ │
│ └─────────────────────┘ └──────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Redis │ (кэш, Celery broker) │
│ └─────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Celery Workers (Python) │ │
│ │ │ │
│ │ • Генерация отчётов (PDF, Excel) │ │
│ │ • Загрузка фото на Yandex Disk │ │
│ │ • Интеграция с 1С (по мере необходимости) │ │
│ │ • Фоновые расчёты, уведомления │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Gitea │ │ Certbot │ │
│ │ (Git-сервер) │ │ (Let's Encrypt) │ │
│ │ │ │ │ │
│ │ • aegisone-php │ │ • aegisone.ru │ │
│ │ • aegisone-py │ │ • service.aeg.. │ │
│ │ • project2 │ │ • other.ru │ │
│ │ • CI/CD Actions │ │ • автообновление│ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Yandex Disk API (облачное хранилище) │ │
│ │ │ │
│ │ /AegisOne/ │ │
│ │ ├── objects/{object_id}/ │ │
│ │ │ ├── photos/{photo_id}.jpg │ │
│ │ │ └── documents/{doc_id}/ │ │
│ │ │ ├── {photo_id}.jpg │ │
│ │ │ └── report_{doc_id}.pdf │ │
│ │ └── ... │ │
│ │ │ │
│ │ В PostgreSQL хранятся: file_id, file_url, привязка к объекту│ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3. Технологический стек
3.1. Публичная часть (без изменений)
| Компонент | Технология | Примечание |
|---|---|---|
| Язык | PHP 7.4 | Не обновлять, не трогать |
| БД | MySQL | Мигрировать на PostgreSQL позже (опционально) |
| Веб-сервер | Nginx + PHP-FPM | В Docker-контейнере |
| CSS/JS | Inline | Без изменений |
3.2. Сервисная часть (Python)
| Компонент | Технология | Примечание |
|---|---|---|
| Язык | Python 3.11+ | |
| Фреймворк | FastAPI | REST API + серверный рендеринг |
| Шаблоны | Jinja2 | Серверный рендеринг, как сейчас PHP |
| Веб-сервер | Uvicorn | ASGI-сервер |
| ORM | SQLAlchemy 2.0 + Alembic | Миграции БД |
| БД | PostgreSQL 15+ | Единая БД для всех проектов |
| Аутентификация | JWT (python-jose) | Токены для API и сессий |
| Фоновые задачи | Celery + Redis | Отчёты, загрузка файлов, интеграции |
| Генерация отчётов | WeasyPrint (PDF), openpyxl (Excel) | |
| Yandex Disk | yandex-disk SDK / REST API | OAuth 2.0 |
| Валидация | Pydantic | Схемы данных |
3.3. Инфраструктура
| Компонент | Технология | Примечание |
|---|---|---|
| Контейнеризация | Docker + Docker Compose | |
| Reverse proxy | Nginx | Маршрутизация по доменам |
| SSL | Let's Encrypt + Certbot | Автообновление |
| Git-сервер | Gitea | Лёгкий, встроенный CI/CD |
| CI/CD | Gitea Actions | Автоматический деплой |
| Мониторинг | (опционально) Uptime Kuma |
3.4. Мобильные приложения (будущее)
| Компонент | Технология | Примечание |
|---|---|---|
| Фреймворк | Flutter | |
| API | FastAPI REST endpoints | Те же, что для веб-админки |
| Аутентификация | JWT |
4. Почему Jinja2, а не SPA
4.1. Сравнение
| Критерий | Jinja2 (SSR) | SPA (React/Vue) |
|---|---|---|
| Серверная нагрузка | Рендерит HTML на сервере | Отдаёт статику + JSON API |
| Масштабирование | Горизонтальное: Nginx → N FastAPI инстансов | CDN для статики + Nginx → API |
| Сложность разработки | Один стек, один деплой | Два стека, два деплоя, CORS |
| Скорость разработки | Быстро | Медленнее |
| Команда | 1-2 Python-разработчика | Python + JS/TS разработчики |
| SEO | Не нужен (админка закрыта) | Не нужен |
| Мобильные приложения | API тот же — Flutter подключается | API тот же — Flutter подключается |
| Поддержка | Проще | Сложнее (два кодовых базы) |
4.2. Масштабирование Jinja2 по России
При росте нагрузки:
- Вертикальное: Увеличить ресурсы VPS (CPU, RAM)
- Горизонтальное: Несколько инстансов FastAPI за Nginx (load balancing)
- Кэширование: Redis для кэширования тяжёлых запросов
- CDN: Для статики (CSS, JS, изображения) — Cloudflare или аналог
Jinja2 не является узким местом. Узким местом будет БД или внешние API (Yandex Disk, 1С).
4.3. Вердикт
Jinja2 — правильный выбор. Для B2B-админки SPA — это оверинжиниринг. Jinja2 даёт:
- Быструю разработку
- Простую поддержку
- Легкое масштабирование
- Единую кодовую базу
- Готовность к мобильным приложениям (тот же API)
5. Этапы реализации
Этап 1: Docker-фундамент на VPS (1-2 недели)
Цель: Подготовить VPS для мультипроектной работы с Docker.
1.1. Установка Docker и Docker Compose
# На VPS (Ubuntu/Debian)
apt update && apt upgrade -y
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
1.2. Базовая структура директорий на VPS
/opt/
├── nginx-proxy/ # Nginx reverse proxy + Certbot
│ ├── docker-compose.yml
│ ├── nginx.conf
│ └── certs/ # Let's Encrypt сертификаты
├── gitea/ # Git-сервер
│ ├── docker-compose.yml
│ └── data/ # Данные Gitea
├── aegisone-php/ # Публичная часть (PHP)
│ ├── docker-compose.yml
│ └── src/ # Исходный код (git clone)
├── aegisone-py/ # Сервисная часть (Python)
│ ├── docker-compose.yml
│ ├── app/ # FastAPI приложение
│ ├── migrations/ # Alembic миграции
│ └── requirements.txt
└── project2/ # Существующий проект
└── docker-compose.yml
1.3. Nginx reverse proxy + Certbot
- Один Nginx-контейнер на портах 80/443
- Маршрутизация по
server_name:aegisone.ru→aegisone-php:80service.aegisone.ru→aegisone-py:8000git.aegisone.ru→gitea:3000other-project.ru→project2:8000
- Certbot в отдельном контейнере или встроенный (nginx-proxy + acme-companion)
1.4. Gitea (Git-сервер)
- Docker-образ
gitea/gitea:latest - Порт 3000 →
git.aegisone.ru - PostgreSQL для данных Gitea
- Встроенный CI/CD (Gitea Actions)
- Репозитории:
aegisone-php(публичная часть, перенос с текущего хостинга)aegisone-py(новая сервисная часть)project2(существующий проект)infra(конфигурации Docker, Nginx, CI/CD)
1.5. Обёртка существующего проекта в Docker
- Создать
docker-compose.ymlдля project2 - Протестировать работоспособность
- Настроить домен
other-project.ru
Критерий завершения этапа:
- Docker + Docker Compose установлены
- Nginx reverse proxy работает, маршрутизирует по доменам
- Certbot выдаёт SSL-сертификаты (Let's Encrypt)
- Gitea запущен на
git.aegisone.ru - Существующий проект работает в Docker
- Все домены доступны по HTTPS
Этап 2: Перенос AegisOne на VPS (1 неделя)
Цель: Перенести публичную часть с хостинга на VPS, отключить хостинг.
2.1. Docker-контейнер для PHP
# /opt/aegisone-php/docker-compose.yml
services:
nginx:
image: nginx:alpine
ports:
- "9080:80" # Внутренний порт, внешний через reverse proxy
volumes:
- ./src:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
php:
image: php:7.4-fpm
volumes:
- ./src:/var/www/html
environment:
- DB_HOST=mysql
- DB_NAME=aegisone
- DB_USER=aegisone
- DB_PASS=<password>
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: <root_password>
MYSQL_DATABASE: aegisone
MYSQL_USER: aegisone
MYSQL_PASSWORD: <password>
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
2.2. Перенос файлов
- Скачать все файлы с хостинга (FTP/SFTP)
- Загрузить в
/opt/aegisone-php/src/ - Настроить
config.phpдля нового окружения (DB_HOST=mysql)
2.3. Миграция БД
- Экспорт MySQL с хостинга:
mysqldump -u user -p db_name > backup.sql - Импорт в Docker MySQL:
docker exec -i aegisone-php-mysql mysql -u aegisone -p aegisone < backup.sql - Проверить работоспособность
2.4. Настройка домена
- DNS:
aegisone.ru→ IP VPS - Nginx reverse proxy:
server_name aegisone.ru→aegisone-php:9080 - SSL: Certbot для
aegisone.ru
2.5. Тестирование и отключение хостинга
- Проверить все страницы: главная, услуги, блог, контакты, форма
- Проверить карусель, FAQ, тему (светлая/тёмная)
- Проверить Яндекс.Карту с переключением темы
- После подтверждения — отключить хостинг
Критерий завершения этапа:
- Публичная часть работает на VPS
- Все страницы загружаются корректно
- Форма обратной связи работает
- Яндекс.Карта переключает тему
- Домен
aegisone.ruуказывает на VPS - Хостинг отключён
Этап 3: Python-админка (FastAPI + Jinja2) (3-5 недель)
Цель: Полностью переписать сервисную часть на Python.
3.1. Структура проекта
aegisone-py/
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
├── alembic.ini
├── migrations/ # Alembic миграции
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI приложение
│ ├── config.py # Настройки (env vars)
│ ├── database.py # SQLAlchemy engine, session
│ ├── models/ # SQLAlchemy модели
│ │ ├── __init__.py
│ │ ├── user.py
│ │ ├── customer.py
│ │ ├── object.py
│ │ ├── sla.py
│ │ ├── questionnaire.py
│ │ ├── blog.py
│ │ ├── case.py
│ │ ├── document.py
│ │ ├── photo.py
│ │ └── audit_log.py
│ ├── schemas/ # Pydantic схемы
│ │ ├── __init__.py
│ │ ├── user.py
│ │ ├── customer.py
│ │ └── ...
│ ├── api/ # API endpoints
│ │ ├── __init__.py
│ │ ├── auth.py # Логин, JWT
│ │ ├── users.py
│ │ ├── customers.py
│ │ ├── objects.py
│ │ ├── sla.py
│ │ ├── questionnaire.py
│ │ ├── blog.py
│ │ ├── cases.py
│ │ ├── documents.py
│ │ └── reports.py
│ ├── templates/ # Jinja2 шаблоны
│ │ ├── base.html # Базовый шаблон
│ │ ├── login.html
│ │ ├── dashboard.html
│ │ ├── users/
│ │ ├── customers/
│ │ ├── objects/
│ │ ├── sla/
│ │ ├── questionnaire/
│ │ ├── blog/
│ │ ├── documents/
│ │ └── reports/
│ ├── static/ # CSS, JS, изображения
│ │ ├── css/
│ │ │ ├── service.css # Стили админки
│ │ │ └── ...
│ │ ├── js/
│ │ │ ├── main.js
│ │ │ └── ...
│ │ └── img/
│ ├── services/ # Бизнес-логика
│ │ ├── __init__.py
│ │ ├── auth_service.py
│ │ ├── calc_service.py # Расчёты (Risk Score, Object Index, SLA)
│ │ ├── report_service.py # Генерация отчётов
│ │ ├── yandex_disk_service.py # Интеграция с Yandex Disk
│ │ └── ...
│ ├── tasks/ # Celery задачи
│ │ ├── __init__.py
│ │ ├── reports.py
│ │ ├── yandex_disk.py
│ │ └── ...
│ └── utils/ # Утилиты
│ ├── __init__.py
│ ├── password.py
│ └── ...
└── tests/ # Тесты (опционально)
3.2. Миграция данных из MySQL в PostgreSQL
- Создать Alembic миграции для всех таблиц
- Написать скрипт миграции данных:
users→userscustomers→customersobjects→objectssla_contracts→sla_contractsquestionnaire_sessions,questionnaire_answers,questionnaire_items→ аналогичноblog_posts→blog_postscases→casesaudit_log→audit_log
- Протестировать миграцию на копии БД
3.3. Аутентификация
- JWT-токены (python-jose)
- Логин/пароль (bcrypt)
- Роли:
owner,engineer,technician - Сессии через cookies (для Jinja2) + JWT (для API)
- CSRF-защита для форм
3.4. CRUD-модули (по порядку приоритета)
3.4.1. Пользователи (/service/users/)
- Список, создание, редактирование, удаление
- Роль
ownerнельзя удалить, нельзя изменить роль - Блокировка/разблокировка
- Аудит действий
3.4.2. Клиенты (/service/customers/)
- Список, создание, редактирование, удаление
- ИНН, КПП, юридический адрес, контакты
- Связь с объектами и SLA
3.4.3. Объекты (/service/objects/)
- Список, создание, редактирование, удаление
- Привязка к клиенту
- Тип, адрес, площадь, сотрудники
- Risk Score, Complexity Index, Object Index (авторасчёт)
- SLA price (авторасчёт)
3.4.4. SLA контракты (/service/sla/)
- Список, создание, редактирование, удаление
- Привязка к клиенту и объекту
- Тарифы: Базовый, Оптимальный, Максимальный
- Время реакции, периодичность ТО
- Статус: active, expired, cancelled, negotiation
3.4.5. Опросник (/service/questionnaire/)
- Создание новой сессии
- 5 шагов: Коммерческий, Технический, Эксплуатация, Риски, Расчёт SLA
- Вопросы из БД (
questionnaire_items) - Сохранение ответов
- Авторасчёт: Risk Score, Complexity Index, Infrastructure Load, Service History, Object Index, SLA Price
- Формирование паспорта объекта
3.4.6. Блог (/service/blog/)
- Список, создание, редактирование, удаление
- Категории: audit, sla, incident, supervision, documentation, risk, cases
- HTML-редактор (toolbar)
- Автогенерация slug из заголовка
- Статус: draft, published
3.4.7. Примеры из практики (/service/cases/)
- Список, создание, редактирование, удаление
- Заголовок, текст, эффект
- Сортировка, активность
3.4.8. Документы (/service/documents/)
- Список документов (из
service/docs/*.md) - Ручная сортировка
- Переименование
- Гранулярные права: view, edit, cancel (по ролям)
- JSON-хранилище прав (
docs_permissions.json)
3.5. Расчёты (перенос из PHP)
calc_risk_score()— Risk Scorecalc_complexity()— Complexity Indexcalc_infrastructure_load()— Infrastructure Loadcalc_service_history()— Service Historycalc_object_index()— Object Indexcalc_sla_price()— SLA Pricerisk_multiplier()— множитель рискаrisk_label()— текстовая метка рискаobject_class()— класс объектаfmt_money()— форматирование денег
Все функции переписать на Python, покрыть тестами.
3.6. Дашборд (/service/dashboard/)
- Метрики: количество объектов, активных SLA, открытых задач
- Графики (Chart.js или аналог)
- Быстрые действия
- Последние активности (audit_log)
3.7. Фронтенд (Jinja2)
- Базовый шаблон (
base.html) с:- Боковой панелью (sidebar) с навигацией
- Верхней панелью (header) с пользователем и переключателем темы
- Основным контентом
- Темы: system → dark → light (localStorage, как сейчас)
- Кастомные скроллбары
- Тултипы на кнопках
- Модальные окна (создание/редактирование)
- Таблицы с поиском и пагинацией
- Адаптивность (мобильная версия)
Критерий завершения этапа:
- Все CRUD-модули работают
- Расчёты корректны (сравнить с PHP-версией)
- Миграция данных завершена
- Фронтенд полностью функционален
- Темы переключаются
- Мобильная версия работает
service.aegisone.ruдоступен по HTTPS
Этап 4: Интеграции (2-3 недели)
Цель: Добавить генерацию отчётов, интеграцию с Yandex Disk, фоновые задачи.
4.1. Yandex Disk API
- Регистрация приложения в Yandex OAuth
- Получение OAuth-токена
- SDK:
yandex-diskили REST API черезrequests - Структура папок:
/AegisOne/ ├── objects/{object_id}/ │ ├── photos/ │ │ └── {photo_id}.jpg │ └── documents/{doc_id}/ │ ├── {photo_id}.jpg │ └── report_{doc_id}.pdf └── ... - Эндпоинты:
POST /api/documents/{id}/upload-photo— загрузка фотоGET /api/documents/{id}/photos— список фотоDELETE /api/photos/{id}— удаление фото
- В БД: таблица
photos(id, document_id, object_id, yandex_file_id, yandex_file_url, uploaded_at, uploaded_by)
4.2. Генерация отчётов
- PDF: WeasyPrint (HTML → PDF)
- Шаблон паспорта объекта
- Шаблон отчёта по аудиту
- Шаблон SLA-контракта
- Excel: openpyxl
- Экспорт списка объектов
- Экспорт SLA-контрактов
- Экспорт отчётов по KPI
- Фоновая генерация через Celery (для тяжёлых отчётов)
4.3. Celery (фоновые задачи)
- Broker: Redis
- Задачи:
- Генерация PDF-отчётов
- Загрузка фото на Yandex Disk
- Отправка уведомлений (email, Telegram)
- Интеграция с 1С (по мере необходимости)
- Мониторинг: Flower (веб-интерфейс для Celery)
4.4. Интеграция с 1С (опционально, по мере необходимости)
- REST API 1С или OData
- Синхронизация: клиенты, объекты, договоры
- Фоновая задача Celery
Критерий завершения этапа:
- Yandex Disk API интегрирован
- Фото загружаются и привязываются к документам
- PDF-отчёты генерируются
- Excel-экспорт работает
- Celery запущен, задачи выполняются
- (Опционально) Интеграция с 1С настроена
Этап 5: CI/CD и автоматизация деплоя (1 неделя)
Цель: Настроить автоматический деплой при push в Git.
5.1. Gitea Actions (CI/CD)
- Встроенный CI/CD в Gitea (совместим с GitHub Actions)
- Workflow для
aegisone-py:name: Deploy AegisOne Python on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build and push Docker image run: | docker build -t registry.git.aegisone.ru/aegisone-py:latest . docker push registry.git.aegisone.ru/aegisone-py:latest - name: Deploy to VPS run: | ssh user@vps "cd /opt/aegisone-py && docker compose pull && docker compose up -d"
5.2. Структура репозиториев в Gitea
git.aegisone.ru/
├── aegisone/aegisone-php # Публичная часть (PHP)
├── aegisone/aegisone-py # Сервисная часть (Python)
├── aegisone/infra # Docker, Nginx, CI/CD конфиги
└── aegisone/project2 # Существующий проект
5.3. Автоматический деплой
- Push в
main→ Gitea Actions → сборка Docker-образа → деплой на VPS - Rollback:
docker compose down && docker compose up -dс предыдущим образом - Миграции БД: Alembic
upgrade headавтоматически при деплое
5.4. Локальная разработка
docker-compose.dev.ymlдля локальной разработки- Hot-reload для Python (uvicorn --reload)
- Локальная БД (PostgreSQL в Docker)
- Синхронизация с VPS:
git push→ автоматический деплой
Критерий завершения этапа:
- Gitea Actions настроены для всех проектов
- Push в
main→ автоматический деплой - Rollback работает
- Миграции БД применяются автоматически
- Локальная разработка через Docker
6. Миграция данных: MySQL → PostgreSQL
6.1. Таблицы для миграции
| MySQL таблица | PostgreSQL таблица | Примечание |
|---|---|---|
users |
users |
Без изменений |
login_attempts |
login_attempts |
Без изменений |
audit_log |
audit_log |
Без изменений |
objects |
objects |
+ customer_id FK |
object_assignments |
object_assignments |
Без изменений |
tasks |
tasks |
Без изменений |
task_comments |
task_comments |
Без изменений |
customers |
customers |
Новая таблица |
sla_contracts |
sla_contracts |
+ customer_id FK, contract_number, description, response_time_hours |
incidents |
incidents |
Без изменений |
engineer_kpi |
engineer_kpi |
Без изменений |
questionnaire_sessions |
questionnaire_sessions |
Без изменений |
questionnaire_answers |
questionnaire_answers |
Без изменений |
questionnaire_items |
questionnaire_items |
Новая таблица |
object_passports |
object_passports |
Без изменений |
blog_posts |
blog_posts |
ENUM категории изменён |
cases |
cases |
Без изменений |
6.2. Скрипт миграции
# scripts/migrate_mysql_to_postgres.py
import mysql.connector
import psycopg2
from psycopg2.extras import execute_batch
# Подключение к MySQL
mysql_conn = mysql.connector.connect(host='...', user='...', password='...', database='...')
mysql_cursor = mysql_conn.cursor(dictionary=True)
# Подключение к PostgreSQL
pg_conn = psycopg2.connect(host='...', user='...', password='...', database='...')
pg_cursor = pg_conn.cursor()
# Миграция каждой таблицы
tables = ['users', 'customers', 'objects', 'sla_contracts', ...]
for table in tables:
mysql_cursor.execute(f"SELECT * FROM {table}")
rows = mysql_cursor.fetchall()
if rows:
columns = rows[0].keys()
placeholders = ', '.join(['%s'] * len(columns))
cols = ', '.join(columns)
execute_batch(
pg_cursor,
f"INSERT INTO {table} ({cols}) VALUES ({placeholders}) ON CONFLICT DO NOTHING",
[tuple(row[col] for col in columns) for row in rows]
)
pg_conn.commit()
6.3. Проверка миграции
- Сравнить количество записей в MySQL и PostgreSQL
- Проверить FK-связи
- Протестировать CRUD-операции на PostgreSQL
- Откат: сохранить бэкап MySQL до миграции
7. Безопасность
7.1. Аутентификация и авторизация
- JWT-токены с expiration (1 час)
- Refresh tokens (7 дней)
- Роли:
owner,engineer,technician - Гранулярные права для документов (view, edit, cancel)
- CSRF-защита для форм
7.2. Защита данных
- Пароли: bcrypt (cost factor 12)
- HTTPS для всех доменов (Let's Encrypt)
- Firewall: только порты 80, 443, 22 (SSH)
- Docker: изоляция контейнеров, нет root в контейнерах
- БД: нет внешнего доступа, только из Docker-сети
7.3. Бэкапы
- PostgreSQL:
pg_dumpежедневно (cron) - Yandex Disk: файлы уже в облаке
- Gitea: бэкап репозиториев (tar)
- Хранение бэкапов: отдельный диск или облако
7.4. Мониторинг
- (Опционально) Uptime Kuma для мониторинга доступности
- Логи: Docker logs + ротация
- Алерты: email/Telegram при ошибках
8. Риски и митигация
| Риск | Вероятность | Влияние | Митигация |
|---|---|---|---|
| Ошибка миграции данных | Средняя | Высокое | Тестирование на копии, бэкап MySQL |
| Простои при деплое | Низкая | Среднее | Zero-downtime деплой (docker compose up -d) |
| Проблемы с SSL | Низкая | Среднее | Certbot автообновление, мониторинг |
| Yandex Disk API лимиты | Низкая | Низкое | Кэширование, retry logic |
| Нехватка ресурсов VPS | Средняя | Высокое | Мониторинг CPU/RAM, масштабирование |
| Ошибки в расчётах | Средняя | Высокое | Тесты, сравнение с PHP-версией |
9. Оценки времени
| Этап | Описание | Оценка |
|---|---|---|
| Этап 1 | Docker-фундамент | 1-2 недели |
| Этап 2 | Перенос AegisOne на VPS | 1 неделя |
| Этап 3 | Python-админка | 3-5 недель |
| Этап 4 | Интеграции | 2-3 недели |
| Этап 5 | CI/CD | 1 неделя |
| Итого | 8-12 недель |
10. Контрольные точки
| Точка | Описание | Критерий успеха |
|---|---|---|
| КП1 | Docker-фундамент готов | Все сервисы запущены, домены работают по HTTPS |
| КП2 | Публичная часть на VPS | aegisone.ru работает, хостинг отключён |
| КП3 | Python-админка MVP | CRUD для пользователей, объектов, SLA работает |
| КП4 | Python-админка полная | Все модули, расчёты, миграция данных завершены |
| КП5 | Интеграции | Yandex Disk, отчёты, Celery работают |
| КП6 | CI/CD | Автоматический деплой при push |
11. Открытые вопросы (уточнить перед реализацией)
Важно: Если при реализации возникнут вопросы — лучше уточнить, чем переделывать потом.
- Миграция данных: Переносим все данные из MySQL в PostgreSQL или начинаем с чистой БД? (Рекомендация: мигрировать)
- Домен для админки:
service.aegisone.ruилиapp.aegisone.ru? (Рекомендация:service.aegisone.ru) - Yandex Disk OAuth: Использовать токен приложения или OAuth с авторизацией пользователя? (Рекомендация: токен приложения для простоты)
- Генерация отчётов: Какие именно отчёты нужны в первую очередь? (Паспорт объекта, отчёт по аудиту, SLA-контракт?)
- Интеграция с 1С: Какая версия 1С? Какой метод интеграции (REST API, OData, файловый обмен)?
- Мониторинг: Нужен ли Uptime Kuma или другой мониторинг? (Рекомендация: да, для продакшена)
- Бэкапы: Где хранить бэкапы PostgreSQL? (Отдельный диск на VPS, облако, другой сервер?)
- Тестирование: Покрывать ли код тестами? (Рекомендация: да, хотя бы критические расчёты)
- Документация: Вести ли документацию по API? (Рекомендация: да, через FastAPI автоматическую /docs)
- Логирование: Какой уровень логирования? Куда писать логи? (Рекомендация: INFO в stdout, Docker logs)
12. Следующие шаги
- Утвердить план — ответить на открытые вопросы (раздел 11)
- Начать Этап 1 — Docker-фундамент на VPS
- Параллельно — создать репозитории в Gitea, настроить CI/CD skeleton
- После Этапа 1 — приступить к Этапу 2 (перенос PHP)
- После Этапа 2 — приступить к Этапу 3 (Python-админка)
Документ создан: 2026-05-17
Версия: 1.0
Автор: AI-ассистент + Владелец
Статус: Готов к реализации после утверждения