Skip to content

Latest commit

 

History

History
408 lines (324 loc) · 26.4 KB

File metadata and controls

408 lines (324 loc) · 26.4 KB

Руководство разработчика NectarinePanel

English · Українська · Русский · Polski

Это основная документация для разработчиков и операторов, которые устанавливают, изменяют, тестируют, выпускают или диагностируют NectarinePanel. Работа с веб-интерфейсом описана в руководстве пользователя. Остальные файлы docs/ используются как углублённый технический справочник.

1. Назначение проекта

NectarinePanel — модульный монорепозиторий для развёртывания и эксплуатации приложений на одном Ubuntu VPS, а не многосерверный планировщик. FastAPI отвечает за валидацию, авторизацию и состояние, Celery — за долгие задачи, а привилегированные изменения сервера проходят через локальный агент с ограниченным набором операций.

Стек: FastAPI, асинхронный SQLAlchemy, Alembic, PostgreSQL, Valkey, Celery, Nuxt 4, Vue 3, TypeScript, Pinia, системный агент и необязательный Telegram-бот на aiogram. Целевая рабочая система — Ubuntu 24.04 LTS. Для разработки нужны Python 3.12+, поддерживаемый в frontend/package.json Node.js LTS, npm 10+ и Docker Engine с Compose v2.

2. Структура репозитория

backend/        API FastAPI, модели, схемы, сервисы и миграции Alembic
worker/         задачи Celery и обработчик фоновых заданий
agent/          проверяемые системные операции и локальная HTTP-граница
frontend/       Nuxt, компоненты, composable-функции, переводы и тесты
telegram-bot/   необязательный бот владельца
installer/      установщик, обновление, удаление, модули systemd и Nginx
docs/           основные руководства и технические справочники
tests/          тесты репозитория, установщика и контейнерных файлов
scripts/        сценарии обслуживания и проверки

Сохраняйте существующую прагматичную структуру. Не добавляйте слои domain/application/infrastructure без конкретной необходимости. Маршруты обрабатывают HTTP, сервисы содержат переиспользуемую бизнес- и инфраструктурную логику, схемы определяют контракты API, а модели — структуру хранения данных.

3. Архитектура и поток операции

Browser -> Nginx -> Nuxt
                 -> FastAPI -> PostgreSQL
                            -> Valkey -> Celery worker / scheduler
                            -> local agent -> root-owned helper -> host
Telegram -> authenticated internal FastAPI endpoints

Типичная асинхронная операция:

  1. FastAPI аутентифицирует пользователя, проверяет RBAC, валидирует входные данные и создаёт записи задачи и аудита.
  2. Celery получает идентификаторы и несекретные параметры.
  3. Обработчик загружает актуальное состояние и зашифрованные учётные данные из хранилища.
  4. Привилегированная операция отправляется в типизированную конечную точку агента.
  5. Агент и вспомогательная программа повторно проверяют запрос и преобразуют его в фиксированный список аргументов или ограниченную файловую операцию.
  6. Обработчик сохраняет ход и результат; интерфейс использует WebSocket с резервным опросом API.

Никогда не добавляйте универсальный запуск команд в агент и не монтируйте сокет Docker в публичную серверную часть. Подробнее: архитектура, безопасность, проекты.

4. Локальное окружение

Все команды Python выполняются только через виртуальное окружение репозитория.

python3 -m venv .venv
.venv/bin/pip install -r backend/requirements-dev.txt
cd frontend && npm ci
cd ..
cp .env.example .env

Замените секреты для разработки в .env до передачи окружения другим людям:

openssl rand -hex 32
.venv/bin/python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

Полное Docker-окружение

docker compose up --build
docker compose exec backend python -m app.cli create-admin --username admin

Панель: http://localhost:3000, OpenAPI: http://localhost:8000/api/v1/docs. Порты разработки привязаны к локальному интерфейсу. Этот Compose не предназначен для рабочей среды.

Опциональные профили:

docker compose --profile telegram up --build
docker compose --profile adminer up --build

Запуск компонентов на хосте

Запустите PostgreSQL/Valkey или задайте совместимые URL в .env, затем в отдельных терминалах:

make migrate
make backend
make worker
make scheduler
make agent
make frontend

Серверная часть при прямом запуске по умолчанию использует SQLite, но обработчик задач, фоновые задания, ограничение частоты запросов и планировщик требуют Valkey. Для тестов среды выполнения и сервера используйте заглушки или одноразовое окружение; не направляйте среду разработки в рабочее хранилище.

5. Конфигурация

Авторитетная модель — backend/app/core/config.py, стандартные значения — в .env.example.

Переменная Назначение
ENVIRONMENT development, test или рабочее значение; рабочая среда отклоняет стандартные небезопасные секреты.
DATABASE_URL Строка подключения асинхронного SQLAlchemy.
REDIS_URL Valkey/Redis для ограничения запросов, Celery и оперативного состояния.
JWT_SECRET Не менее 32 символов вне локального окружения.
FIELD_ENCRYPTION_KEY Ключ Fernet для сохранённых секретов; обязателен в рабочей среде.
AGENT_URL, AGENT_TOKEN Закрытая конечная точка агента и общий секрет аутентификации.
STORAGE_ROOT Корень проектов, резервных копий, загрузок и состояния сред выполнения.
CONFIG_ROOT, NGINX_CONFIG_ROOT Конфигурация панели и созданных узлов Nginx.
CORS_ORIGINS Разрешённые источники браузера через запятую.
PUBLIC_BASE_URL Публичный URL панели для ссылок и обратных вызовов.
TELEGRAM_* Необязательная конфигурация бота и внутренней аутентификации.

Не меняйте FIELD_ENCRYPTION_KEY без миграции данных: существующие зашифрованные поля станут нечитаемыми. Не записывайте в логи объекты настроек, токены, пароли, закрытые ключи и расшифрованные DSN.

6. Разработка серверной части

Серверная часть асинхронна. Используйте AsyncSession, схемы Pydantic на границе API и стабильные HTTP-ошибки вместо внутренних исключений.

При добавлении конечной точки:

  1. создайте или обновите схему в backend/app/schemas/;
  2. вынесите переиспользуемую логику в backend/app/services/, если маршрут смешивает обработку HTTP с бизнес- или инфраструктурной логикой;
  3. до чтения чувствительных данных вызовите require_global_role(...) или require_project_permission(project_id, permission);
  4. записывайте изменяющие и связанные с безопасностью действия в аудит без открытых секретов;
  5. добавьте тесты успешного выполнения, валидации, отсутствия аутентификации, запрещённой роли, доступа к чужому проекту и значимых ошибок;
  6. не ломайте существующий контракт ответа без явно объявленного несовместимого изменения.

Роли owner и admin имеют глобальный доступ к проектам. Доступ ролей maintainer и viewer задаётся назначением на проект и картой разрешений в backend/app/services/permissions.py. Скрытие действия в интерфейсе не заменяет авторизацию на сервере.

Для всех модулей, функций и классов Python обязательны короткие английские строки документации. Используйте безопасные параметры драйверов, проверенные идентификаторы, фиксированные списки аргументов и ограниченный ввод-вывод. Не создавайте команды оболочки из пользовательских данных.

7. Миграции базы данных

Каждое изменение хранимых данных требует миграции Alembic от текущей вершины:

cd backend
../.venv/bin/alembic heads
../.venv/bin/alembic revision --autogenerate -m "describe change"
../.venv/bin/alembic upgrade head
cd ..

Проверьте DDL, имена, индексы, внешние ключи, стандартные значения, порядок обновления и безопасность отката. Протестируйте обновление с предыдущей схемы. Не изменяйте уже применённую миграцию — добавьте исправляющую. Программа обновления создаёт аварийную резервную копию, но миграция всё равно должна быть транзакционной и совместимой с существующими данными, насколько позволяет СУБД.

8. Обработчик и фоновые задачи

Celery используется для развёртывания, резервного копирования, операций с базами данных и сертификатами, мониторинга и других продолжительных задач. API должен ставить задачу в очередь, а не удерживать HTTP-соединение.

Правила фоновых задач:

  • параметры содержат идентификаторы и несекретные данные, но не учётные данные;
  • обработчик заново читает текущее состояние базы данных при старте;
  • ход выполнения и ошибки ограничены по размеру и безопасны для интерфейса;
  • повторные попытки задаются явно и только для идемпотентных или возобновляемых операций;
  • очистка выполняется в finally;
  • метаданные фиксируются после успеха внешней операции;
  • повторная очистка или удаление по возможности идемпотентны.

В модульных тестах подменяйте границы агента и клиентов, проверяйте успех и частичный отказ. Не требуйте работающий Docker или внешние сервисы.

9. Системный агент

Агент — привилегированная граница безопасности. HTTP-процесс работает как vps-panel-agent и передаёт одну проверенную операцию через стандартный ввод точной вспомогательной программе, принадлежащей суперпользователю и разрешённой в sudoers.

Новая операция требует:

  1. строгой типизированной модели запроса и ограничений;
  2. аутентификации по токену агента;
  3. разрешения пути внутри допустимого корня после обработки символических ссылок;
  4. фиксированной программы и аргументов без shell=True;
  5. ограничения времени и вывода, а также предсказуемых ошибок;
  6. повторной валидации во вспомогательной программе для операций суперпользователя;
  7. тестов безопасности на выход за пределы пути, инъекции, ссылки, некорректные данные и отсутствие авторизации;
  8. минимально необходимых владельцев и системных разрешений.

Если действие нельзя безопасно выразить как фиксированную разрешённую операцию, его не должно быть в API агента.

10. Интерфейс и локализация

Nuxt отвечает за представление и состояние клиента. Авторизация, секреты и системная логика остаются в серверной части. Используйте существующие компоненты, переменные CSS, значки Tabler, composable-функции и адаптивные шаблоны; не добавляйте зависимость ради небольшой тестируемой вспомогательной функции.

frontend/pages/        страницы маршрутов
frontend/components/   переиспользуемые компоненты интерфейса
frontend/composables/  API, локализация, разрешения и общая логика
frontend/stores/       состояние Pinia
frontend/locales/      каталоги EN, UK, RU и PL
frontend/types/        типы интерфейса
frontend/tests/        тесты Vitest

Каждая видимая строка должна использовать функцию локализации и существовать во всех четырёх каталогах. Ключи перевода должны быть смысловыми и стабильными, а даты и числа — форматироваться с учётом языка. Для страниц нужны явные состояния загрузки, ошибки, пустого результата, запрета доступа и успеха. Необратимые действия требуют диалога подтверждения и, где поддерживается, подтверждения на сервере.

cd frontend
npm run lint
npm run typecheck
npm run test
npm run build
cd ..

11. Тесты и проверка качества

Во время разработки запускайте целевые тесты:

.venv/bin/python -m pytest backend/tests/test_projects.py
.venv/bin/python -m pytest agent/tests/test_security.py
cd frontend && npm run test -- projects-utils && cd ..

Перед коммитом выполните полную проверку:

make check

Она включает проверку и форматирование Ruff, mypy, ESLint, проверку типов Nuxt, тесты Python и интерфейса, рабочую сборку, аудит npm, синтаксис сценариев оболочки и конфигурацию Compose. При изменении установщика или образов дополнительно:

docker compose --profile telegram build backend frontend worker agent telegram-bot
sudo ./installer/install.sh --domain panel.example.com --email admin@example.com --dry-run

Новая логика требует тестов, включая граничные случаи. По умолчанию предпочитайте модульные тесты; интеграционные добавляйте там, где заглушки не доказывают поведение на границе базы данных, очереди, агента или файловой системы.

12. Инварианты хранения и развёртывания

/opt/nectarine-panel/              установленное приложение
/etc/nectarine-panel/              конфигурация сервисов и секреты
/etc/nginx/vps-panel/              созданные узлы проектов
/srv/vps-panel/projects/{id}/      релизы, текущая ссылка, общие данные, загрузки и логи
/srv/vps-panel/backups/            копии проектов, баз данных и всей панели
/srv/vps-panel/minecraft/{id}/     данные среды Minecraft

Релизы неизменяемы, а активация атомарно заменяет current. Постоянные данные находятся в shared/, а не в релизе или несмонтированном слое контейнера. Распаковка отклоняет выход за пределы каталога, внешние ссылки, специальные файлы, чрезмерное количество элементов и архивные бомбы. Восстановление проверяет контрольную сумму, тип, совместимость и цель до замены данных.

13. Установка и жизненный цикл рабочей системы

Устанавливайте проверенный релиз с тегом от имени суперпользователя:

sudo ./installer/install.sh \
  --domain panel.example.com \
  --email admin@example.com

Установщик создаёт отдельных пользователей, PostgreSQL/Redis, хранилище, окружение Python, сборку интерфейса, миграции, модули systemd, Nginx, вспомогательную программу агента, первого владельца и TLS. Неуказанный пароль администратора генерируется и показывается один раз.

Параметр Назначение
--domain, --email Имя хоста панели и адрес почты для Let's Encrypt.
--admin-user, --admin-password Первый владелец; пароль минимум 12 символов.
--storage-root Абсолютный корень постоянных данных.
--telegram-token, --telegram-owner-id Необязательная настройка бота.
--public-ip Явно заданный публичный адрес.
--source Установка из доверенного локального дерева исходного кода.
--repository, --ref Репозиторий и закреплённая ревизия Git.
--max-upload-mb Ограничение загрузки от 1 до 4096 МиБ.
--backend-port, --frontend-port, --agent-port, --adminer-port Уникальные локальные порты 1024–65535.
--non-interactive Ошибка вместо запроса недостающих значений.
--skip-ssl HTTP без выпуска сертификата.
--dry-run Валидация без установки.
sudo /opt/nectarine-panel/installer/update.sh --ref vX.Y.Z
sudo /opt/nectarine-panel/installer/uninstall.sh

update.sh поддерживает --source, --repository, --ref, --dry-run, создаёт аварийные резервные копии, применяет миграции и проверяет состояние. uninstall.sh сохраняет постоянные данные без явно подтверждённого --purge; также доступны --yes и --dry-run.

Не передавайте непроверенную изменяемую ветку напрямую в оболочку суперпользователя. Подробнее: установка, выпуск релиза.

14. Диагностика рабочей системы

Начинайте со статуса сервисов и ограниченных свежих логов:

sudo systemctl status \
  vps-panel-backend vps-panel-frontend vps-panel-worker \
  vps-panel-scheduler vps-panel-agent vps-panel-telegram-bot
sudo journalctl -u vps-panel-backend -n 200 --no-pager
sudo journalctl -u vps-panel-worker -n 200 --no-pager
sudo journalctl -u vps-panel-agent -n 200 --no-pager
sudo nginx -t
curl -fsS http://127.0.0.1:8000/api/v1/health

Используйте фактический порт серверной части. Проверьте PostgreSQL, Redis, Docker, место и индексные дескрипторы диска, DNS, порты 80/443 и владельцев файлов в корне хранилища. Ответ 502 от операции проекта обычно означает, что серверная часть не завершила проверенное действие агента; сопоставьте логи серверной части, обработчика и агента по времени и идентификатору задачи.

Не публикуйте полные файлы окружения и логи без удаления чувствительных данных. Удаляйте токены, cookie, пароли, закрытые URL и ключи SSH, строки подключения к базе и пользовательские данные. Перед ручным исправлением создайте резервную копию и определите владельца состояния. Не обходите агент разовыми изменениями от суперпользователя, которые панель не сможет согласовать.

15. Запросы на слияние и релизы

Делайте коммиты сфокусированными, документируйте миграции, безопасность, совместимость резервных копий и влияние на эксплуатацию. Перед запросом на слияние:

  1. проверьте git diff и git status;
  2. выполните make check и нужные сборки контейнеров;
  3. убедитесь, что новый текст интерфейса есть в четырёх языковых каталогах;
  4. убедитесь, что не добавлены .env, базы данных, архивы, токены, закрытые ключи, внутренние имена хостов или созданные файлы сборки;
  5. обновите руководство пользователя при изменении рабочего процесса, а руководство разработчика или справочник — при изменении внутренней логики.

Для релиза обновите журнал изменений и версию, проверьте миграции, создайте подписанный тег vX.Y.Z, опубликуйте контрольные суммы и инструкции по обновлению и откату, проверьте установку на чистую Ubuntu 24.04 и восстановление на временном сервере. Следуйте CONTRIBUTING.md, SECURITY.md и releasing.md.