ayurishchevandClaude Sonnet 5 4c1841b61b ros_control: централизованное управление парком MikroTik RouterOS
Control Server (FastAPI) с WEB UI (Jinja2 + HTMX) и JSON API для группового
администрирования устройств RouterOS 7 через REST.

- Устройства: список, статус (модель, канал, версии ROS/FW, uptime, доступные
  обновления), примечания, пароли шифруются (Fernet); фоновый опрос каждые 30 с
  и быстрое обнаружение недоступности (таймаут соединения 4 с).
- Группы устройств и фильтры (устройства, резервные копии).
- Резервные копии: .backup и .rsc (show-sensitive) создаются через REST,
  скачиваются сервером и загружаются в S3 (Yandex Object Storage).
- Обновление ROS/FW и выбор канала, групповые операции задачами.
- Интерфейс по утверждённому макету: светлая/тёмная темы, окна, шрифты IBM Plex
  локально. Docker Compose, SQLite в томе, минимальный набор тестов.
- Планы и итоги каждого изменения — в docs/changes/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:13:29 +03:00

ros_control

Централизованное управление парком MikroTik RouterOS: WEB UI и JSON API. Дизайн и требования — ros_control.svg; макет интерфейса — утверждён и перенесён в приложение (см. docs/changes/006-ui-redesign).

Admin Dashboard ⇄ Control Server ⇄ RouterOS REST (на каждом устройстве)
                       ⇅   ⇅
              Metadata DB   S3 (Yandex Object Storage)

Возможности

Устройства

  • Список устройств: добавление, изменение, удаление; пароли хранятся зашифрованно (Fernet). Имя устройства в таблице кликабельно — открывает окно изменения.
  • К устройству можно добавить примечание (до 500 символов): видно подсказкой при наведении на имя.
  • Статус: online/offline, модель, канал обновлений, версии ROS и FW, uptime, время запроса бэкапа. Колонки Upgrade ROS и Upgrade FW показывают версию, до которой можно обновиться (устройство проверяет обновления на серверах MikroTik; без интернета на устройстве — «—»).
  • Мониторинг доступности: сервер опрашивает устройства каждые 30 с (POLL_INTERVAL), недоступность определяется за ~4 с на устройство (ROS_CONNECT_TIMEOUT); страница обновляет статусы сама, без перезагрузки.

Группы и фильтры

  • Устройство относится к одной группе: вкладки групп со счётчиками, страница «Группы» (создание, переименование, удаление), перенос отмеченных устройств в группу. При добавлении устройства группу можно создать «на месте» (пункт «+ Новая группа…»).
  • Фильтры устройств: поиск (имя, адрес, модель), статус, наличие обновлений, канал. Фильтры бэкапов: группа, устройство, тип файла, период, имя файла. Фильтры попадают в URL.

Операции

  • Действия по устройству — в меню «⋯» строки; действия над выбранными устройствами (бэкап, статус, обновление ROS/FW, канал, перенос в группу) появляются в полосе инструментов при выборе строк; через API их можно запускать и над всей группой.
  • Бэкап: .backup (без шифрования) и .rsc (с show-sensitive, т.е. с паролями и ключами — из него можно восстановить все сущности, использующие пароль). Сервер создаёт файлы через REST, скачивает во временную папку, загружает в S3 и удаляет файлы с устройства.
  • Список бэкапов в бакете, скачивание (временная ссылка), удаление.
  • Канал обновлений; обновление ROS (устройство перезагружается после скачивания); обновление FW (перезагрузка сразу после появления в журнале устройства записи «Firmware upgraded successfully…»).
  • Долгие и групповые операции выполняются задачами (карточка «Задачи», состояние — в UI и через API).

Интерфейс

Экран строится сверху вниз: приложение (навигация) → страница (заголовок, счётчики, главное действие) → вкладки групп → полоса инструментов таблицы → данные; «Задачи» — отдельная карточка. Пока ничего не выбрано, полоса показывает фильтры; при выборе строк — действия над выбранными. Добавление и изменение устройств, создание и переименование групп — в окнах поверх страницы (запасные страницы /devices/new, /devices/{id}/edit работают без JavaScript). Выпадающие меню не обрезаются таблицей и раскрываются вверх, если снизу нет места. Светлая и тёмная темы переключаются по настройке системы. Шрифты IBM Plex лежат в app/ui/static/fonts (лицензия OFL), внешние ресурсы не загружаются.

Требования к устройствам

  • RouterOS 7.1+, включённый сервис www-ssl (REST API, порт 443; не api-ssl 8729 и не api 8728). Если www-ssl недоступен, для доверенной сети можно указать сервис www (порт 80) и снять флаг «HTTPS» у устройства — логин и пароль пойдут открытым текстом.
  • Пользователь с политиками read, write, policy, test, ftp, reboot, sensitive (проще всего — группа full). Встроенная группа write с запретом ftp/policy не подходит: бэкап падает с not enough permissions. После смены прав пересоздайте подключение к устройству.
  • Доступ устройств к S3 не нужен: файлы забирает и загружает Control Server (ему нужен доступ к storage.yandexcloud.net:443).

Безопасность

  • Замените значения по умолчанию API_TOKEN и SESSION_SECRET на случайные (openssl rand -hex 24); порт 8000 не стоит открывать в недоверенную сеть.
  • Пароли устройств шифруются ключом SECRET_KEY (Fernet); потеря ключа = потеря доступа к сохранённым паролям.
  • Секреты в бэкапах: .rsc создаётся с show-sensitive, а .backup — без шифрования, поэтому файлы содержат пароли и ключи открытым текстом. Ограничьте доступ к бакету и ссылкам скачивания.

Запуск

cp .env.example .env    # заполнить SECRET_KEY, ADMIN_PASSWORD, API_TOKEN, S3_*
docker compose up -d --build     # UI: http://localhost:8000, OpenAPI: /docs

БД (SQLite) хранится в Docker-томе ros_data (docker volume inspect ros_control_ros_data), переживает пересборку контейнера; схема обновляется автоматически при старте. Остановка: docker compose down (том сохраняется; down -v удалит БД).

Ключ Fernet: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())".

Настройки (.env)

Переменная По умолчанию Назначение
SECRET_KEY — ключ Fernet для паролей устройств (обязателен)
SESSION_SECRET change-me подпись cookie-сессии UI
ADMIN_USER / ADMIN_PASSWORD admin / change-me вход в UI
API_TOKEN change-me Bearer-токен API
DATABASE_URL sqlite:///./data/ros_control.db база метаданных (в compose — том)
S3_ENDPOINT, S3_REGION, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, S3_PREFIX Yandex Object Storage, backups бакет для резервных копий
MAX_CONCURRENCY 10 одновременные обращения к устройствам
ROS_CONNECT_TIMEOUT 4 секунд на установление соединения (скорость обнаружения недоступности)
ROS_TIMEOUT 30 секунд на ответ устройства (долгие операции)
POLL_INTERVAL 30 период фонового опроса, с; 0 — выключить
UPDATE_CHECK_INTERVAL 1800 как часто опрос проверяет обновления ROS, с

Разработка

python3 -m venv venv && ./venv/bin/pip install -r requirements.txt
set -a; . ./.env; set +a
./venv/bin/uvicorn app.main:app --reload
./venv/bin/python -m pytest          # 9 тестов, фоновый опрос в тестах выключен

API v1

Заголовок Authorization: Bearer <API_TOKEN>. Интерактивная документация — /docs. Пример:

curl -s -H "Authorization: Bearer $API_TOKEN" http://localhost:8000/api/v1/devices | python3 -m json.tool

Устройство: name, host, port, username, password (только при записи), verify_tls, use_tls (false — HTTP), group_id (null — без группы), note.

Метод Путь Назначение
GET/POST /api/v1/devices список (фильтры group, q, status, updates, channel) / добавить
GET/PATCH/DELETE /api/v1/devices/{id} получить / изменить / удалить
POST /api/v1/devices/refresh, /devices/{id}/refresh обновить статус
POST /api/v1/devices/{id}/backups бэкап (задача)
PUT /api/v1/devices/{id}/update/channel {"channel": "stable|long-term|testing|development"}
POST /api/v1/devices/{id}/update/install обновление ROS (задача)
POST /api/v1/devices/{id}/firmware/upgrade обновление FW (задача)
GET/POST /api/v1/groups группы (с числом устройств) / создать
PATCH/DELETE /api/v1/groups/{id} переименовать / удалить (устройства остаются без группы)
POST /api/v1/batch/{backup|ros_update|fw_update} {"device_ids": [...]} и/или {"group_id": N} — групповая операция
PUT /api/v1/batch/channel {"device_ids": [...] или "group_id": N, "channel": "..."}
GET/DELETE /api/v1/backups, /backups/download?key= бэкапы в бакете (фильтры device_id, group, kind, date_from, date_to, q)
GET /api/v1/jobs, /jobs/{id} состояние задач

Внешние справочники: RouterOS REST API, Yandex Object Storage S3 API.

Структура

  • app/ros — клиент RouterOS REST и операции (статус, бэкап, скачивание файлов, обновления)
  • app/s3.py — бакет; app/security.py — шифрование и авторизация; app/models.py, app/db.py — БД и миграции
  • app/services — устройства и фильтры, группы, бэкапы, операции, задачи, фоновый опрос (poller.py)
  • app/api — JSON API; app/ui — WEB UI (Jinja2 + HTMX, static/ со стилями, скриптом и шрифтами)
  • tests — минимальный набор; docs/changes — планы и итоги каждого изменения

История изменений

Планы и итоги — в docs/changes/:

  • 001-initial-implementation — первая версия.
  • 002-http-support-and-fixes — HTTP-подключение, исправления по итогам теста на реальном устройстве.
  • 003-download-via-rest-upload-from-server — бэкап: скачивание файлов через REST, загрузка в S3 сервером.
  • 004-upgrade-columns-and-actions-menu — колонки Upgrade ROS/FW, меню действий «⋯».
  • 005-groups-and-filters — группы устройств, фильтры устройств и бэкапов.
  • 006-ui-redesign — новый интерфейс по утверждённому макету; исправлены перезагрузка после обновления FW и привязка группы при добавлении устройства.
  • 007-fast-offline-detection — фоновый опрос устройств (30 с), быстрый таймаут соединения, автообновление страницы.
  • 008-device-note — примечание к устройству.
  • 009-dialog-label-alignment — выравнивание полей в окне устройства.
  • 010-export-show-sensitive — .rsc создаётся с show-sensitive (секреты в файле).
  • 011-dropdown-clipping — выпадающие меню не обрезаются в узком окне.
  • 012-clickable-device-name — клик по имени устройства открывает окно изменения.
S
Description
MikroTIk Router OS Firmware Management and Backup Tool
Readme
1.4 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 73.9%
HTML 15.2%
CSS 6.4%
JavaScript 4.4%
Dockerfile 0.1%