Панель управления — Tools API
Версия: 1.2
Дата: 21.04.2026
Статус: Утверждён
Панель управления документацией — браузерный интерфейс для запуска всех скриптов системы без терминала. Состоит из двух частей: API-сервер (tools/cms-tools-api.js) и страница интерфейса (static/admin/tools.html).
Открывается по адресу: http://localhost:3000/admin/tools.html
Из CMS-редактора — кнопка Инструменты в правом верхнем углу шапки.
Архитектура
Браузер (tools.html)
│
├── GET /projects — список проектов из docs/
├── GET /run/<script> — запуск скрипта, SSE-поток вывода
└── POST /import — upload файла + запуск import_bundle.sh
CMS Tools API (порт 8084)
└── запускает bash-скрипты из tools/ в корне репозитория
SSE (Server-Sent Events) — вывод скрипта стримится в браузер построчно в реальном времени. Соединение закрывается когда скрипт завершается.
Установка и запуск
Зависимости
npm install --save-dev express multer
Устанавливается один раз. Пакеты express и multer нужны только API-серверу.
Ручной запуск
node tools/cms-tools-api.js
# или с кастомным портом:
PORT=8084 node tools/cms-tools-api.js
Автозапуск через pm2
API-сервер уже добавлен в ecosystem.config.js — стартует автоматически вместе с остальными процессами:
# Первый запуск (все три процесса):
pm2 start ecosystem.config.js
# Только API:
pm2 start ecosystem.config.js --only cms-tools-api
# Перезапуск после обновления кода:
pm2 restart cms-tools-api
Конфигурация в ecosystem.config.js:
{
name: 'cms-tools-api',
script: 'tools/cms-tools-api.js',
cwd: '/home/alex/sites/cms-docs',
env: { PORT: '8084' },
}
Автостарт при перезагрузке системы
# Выполнить один раз — генерирует systemd unit:
pm2 startup
# Сохранить список процессов:
pm2 save
После этого все три процесса (cms-docs-dev, cms-decap-server, cms-tools-api) запустятся автоматически при старте системы.
Настройка
Порт
По умолчанию API слушает порт 8084. Изменить через переменную окружения PORT:
PORT=9000 node tools/cms-tools-api.js
Или в ecosystem.config.js:
{
name: 'cms-tools-api',
script: 'tools/cms-tools-api.js',
cwd: '/home/alex/sites/cms-docs',
env: { PORT: '8084' },
}
Если порт 8084 занят — проверить:
ss -tlnp | grep 8084
Занятый порт — поменять в ecosystem.config.js и обновить константу API в static/admin/tools.html:
const API = 'http://localhost:8084'; // строка 2 блока <script>
Путь к репозиторию
API определяет корень репозитория автоматически через path.resolve(__dirname, '..') — то есть на директорию выше tools/. Если скрипт запускается из другого места — путь всё равно будет правильным, так как привязан к расположению файла, а не к рабочей директории.
ecosystem.config.js — полный пример
Файл в корне репозитория управляет всеми тремя процессами:
module.exports = {
apps: [
// Docusaurus dev-сервер — сайт + CMS
{
name: 'cms-docs-dev',
script: 'npm',
args: 'start',
cwd: '/home/alex/sites/cms-docs',
watch: false,
autorestart: true,
env: { NODE_ENV: 'development' },
},
// Decap CMS прокси для git-операций
{
name: 'cms-decap-server',
script: 'npx',
args: 'decap-server',
cwd: '/home/alex/sites/cms-docs',
watch: false,
autorestart: true,
env: { PORT: '8083' },
},
// Tools API — панель управления
{
name: 'cms-tools-api',
script: 'tools/cms-tools-api.js',
cwd: '/home/alex/sites/cms-docs',
watch: false,
autorestart: true,
env: { PORT: '8084' },
},
],
};
Параметры:
| Параметр | Значение | Назначение |
|---|---|---|
name | строка | Имя процесса в pm2 — используется в командах pm2 restart/stop/logs |
script | путь или команда | Что запускать |
args | аргументы | Передаются в script |
cwd | абсолютный путь | Рабочая директория — обязательно абсолютный путь |
watch | false | Не перезапускать при изменении файлов (dev-сервер сам следит) |
autorestart | true | Перезапускать если процесс упал |
env.PORT | число | Порт для процесса |
Изменить cwd если репозиторий лежит в другой папке — иначе процессы не найдут файлы.
Где хранит настройки pm2
pm2 хранит свои данные в ~/.pm2/:
~/.pm2/
dump.pm2 — сохранённый список процессов (pm2 save)
logs/ — логи всех процессов
cms-tools-api-out.log
cms-tools-api-error.log
pids/ — PID-файлы запущенных процессов
Полезные команды:
pm2 logs cms-tools-api # хвост логов в реальном времени
pm2 logs cms-tools-api --lines 100 # последние 100 строк
pm2 flush # очистить все логи
pm2 show cms-tools-api # подробная информация о процессе
pm2 monit # интерактивный мониторинг CPU/RAM
Переменные окружения
API наследует весь process.env от pm2/shell и передаёт его в дочерние скрипты. Если скрипты деплоя используют переменные окружения (SSH-ключи, токены) — добавить их в секцию env в ecosystem.config.js:
env: {
PORT: '8084',
SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK, // пробросить ssh-agent
}
Или задать глобально через ~/.bashrc / ~/.profile — pm2 подхватит при запуске через systemd только если --hp указывает на правильный home.
tools.html — где менять настройки интерфейса
Файл static/admin/tools.html. Все настраиваемые параметры в начале блока <script>:
const API = 'http://localhost:8084'; // адрес API-сервера
Если изменили порт API — поменять здесь. Остальные параметры (список скриптов, логика) живут в tools/cms-tools-api.js.
Проверка работы
# Статус процессов:
pm2 list
# Логи API:
pm2 logs cms-tools-api
# Быстрая проверка через curl:
curl http://localhost:8084/projects
Ответ должен вернуть JSON со списком проектов.
Три запущенных процесса
| Имя pm2 | Порт | Назначение |
|---|---|---|
cms-docs-dev | 3000 | Docusaurus dev-сервер, сайт и CMS |
cms-decap-server | 8083 | Decap CMS прокси для git-операций |
cms-tools-api | 8084 | API для запуска скриптов из браузера |
Интерфейс панели
Шапка
Тёмная полоса вверху. Содержит название и ссылку ← CMS — возврат в редактор.
Строка выбора проекта
Проект: [ выпадающий список ] [ badge с текущим slug ]
Список проектов загружается автоматически при открытии страницы — читаются все папки docs/ у которых есть _project_.json. При открытии панели из CMS-редактора (через кнопку "Инструменты") slug определяется автоматически из URL редактора.
Выбор проекта влияет на все операции блока Текущий проект.
Блок: Текущий проект
Операции над выбранным проектом. Перед нажатием — выбрать проект в строке выше.
| Кнопка | Скрипт | Что делает |
|---|---|---|
| Экспорт архива | export_project.sh <slug> | Создаёт exports/<slug>-YYYY-MM-DD.tar.gz без паролей и .gitkeep. Архив можно передать другому человеку. |
| Бандл для ревью | bundle_for_review.sh <slug> | Склеивает все MD-файлы проекта в один текстовый файл и упаковывает в .tar.gz. Для передачи документации проекта в AI с большим контекстным окном. |
| Пересобрать index.md | build_project_index.sh <slug> | Регенерирует docs/<slug>/index.md на основе _project_.json и _category_.json разделов. Нужно запускать после добавления новых документов или разделов. |
| Синхр. assets | sync_assets.sh <slug> | Копирует файлы из docs/<slug>/assets/ в static/<slug>/. Нужно после добавления новых медиафайлов чтобы они стали доступны на сайте. |
Добавить пользователя в проект
[ логин ] [ пароль ] [ Добавить ]
Вызывает add_user.sh <slug> <username> <password>. Генерирует два хэша и записывает в access[] файла docs/<slug>/_project_.json:
cms_hash— SHA-256 отusername:passwordдля JS-аутентификации в браузереpassword_hash— SHA-512 htpasswd-совместимый хэш (генерируется для совместимости, текущей аутентификацией не используется)
Если пользователь уже существует — оба хэша обновляются. После добавления система автоматически вызывает build_auth.sh для обновления JS-модуля.
Блок: Глобальные операции
Операции на всю систему, не зависят от выбранного проекта.
| Кнопка | Скрипт | Что делает |
|---|---|---|
| Пересобрать главную | build_index.sh | Регенерирует docs/index.md — главную страницу со списком всех публичных проектов (public: true). Запускать после добавления нового проекта или изменения его метаданных. |
| Синхр. все assets | sync_assets.sh | Синхронизирует assets/ всех проектов в static/ — без аргумента скрипт обрабатывает все проекты сразу. |
| Экспорт публичных | export_public.sh | Экспортирует все проекты с public: true — вызывает export_project.sh для каждого. Архивы сохраняются в exports/. |
| Пересобрать доступы | build_auth.sh | Регенерирует src/auth/project-access.js из всех _project_.json. Запускать после добавления/изменения пользователей если не хочется делать полную сборку. Автоматически вызывается как prebuild при npm run build. |
| Бандл всех для ревью | bundle_for_review.sh --all | Склеивает все MD-файлы каждого проекта в один текстовый файл и упаковывает в .tar.gz. Нужна для передачи всей документации в AI с большим контекстным окном. Архивы сохраняются в exports/. |
JS-аутентификация
Система защиты проектов работает на стороне браузера — поверх статического сайта, без серверной логики.
Схема:
_project_.json (access[].cms_hash)
↓
tools/build_auth.sh
↓
src/auth/project-access.js ← ES-модуль, встраивается в сборку
↓
src/clientModules/authGuard.js ← хук onRouteUpdate, проверяет каждый переход
src/pages/login.tsx ← страница /login, SHA-256 верификация
Жизненный цикл токена:
- При успешном входе:
localStorage['docs-auth:<slug>'] = cms_hash - При каждом переходе:
authGuard.jsсравнивает токен сproject-access.js - Разные проекты — независимые токены
- Токен живёт до смены браузера или явной очистки
prebuild в package.json гарантирует что build_auth.sh запускается автоматически перед каждым npm run build. Кнопка Деплой в панели это учитывает.
Кнопка "Пересобрать доступы" (build_auth) — обновляет только JS-модуль без полной пересборки сайта. Удобна после добавления пользователя через "Добавить пользователя", когда нужно проверить результат локально.
Блок: Деплой на сервер
Операции публикации на удалённый сервер. Требуют настроенного cms-config.json с секциями shared или vps.
| Кнопка | Скрипт | Что делает |
|---|---|---|
| Shared · rsync | deploy_site.sh --mode=shared | Полный деплой на shared хостинг: sync assets → build index → npm run build → rsync |
| VPS · docker | deploy_site.sh --mode=vps --method=docker | Полный деплой на VPS через Docker + Traefik: сборка → rsync → docker compose up -d |
| VPS · pm2 | deploy_site.sh --mode=vps --method=pm2 | Полный деплой на VPS через pm2: сборка → rsync → pm2 restart |
Метод VPS по умолчанию берётся из cms-config.json → vps.deploy_method. Кнопки VPS · docker и VPS · pm2 явно переопределяют метод флагом --method.
Порядок деплоя: одна кнопка делает всё — включая актуализацию JS-доступов через build_auth.sh.
Подробнее о настройке VPS: Деплой на VPS — Docker + Traefik
API-эндпоинты
deploy_access_*иdeploy_push_*сохранены для совместимости, но являются stub — ничего не генерируют и не заливают. Кнопки в интерфейсе панели удалены. Аутентификация полностью встроена в JS-бандл.
Блок: Импорт документов
Принимает архив с документами от другого человека или системы и создаёт изолированную ветку import/<id> для ревью.
Как использовать
- Перетащить файл в область или кликнуть для выбора
- Опционально — ввести имя оператора (кто выполняет импорт, для лога)
- Нажать Импортировать
- В консоли справа появится вывод скрипта с именем созданной ветки
Поддерживаемые форматы:
.bundle— git bundle (создаётся черезgit bundle create).tar.gz— архив с папкой проекта (с.gitили без).zip— то же самое в формате zip
После импорта — в консоли будет:
Done. Branch 'import/bundle-2026-04-21-v01' created.
Затем в терминале:
git diff main..import/bundle-2026-04-21-v01 --stat # посмотреть изменения
git merge import/bundle-2026-04-21-v01 # принять
Панель вывода (консоль)
Правая тёмная колонка — отображает вывод запущенного скрипта в реальном времени.
Цвета:
- Синий — команда которая запущена (
$ tools/export_project.sh ...) - Белый — stdout скрипта
- Красный — stderr скрипта
- Бирюзовый — успешное завершение (
✓ Завершено) - Красный жирный — ошибка (
✗ Ошибка)
Статус в правом верхнем углу консоли:
| Статус | Значение |
|---|---|
готов | Ожидает операции |
выполняется... | Скрипт запущен |
готов (синий) | Последняя операция завершилась успешно |
ошибка (красный) | Последняя операция завершилась с ошибкой |
Футер консоли:
- Слева —
API: порт 8084 ✓(зелёный) илиAPI: недоступен(красный) — проверяется при загрузке страницы - Справа — кнопка Очистить — очищает вывод
API эндпоинты
Для прямого использования или интеграции.
GET /projects
Возвращает список всех проектов.
curl http://localhost:8084/projects
[
{ "slug": "vitiana-api-platform", "label": "Vitiana API Platform", "public": false },
{ "slug": "cms-system", "label": "Система документации", "public": false }
]
GET /run/:name?slug=<slug>
Запускает скрипт. Возвращает SSE-поток.
curl http://localhost:8084/run/export_project?slug=vitiana-api-platform
Доступные значения :name:
| name | Нужен slug | Скрипт |
|---|---|---|
export_project | да | export_project.sh |
build_project_index | да | build_project_index.sh |
sync_assets | нет | sync_assets.sh |
build_index | нет | build_index.sh |
build_auth | нет | build_auth.sh — регенерирует src/auth/project-access.js |
export_public | нет | export_public.sh |
serve_preview | нет | serve_preview.sh |
deploy_site_shared | нет | deploy_site.sh --mode=shared |
deploy_site_vps | нет | deploy_site.sh --mode=vps |
deploy_access_shared | нет | deploy_access.sh --mode=shared (stub — ничего не делает) |
deploy_access_vps | нет | deploy_access.sh --mode=vps (stub — ничего не делает) |
deploy_push_shared | нет | deploy_push.sh --mode=shared (stub — ничего не делает) |
deploy_push_vps | нет | deploy_push.sh --mode=vps (stub — ничего не делает) |
add_user | да | add_user.sh (+ username, password) |
bundle_for_review | да | bundle_for_review.sh <slug> |
bundle_all_for_review | нет | bundle_for_review.sh --all |
Формат SSE-событий:
data: {"type":"start","cmd":"tools/export_project.sh vitiana-api-platform"}
data: {"type":"stdout","text":"Exporting vitiana-api-platform...\n"}
data: {"type":"stderr","text":""}
data: {"type":"done","code":0}
POST /import
Загружает файл и запускает импорт. Multipart form-data.
curl -X POST http://localhost:8084/import \
-F "file=@bundle.tar.gz" \
-F "operator=alex"
Возвращает SSE-поток аналогично /run.
Безопасность
API работает только на localhost и не слушает внешние интерфейсы. Предназначен исключительно для локального использования.
Если сервер задеплоен на VPS и нужен доступ к панели удалённо — пробросить порт через SSH:
ssh -L 8084:localhost:8084 user@your-server.com
После этого панель будет доступна локально на http://localhost:3000/admin/tools.html как обычно, но скрипты будут выполняться на сервере.
Не открывать порт 8084 наружу — нет аутентификации, любой сможет запускать скрипты.