Перейти к основному содержимому

Панель управления — 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абсолютный путьРабочая директория — обязательно абсолютный путь
watchfalseНе перезапускать при изменении файлов (dev-сервер сам следит)
autorestarttrueПерезапускать если процесс упал
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-dev3000Docusaurus dev-сервер, сайт и CMS
cms-decap-server8083Decap CMS прокси для git-операций
cms-tools-api8084API для запуска скриптов из браузера

Интерфейс панели

Шапка

Тёмная полоса вверху. Содержит название и ссылку ← 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.mdbuild_project_index.sh <slug>Регенерирует docs/<slug>/index.md на основе _project_.json и _category_.json разделов. Нужно запускать после добавления новых документов или разделов.
Синхр. assetssync_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). Запускать после добавления нового проекта или изменения его метаданных.
Синхр. все assetssync_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 · rsyncdeploy_site.sh --mode=sharedПолный деплой на shared хостинг: sync assets → build index → npm run build → rsync
VPS · dockerdeploy_site.sh --mode=vps --method=dockerПолный деплой на VPS через Docker + Traefik: сборка → rsync → docker compose up -d
VPS · pm2deploy_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> для ревью.

Как использовать

  1. Перетащить файл в область или кликнуть для выбора
  2. Опционально — ввести имя оператора (кто выполняет импорт, для лога)
  3. Нажать Импортировать
  4. В консоли справа появится вывод скрипта с именем созданной ветки

Поддерживаемые форматы:

  • .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 наружу — нет аутентификации, любой сможет запускать скрипты.