| monitor | 16 hours ago | ||
| panel | 16 hours ago | ||
| .dockerignore | 16 hours ago | ||
| .gitignore | 16 hours ago | ||
| README.md | 16 hours ago | ||
| docker-compose.yml | 16 hours ago | ||
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 |
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} — удалить сервер (с каскадом метрик)