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
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 |
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} — удалить сервер (с каскадом метрик)