Gnexus Hardware Monitor — сбор мониторинга всех серверов в одном месте.
┌───────────────┐ POST /api/v1/ingest ┌────────────────────┐ │ hard-monitor │ ─────────────────────► │ hard-panel │ │ (агент, │ метрики + ключ │ FastAPI + SQLite │ │ stateless) │ │ + Vue UI │ └───────────────┘ └────────────────────┘
| Часть | Технологии |
|---|---|
| panel backend | Python 3.12, FastAPI, aiosqlite (SQLite, WAL) |
| panel frontend | Vue 3, gnexus-ui-kit, chart.js |
| monitor | Python 3.8+ (psutil, requests), systemd |
| Деплой | Docker / docker-compose |
Нужен сервер с docker и docker compose. SQLite живёт в volume — отдельной БД не надо.
git clone https://git.gnexus.space/git/root/hard-panel.git cd hard-panel
1. Конфиг — корень репо, рядом с docker-compose.yml:
cp panel/backend/.env.example .env
Отредактируй .env:
# порт, на котором панель слушает снаружи (по умолчанию 8000) GHARD_PANEL_PORT=8000
GHARD_ADMIN_TOKEN — опционален: веб-интерфейс работает без логина. Если задать токен, API панели (создание серверов, метрики) закроется Bearer-токеном — удобно, когда панель торчит в интернет, а UI тебе не нужен. Единственная настоящая авторизация в системе — ключи агентов (ghm_...).
2. Запуск:
docker compose up -d --build
Проверка: curl http://localhost:8000/api/v1/health → {"status":"ok"}. OpenAPI-документация: http://localhost:8000/docs.
3. Reverse proxy (рекомендуется) — агенты будут слать метрики из интернета, поэтому панель стоит закрыть TLS-ом. Пример Caddy:
panel.example.com {
reverse_proxy 127.0.0.1:8000
}
Caddy сам выпустит сертификат. Для nginx: proxy_pass http://127.0.0.1:8000; и обычный certbot. Заголовок X-Forwarded-For панель учитывает — в карточке сервера будет виден реальный IP агента.
Проще всего — кнопка «Добавить сервер» в веб-интерфейсе. Через API то же самое:
curl -X POST https://panel.example.com/api/v1/servers \
-H "Content-Type: application/json" \
-d '{"name": "web-01"}'
Ответ — plaintext-ключ, показывается один раз, сохрани сразу:
{"id": 1, "name": "web-01", "key": "ghm_KyfA9jheG9OSZxFlfFmdx8yFpO3tZAcO"}
Дальше на целевом сервере (python3 + pip):
curl -fsSL https://git.gnexus.space/root/hard-panel/raw/branch/master/monitor/install.sh | \
sudo bash -s -- https://panel.example.com ghm_KyfA9jheG9OSZ... 30
Скрипт поставит всё в /opt/hard-monitor (venv + psutil + requests), запишет .env с правами 600, установит systemd-юнит hard-monitor и запустит. Повторный запуск — обновление агента.
Логи и управление:
journalctl -u hard-monitor -f # смотреть логи systemctl restart hard-monitor # рестарт
Проверка на панели — сервер должен получить status: "online":
curl -s https://panel.example.com/api/v1/servers
monitor/deploy.sh делает весь цикл сам: создаёт сервер на панели → заходит по SSH → ставит агента → ждёт первый пакет. Одна команда на любое число хостов:
cd monitor ./deploy.sh --panel https://panel.example.com user@web-01 user@db-01 user@cache-01
Опции:
| Опция | Что делает |
|---|---|
--panel URL |
адрес панели (обязательно) |
--token TOKEN |
GHARD_ADMIN_TOKEN — нужен, только если токен на панели задан |
--interval N |
интервал агента в секундах (по умолчанию 30) |
--recreate |
удалить существующую запись сервера на панели и создать заново (новый ключ); без него ключ переиспользуется из /opt/hard-monitor/.env на хосте |
--git-install |
ставить curl-ом из репозитория; по умолчанию файлы агента заливаются scp с локальной машины |
Требования к хостам: SSH-доступ по ключу, python3, sudo без пароля. Повторный запуск на уже развёрнутом хосте — обновление агента (запись на панели и ключ сохраняются).
Скрипт специально сделан неинтерактивным и идемпотентным, чтобы его мог запустить ИИ-агент с SSH-доступом к машинам. Промт для агента:
Разверни hard-monitor на моих серверах. Панель: https://panel.example.com 1. Склонируй https://git.gnexus.space/git/root/hard-panel.git (нужна папка monitor/) 2. Запусти: cd monitor && ./deploy.sh --panel https://panel.example.com user@host1 user@host2 ... 3. Если какой-то хост упал с ошибкой — разберись (ssh, journalctl -u hard-monitor), почини и перезапусти deploy.sh только для этого хоста 4. Проверь, что все серверы online: curl -s https://panel.example.com/api/v1/servers (у каждого status: "online")
Агенту не нужен доступ к UI панели: серверы создаются через API, ключи никогда не показываются человеку и не сохраняются — install.sh сразу кладёт их в /opt/hard-monitor/.env (права 600).
Panel — на сервере с панелью:
cd hard-panel git pull docker compose up -d --build
Агент — на каждом сервере (нужны свежие hard_monitor.py / hard-monitor.service в текущем каталоге — склонируй репо):
git clone https://git.gnexus.space/git/root/hard-panel.git && cd hard-panel/monitor sudo ./install.sh # с теми же PANEL_URL/SERVER_KEY — перезапишет файлы и рестартанёт
Или вручную: скопируй hard_monitor.py в /opt/hard-monitor/ и systemctl restart hard-monitor. Конфиг .env не трогается.
Вся панель — один файл SQLite в volume panel-data. Полный бэкап:
docker compose exec panel python -c \
"import sqlite3; sqlite3.connect('/data/hard-panel.db').backup(sqlite3.connect('/data/backup.db'))"
docker compose cp panel:/data/backup.db ./hard-panel-backup.db
(или просто остановить и скопировать volume). Ключи серверов в БД — хэши, восстановить plaintext из бэкапа нельзя: потерянный ключ — пересоздай сервер.
| Переменная | По умолчанию | Описание |
|---|---|---|
GHARD_ADMIN_TOKEN |
(пусто) | опциональный Bearer-токен API; веб-интерфейс работает без логина |
GHARD_DATABASE_PATH |
/data/hard-panel.db |
путь к SQLite |
GHARD_PANEL_PORT |
8000 |
host-порт (docker-compose) |
GHARD_OFFLINE_MULTIPLIER |
3 |
offline = нет пакетов дольше N × interval |
GHARD_SHARE_INTERVAL |
60 |
период опроса сетевых хранилищ, сек |
POST /api/v1/servers — создать сервер, получить ключ агента (один раз)POST /api/v1/ingest — пакет метрик агента, заголовок X-Server-KeyGET /api/v1/servers — сводка для дашбордаGET /api/v1/servers/{id} — карточка + последняя точкаGET /api/v1/servers/{id}/metrics?since=…&until=… — история для графиковPATCH /api/v1/servers/{id} — имя / заметкаDELETE /api/v1/servers/{id} — удалить сервер (с каскадом метрик)GET/POST/PATCH/DELETE /api/v1/shares[/{id}] — сетевые хранилища (CRUD)GET /api/v1/shares/{id}/samples?since=… — история заполнения хранилищаПанель умеет следить за контентом на сетевых накопителях (NAS): хранилище примонтируется к машине, где работает panel, а панель сама опрашивает его через os.statvfs — отдельно раздел Storage в веб-интерфейсе, точки заполнения каждые GHARD_SHARE_INTERVAL секунд, история за 7 дней.
Примонтировать SMB/CIFS-шару (Debian/Ubuntu):
sudo apt install cifs-utils # /etc/nas-creds: username=..., password=..., domain=... sudo mount -t cifs //192.168.1.50/media /mnt/media-nas -o credentials=/etc/nas-creds,uid=1000,iocharset=utf8
NFS:
sudo apt install nfs-common sudo mount -t nfs nas.local:/export/media /mnt/media-nas
Постоянно — через /etc/fstab:
//192.168.1.50/media /mnt/media-nas cifs credentials=/etc/nas-creds,uid=1000,iocharset=utf8,_netdev,nofail 0 0 nas.local:/export/media /mnt/media-nas nfs defaults,_netdev,nofail 0 0
Затем в панели: Storage → Add share, имя и путь монтирования (/mnt/media-nas). Статусы: online (замер удался), offline (примонтированный путь недоступен — отвалилась сеть/NAS), waiting (данных ещё нет или пробер молчит). Отвал NAS показывается как offline, данные при этом панель не трогает. _netdev,nofail в fstab нужен, чтобы загрузка панели не зависла, если NAS в момент старта выключен.
Панель сама является MCP-сервером (streamable HTTP, по умолчанию /mcp) — любой ИИ-агент подключается по URL панели и читает состояние серверов.
Инструменты:
| Tool | Что отдаёт |
|---|---|
panel_overview |
все серверы одной сводкой: статус, CPU/RAM/диск, сеть, последний пакет; плюс сетевые хранилища с заполнением |
server_details |
полное состояние сервера: метрики, диски, процессы, docker, заметка |
server_history |
история метрик за N часов, прореженная до N точек |
Подключение (Claude Code):
claude mcp add --transport http ghard https://panel.example.com/mcp
Для любого другого MCP-клиента — тот же URL, транспорт streamable HTTP. После подключения агент может отвечать на вопросы «как мои серверы?», «что тормозит на web-01?», «растёт ли диск на db-01 за сутки?» без доступа к веб-интерфейсу.
Заметка про токен: /mcp сейчас открыт так же, как REST API при пустом GHARD_ADMIN_TOKEN. Если панель торчит в интернет и ты задаёшь токен — закрой /mcp на reverse proxy или оставь доступ только из доверенной сети, иначе любой сможет читать метрики.