# GHard Monitor

**Gnexus Hardware Monitor** — сбор мониторинга всех серверов в одном месте.

```
┌───────────────┐   POST /api/v1/ingest   ┌────────────────────┐
│ hard-monitor  │ ─────────────────────► │  hard-panel        │
│ (агент,       │   метрики + ключ       │  FastAPI + SQLite  │
│  stateless)   │                        │  + Vue UI          │
└───────────────┘                        └────────────────────┘
```

- **panel/** — панель: приём метрик, SQLite, ивенты, алерты, веб-интерфейс
  (Vue 3 + [gnexus-ui-kit](https://git.gnexus.space/root/gnexus-ui-kit) + chart.js)
- **monitor/** — агент на серверах: psutil-сбор фактов, POST на панель.
  Агент stateless, вся логика (пороги, ивенты, скорость сети по дельте
  счётчиков) — на панели.

## Стек

| Часть | Технологии |
|---|---|
| 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 |

## Разворачивание panel

Нужен сервер с docker и docker compose. SQLite живёт в volume — отдельной
БД не надо.

```bash
git clone https://git.gnexus.space/git/root/hard-panel.git
cd hard-panel
```

**1. Конфиг** — корень репо, рядом с docker-compose.yml:

```bash
cp panel/backend/.env.example .env
```

Отредактируй `.env`:

```ini
# токен админ-доступа к API панели — сгенерируй свой
GHARD_ADMIN_TOKEN=<openssl rand -hex 32>

# порт, на котором панель слушает снаружи (по умолчанию 8000)
GHARD_PANEL_PORT=8000
```

`GHARD_ADMIN_TOKEN` — единственный секрет панели; с ним можно
создавать/удалять серверы и читать метрики, береги его.

**2. Запуск:**

```bash
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 агента.

## Добавление сервера и установка агента

Пока нет веб-интерфейса (этап 3), сервер создаётся через API:

```bash
curl -X POST https://panel.example.com/api/v1/servers \
    -H "Authorization: Bearer $GHARD_ADMIN_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"name": "web-01"}'
```

Ответ — **plaintext-ключ, показывается один раз**, сохрани сразу:

```json
{"id": 1, "name": "web-01", "key": "ghm_KyfA9jheG9OSZxFlfFmdx8yFpO3tZAcO"}
```

Дальше на целевом сервере (python3 + pip):

```bash
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` и
запустит. Повторный запуск — обновление агента.

Логи и управление:

```bash
journalctl -u hard-monitor -f      # смотреть логи
systemctl restart hard-monitor     # рестарт
```

Проверка на панели — сервер должен получить `status: "online"`:

```bash
curl -s https://panel.example.com/api/v1/servers \
    -H "Authorization: Bearer $GHARD_ADMIN_TOKEN"
```

## Обновление

**Panel** — на сервере с панелью:

```bash
cd hard-panel
git pull
docker compose up -d --build
```

**Агент** — на каждом сервере (нужны свежие `hard_monitor.py` /
`hard-monitor.service` в текущем каталоге — склонируй репо):

```bash
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`. Полный бэкап:

```bash
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 из бэкапа нельзя: потерянный ключ —
пересоздай сервер.

## Конфигурация panel (env)

| Переменная | По умолчанию | Описание |
|---|---|---|
| `GHARD_ADMIN_TOKEN` | `change-me` | токен админ-доступа к API |
| `GHARD_DATABASE_PATH` | `/data/hard-panel.db` | путь к SQLite |
| `GHARD_PANEL_PORT` | `8000` | host-порт (docker-compose) |
| `GHARD_OFFLINE_MULTIPLIER` | `3` | offline = нет пакетов дольше N × interval |

## API (кратко)

- `POST /api/v1/servers` — создать сервер, получить ключ агента (один раз)
- `POST /api/v1/ingest` — пакет метрик агента, заголовок `X-Server-Key`
- `GET /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}` — удалить сервер (с каскадом метрик)

## Статус

- [x] Этап 1 — скелет: FastAPI, SQLite-схема, ingest, servers API, docker
- [x] Этап 2 — hard-monitor агент + install.sh + systemd
- [ ] Этап 3 — веб-интерфейс (Vue + ui-kit + chart.js)
- [ ] Этап 4 — ивенты + алерты (Telegram, webhook)
- [ ] Этап 5 — downsample истории (7 дней), финальный деплой