mirror of
https://github.com/IS1DI/x0gp.git
synced 2026-07-16 20:47:55 +00:00
523 lines
18 KiB
Markdown
523 lines
18 KiB
Markdown
# x0gp — Orange Pi 5 Pro Deployment Guide
|
||
|
||
Практический гайд по развёртыванию x0gp на **Orange Pi 5 Pro** через
|
||
**Coolify** в фазе PoC и MVP. Цель — production-like среда с минимумом
|
||
ручной настройки, используя уже имеющееся железо и платформу.
|
||
|
||
Дата создания: 2026-06-18.
|
||
Дата обновления (Orange Pi 5 Pro + Coolify): 2026-06-18.
|
||
|
||
Связанные документы:
|
||
- `../server/PLAN.md` секция 13 — общее описание.
|
||
- `../ARCHITECTURE.md` ADR-010/011 — почему Orange Pi 5 Pro + Coolify.
|
||
|
||
---
|
||
|
||
## 1. Платформа
|
||
|
||
### 1.1. Orange Pi 5 Pro (уже есть)
|
||
|
||
| Параметр | Значение |
|
||
|---|---|
|
||
| SoC | Rockchip RK3588S |
|
||
| CPU | 8 cores (4× Cortex-A76 @ 2.4 GHz + 4× Cortex-A55 @ 1.8 GHz) |
|
||
| RAM | 4 / 8 / 16 / 32 GB LPDDR4x (зависит от версии; уточнить) |
|
||
| GPU | Mali-G610 MP4 |
|
||
| **NPU** | **6 TOPS (RKNN)** — для CV-инференса на борту |
|
||
| Сеть | 2× 2.5 GbE + Wi-Fi 6 |
|
||
| USB | 2× USB 3.0 |
|
||
| Хранилище | eMMC (опц.) + microSD + NVMe через PCIe (если подключён) |
|
||
| ОС | Ubuntu (уже стоит) |
|
||
|
||
**Что проверить на твоей плате:**
|
||
- RAM (сколько: 4/8/16/32 GB).
|
||
- Охлаждение (радиатор + вентилятор — RK3588S троттлит без них).
|
||
- Хранилище (NVMe или microSD — для продакшна лучше NVMe).
|
||
- Coolify: версия, какие сервисы уже развёрнуты.
|
||
|
||
### 1.2. Coolify (уже развёрнут)
|
||
|
||
Self-hosted PaaS, UI для управления Docker-сервисами. Версия >= 4.0.
|
||
|
||
Что даёт нам:
|
||
- UI деплоя из Git-репо (push-to-deploy).
|
||
- Управление доменами + SSL (Let's Encrypt).
|
||
- Управление env-vars и секретами.
|
||
- Встроенные сервисы: PostgreSQL, Redis, MinIO, Plausible, Uptime Kuma.
|
||
- Логи, метрики, рестарт политики.
|
||
- Версионирование деплоев + rollback.
|
||
|
||
---
|
||
|
||
## 2. Подготовка Orange Pi
|
||
|
||
### 2.1. Хранилище (важно!)
|
||
|
||
По умолчанию Coolify может ставить сервисы на microSD — это медленно и
|
||
microSD изнашивается. Рекомендую:
|
||
|
||
1. Подключить **NVMe SSD** через PCIe (M.2 2230/2242).
|
||
2. Перенести `/var/lib/docker` на NVMe.
|
||
3. Либо в настройках Coolify указать custom docker-data-root.
|
||
|
||
Если NVMe нет — можно начать и на microSD, но обязательно на хорошей
|
||
(A2-rated, минимум 32 GB).
|
||
|
||
### 2.2. Охлаждение
|
||
|
||
RK3588S под нагрузкой греется (особенно NPU). Без охлаждения — троттлинг,
|
||
потеря производительности.
|
||
|
||
- Установить радиатор на SoC (идёт в комплекте, проверить).
|
||
- Добавить вентилятор 5V (питание от GPIO или USB).
|
||
- `armbianmonitor` или `s-tui` для мониторинга температуры.
|
||
- Целевая температура: < 70°C под нагрузкой.
|
||
|
||
### 2.3. Swap (если RAM 4-8 GB)
|
||
|
||
- Создать swap-файл 4-8 GB на NVMe (если есть):
|
||
```bash
|
||
sudo fallocate -l 8G /swapfile
|
||
sudo chmod 600 /swapfile
|
||
sudo mkswap /swapfile
|
||
sudo swapon /swapfile
|
||
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
||
```
|
||
|
||
### 2.4. Обновления
|
||
|
||
```bash
|
||
sudo apt update && sudo apt upgrade -y
|
||
sudo apt install -y curl git ufw fail2ban unattended-upgrades
|
||
sudo apt install -y python3-pip python3-venv # для CV-сервиса
|
||
sudo apt install -y libatlas-base-dev libopenblas-dev # для numpy/onnx
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Сеть
|
||
|
||
### 3.1. Физическая схема
|
||
|
||
```
|
||
[Internet] -- [роутер провайдера] -- [WAN порт Orange Pi #1, 2.5 GbE]
|
||
|
|
||
v
|
||
[Orange Pi 5 Pro]
|
||
|
|
||
| LAN порт Orange Pi #2, 2.5 GbE
|
||
v
|
||
[Опц.: коммутатор]
|
||
|
|
||
v
|
||
[x0gp-track AP]
|
||
/ \
|
||
+-------+ +-------+
|
||
| камера 1 | машинки
|
||
| камера 2 | (Wi-Fi)
|
||
+--------+ +-------+
|
||
```
|
||
|
||
### 3.2. Настройка LAN-порта
|
||
|
||
```bash
|
||
# /etc/netplan/99-x0gp-lan.yaml
|
||
network:
|
||
version: 2
|
||
renderer: networkd
|
||
ethernets:
|
||
eth1: # второй порт — LAN к трассе
|
||
addresses:
|
||
- 10.0.0.1/24
|
||
dhcp4: no
|
||
```
|
||
|
||
```bash
|
||
sudo netplan apply
|
||
```
|
||
|
||
### 3.3. Wi-Fi точка доступа (x0gp-track)
|
||
|
||
Используем встроенный Wi-Fi 6 или внешний USB-адаптер (предпочтительно —
|
||
меньше нагрузка на SoC). Hostapd + dnsmasq:
|
||
|
||
```bash
|
||
sudo apt install -y hostapd dnsmasq
|
||
```
|
||
|
||
`/etc/hostapd/hostapd.conf`:
|
||
```
|
||
interface=wlan0
|
||
driver=nl80211
|
||
ssid=x0gp-track
|
||
hw_mode=g
|
||
channel=6
|
||
wmm_enabled=1
|
||
ieee80211n=1
|
||
wpa=2
|
||
wpa_passphrase=<сложный пароль>
|
||
wpa_key_mgmt=WPA-PSK
|
||
rsn_pairwise=CCMP
|
||
```
|
||
|
||
`/etc/dnsmasq.conf`:
|
||
```
|
||
interface=wlan0
|
||
dhcp-range=10.0.0.100,10.0.0.200,12h
|
||
domain=x0gp.local
|
||
```
|
||
|
||
NAT для выхода машинок в интернет (для OTA и связи с Orange Pi):
|
||
```bash
|
||
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
|
||
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||
```
|
||
|
||
Сохранить: `sudo apt install -y iptables-persistent && sudo netfilter-persistent save`.
|
||
|
||
### 3.4. Проброс портов на роутере
|
||
|
||
Открыть на домашнем роутере и пробросить на Orange Pi (статический IP от
|
||
провайдера):
|
||
- 80/tcp → Orange Pi:80 (для LE challenge)
|
||
- 443/tcp → Orange Pi:443 (для Caddy)
|
||
|
||
Если Orange Pi за роутером с NAT — настроить DMZ или port-forward.
|
||
|
||
---
|
||
|
||
## 4. Coolify: сервисы
|
||
|
||
### 4.1. Создание проекта
|
||
|
||
1. Зайти в Coolify UI (обычно `http://orange-pi-ip:8000`).
|
||
2. Создать новый Project: `x0gp`.
|
||
3. Внутри — Environment: `production`.
|
||
|
||
### 4.2. Сервисы через Coolify UI
|
||
|
||
| Сервис | Назначение | Ресурс |
|
||
|---|---|---|
|
||
| **PostgreSQL + TimescaleDB** | Основная БД + телеметрия | 1-2 GB RAM |
|
||
| **Redis** | Сессии, pub/sub, лобби | 256-512 MB |
|
||
| **MinIO** | S3-совместимое хранилище (replay) | по объёму |
|
||
| **api-gateway** | REST + WS, stateless | 256 MB |
|
||
| **race-engine** | Authoritative tick 60 Hz | 512 MB |
|
||
| **prometheus** | Метрики | 512 MB |
|
||
| **grafana** | Дашборды | 256 MB |
|
||
| **caddy** | Reverse proxy + LE | 128 MB |
|
||
|
||
### 4.3. Нативно (systemd) — не в Coolify
|
||
|
||
Эти компоненты требуют прямого доступа к железу, поэтому запускаются
|
||
через systemd:
|
||
|
||
| Сервис | Назначение |
|
||
|---|---|
|
||
| `x0gp-agent-linker.service` | Связь с ESP32-S3 машинками по Wi-Fi LAN |
|
||
| `x0gp-cv-tracker.service` | Overhead-CV, инференс на NPU |
|
||
| `x0gp-node-exporter.service` | Метрики Orange Pi (CPU, RAM, диск, температура) |
|
||
|
||
Конфиги: `/etc/systemd/system/x0gp-*.service`.
|
||
|
||
---
|
||
|
||
## 5. Доступ из интернета (Caddy + LE через Coolify)
|
||
|
||
Coolify автоматически провизит Let's Encrypt сертификаты для сервисов,
|
||
которым назначен домен.
|
||
|
||
### 5.1. Домены
|
||
|
||
| Сервис | Домен (пример) |
|
||
|---|---|
|
||
| API | `api.x0gp.ru` |
|
||
| Frontend (React) | `app.x0gp.ru` |
|
||
| Grafana | `grafana.x0gp.ru` |
|
||
|
||
### 5.2. DNS
|
||
|
||
A-записи указывают на статический IP Orange Pi:
|
||
```
|
||
api.x0gp.ru. A <статический IP>
|
||
app.x0gp.ru. A <статический IP>
|
||
grafana.x0gp.ru. A <статический IP>
|
||
```
|
||
|
||
### 5.3. SSL
|
||
|
||
Coolify при создании сервиса с доменом сам:
|
||
1. Запрашивает LE-сертификат через ACME challenge.
|
||
2. Прописывает сертификат в Caddy.
|
||
3. Обновляет автоматически.
|
||
|
||
### 5.4. Базовая аутентификация
|
||
|
||
Для Grafana/Prometheus/Admin — добавить basic auth через Caddy или
|
||
Cloudflare Access (опц.).
|
||
|
||
---
|
||
|
||
## 6. NPU и CV-инференс
|
||
|
||
### 6.1. RKNN Toolkit 2
|
||
|
||
Установка (на Orange Pi):
|
||
```bash
|
||
sudo apt install -y python3-pip python3-venv
|
||
python3 -m venv ~/cv-venv
|
||
source ~/cv-venv/bin/activate
|
||
pip install --upgrade pip
|
||
pip install rknn-toolkit2 onnx onnxruntime-rknn ultralytics opencv-python numpy
|
||
```
|
||
|
||
### 6.2. Конвертация модели (на PC)
|
||
|
||
YOLOv8n(детекция машинок):
|
||
```python
|
||
from ultralytics import YOLO
|
||
model = YOLO('yolov8n.pt')
|
||
model.export(format='rknn', imgsz=640)
|
||
```
|
||
|
||
Полученный `.rknn` кладём в `/opt/x0gp/cv/models/`.
|
||
|
||
### 6.3. Запуск инференса
|
||
|
||
```python
|
||
from rknnlite.api import RKNNLite
|
||
import cv2, numpy as np
|
||
|
||
rknn = RKNNLite()
|
||
rknn.load_rknn('/opt/x0gp/cv/models/yolov8n.rknn')
|
||
rknn.init_runtime()
|
||
|
||
# ... capture frame, run inference, parse boxes ...
|
||
```
|
||
|
||
Ожидаемая производительность на Orange Pi 5 Pro:
|
||
- YOLOv8n 640×640: 30-60 FPS на NPU.
|
||
- YOLOv8n 320×320: 60-120 FPS.
|
||
|
||
### 6.4. cv-tracker как systemd-сервис
|
||
|
||
`/etc/systemd/system/x0gp-cv-tracker.service`:
|
||
```ini
|
||
[Unit]
|
||
Description=x0gp CV Tracker (overhead cameras)
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=x0gp
|
||
WorkingDirectory=/opt/x0gp/cv
|
||
Environment="PATH=/home/x0gp/cv-venv/bin"
|
||
ExecStart=/home/x0gp/cv-venv/bin/python tracker.py
|
||
Restart=always
|
||
RestartSec=5
|
||
StandardOutput=journal
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Бэкапы
|
||
|
||
### 7.1. Стратегия
|
||
|
||
- **Ежедневно**: `pg_dump` БД + MinIO bucket snapshots.
|
||
- **Еженедельно**: rclone на внешнее S3-совместимое (Backblaze B2 / Yandex Object Storage).
|
||
- **Ежемесячно**: тест восстановления.
|
||
|
||
### 7.2. Скрипт бэкапа
|
||
|
||
`/opt/x0gp/scripts/backup.sh`:
|
||
```bash
|
||
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
BACKUP_DIR=/opt/x0gp/backups/$(date +%Y-%m-%d)
|
||
mkdir -p "$BACKUP_DIR"
|
||
|
||
# Postgres
|
||
docker exec $(docker ps -qf "name=postgres") pg_dump -U x0gp -Fc x0gp > "$BACKUP_DIR/x0gp.dump"
|
||
|
||
# MinIO (через mc client)
|
||
docker exec $(docker ps -qf "name=minio") mc mirror /data "$BACKUP_DIR/minio/"
|
||
|
||
# Конфиги
|
||
tar czf "$BACKUP_DIR/configs.tar.gz" \
|
||
/opt/x0gp/cv/ \
|
||
/etc/systemd/system/x0gp-*.service \
|
||
/opt/x0gp/repo/.env.example
|
||
|
||
# Retention
|
||
find /opt/x0gp/backups/ -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;
|
||
|
||
echo "[$(date)] backup completed: $BACKUP_DIR"
|
||
```
|
||
|
||
### 7.3. Off-site (опционально)
|
||
|
||
```bash
|
||
rclone sync /opt/x0gp/backups/ b2:x0gp-backups/ \
|
||
--transfers 4 --checkers 8 --stats 30s
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Мониторинг
|
||
|
||
### 8.1. Внутренний (Coolify + Prometheus + Grafana)
|
||
|
||
- Prometheus собирает метрики с Go-сервисов, postgres, redis, node-exporter.
|
||
- Grafana: дашборды (импортировать готовые для Go-runtime и Postgres).
|
||
- Loki (опц.) для централизованных логов.
|
||
- Алерты в Telegram через Alertmanager webhook.
|
||
|
||
### 8.2. Внешний (Uptime Kuma через Coolify)
|
||
|
||
- Uptime Kuma — внешний пинг на `https://api.x0gp.ru/health`.
|
||
- Алертит если 2+ минуты не отвечает.
|
||
- Доступен извне через поддомен `status.x0gp.ru`.
|
||
|
||
### 8.3. Ключевые дашборды Grafana
|
||
|
||
- **System**: CPU, RAM, диск, сеть, температура RK3588S (через node-exporter
|
||
+ custom exporter).
|
||
- **x0gp**: ws_connections, rtt_ms p50/p95/p99, tick_lag, drop_rate,
|
||
gateway_online.
|
||
- **DB**: postgres connections, slow queries, replication lag.
|
||
- **CV**: FPS инференса на NPU, использование NPU, число обнаруженных объектов.
|
||
- **Business**: активные гонки, DAU, конверсия заездов.
|
||
|
||
---
|
||
|
||
## 9. Безопасность
|
||
|
||
### 9.1. Чеклист
|
||
|
||
- [ ] SSH только по ключам, пароли отключены.
|
||
- [ ] Нестандартный порт SSH (например, 2222).
|
||
- [ ] fail2ban настроен (по умолчанию для ssh).
|
||
- [ ] UFW: разрешён только 80/tcp + 443/tcp + SSH (LAN only).
|
||
- [ ] Coolify UI доступен только из LAN или за basic auth.
|
||
- [ ] Postgres и Redis слушают только на 127.0.0.1.
|
||
- [ ] Все секреты в Coolify env-vars (не в git).
|
||
- [ ] Автообновления безопасности включены (`unattended-upgrades`).
|
||
- [ ] UPS для Orange Pi (важно для microSD/NVMe).
|
||
- [ ] Бэкапы шифрованы (если off-site).
|
||
|
||
### 9.2. UFW
|
||
|
||
```bash
|
||
sudo ufw default deny incoming
|
||
sudo ufw default allow outgoing
|
||
sudo ufw allow from 192.168.1.0/24 to any port 8000 proto tcp # Coolify UI (LAN only)
|
||
sudo ufw allow 80/tcp # LE challenge + Caddy
|
||
sudo ufw allow 443/tcp # Caddy
|
||
sudo ufw allow from 10.0.0.0/24 to any port 22 proto tcp # SSH с LAN трассы (опц.)
|
||
sudo ufw enable
|
||
```
|
||
|
||
(Если Orange Pi за NAT, 80/443 уже проброшены на роутере — это ок.)
|
||
|
||
### 9.3. Fail2Ban
|
||
|
||
```bash
|
||
sudo systemctl enable fail2ban
|
||
sudo systemctl start fail2ban
|
||
```
|
||
|
||
---
|
||
|
||
## 10. Обслуживание
|
||
|
||
### 10.1. Ежедневно
|
||
|
||
- Проверить алерты в Telegram.
|
||
- Зайти в Grafana, посмотреть дашборды.
|
||
- Проверить Uptime Kuma.
|
||
|
||
### 10.2. Еженедельно
|
||
|
||
- Проверить, что бэкапы создаются (`ls /opt/x0gp/backups/`).
|
||
- `apt list --upgradable`, при необходимости `apt upgrade`.
|
||
- Проверить свободное место на диске.
|
||
- Проверить температуру Orange Pi.
|
||
|
||
### 10.3. Ежемесячно
|
||
|
||
- Тест восстановления из бэкапа.
|
||
- Ротация API-ключей (LE аккаунт, Coolify admin).
|
||
- `docker system prune -a` (осторожно, не удалит volumes).
|
||
- Проверка UPS (тест батареи).
|
||
|
||
### 10.4. Деплой новой версии
|
||
|
||
Через Coolify UI:
|
||
1. Push в Git → триггер автоматического деплоя (если настроен webhook).
|
||
2. Или в Coolify UI нажать "Deploy" на нужном сервисе.
|
||
3. Проверить логи, метрики, smoke-test.
|
||
|
||
---
|
||
|
||
## 11. Troubleshooting
|
||
|
||
### 11.1. "Coolify недоступен"
|
||
|
||
- `docker ps` — все контейнеры работают?
|
||
- `docker logs coolify` — смотреть ошибки.
|
||
- `sudo systemctl restart coolify` (или `docker restart coolify`).
|
||
|
||
### 11.2. "Бэкап не создаётся"
|
||
|
||
- `systemctl status x0gp-backup.timer` — таймер активен?
|
||
- `journalctl -u x0gp-backup.service` — последний запуск.
|
||
- Права на `/opt/x0gp/backups/` — пользователь `x0gp` может писать?
|
||
- Место на диске: `df -h /opt/x0gp/backups`.
|
||
|
||
### 11.3. "Высокий latency"
|
||
|
||
- Проверить `rtt_ms` в Grafana — где растёт (клиент -> edge или edge -> agent).
|
||
- `ping` от Orange Pi до роутера x0gp-track.
|
||
- Wi-Fi: проверить interference через `iw dev wlan0 survey dump`.
|
||
- NPU: не перегревается ли Orange Pi (троттлинг → медленный CV → задержка)?
|
||
|
||
### 11.4. "NPU не работает"
|
||
|
||
- `ls /dev/dri/` — есть ли render node?
|
||
- `rknn-toolkit2` версия совместима с системой?
|
||
- `dmesg | grep -i rknn` — ошибки драйвера?
|
||
- Fallback: запустить инференс на CPU ARM A76 (медленнее, но работает).
|
||
|
||
### 11.5. "Postgres тормозит"
|
||
|
||
- `pg_stat_activity` — что сейчас выполняется.
|
||
- `EXPLAIN ANALYZE` на медленных запросах.
|
||
- Проверить индексы (особенно на `telemetry (race_id, ts)`).
|
||
- NVMe не заполнен? (`df -h`)
|
||
|
||
---
|
||
|
||
## 12. Что дальше
|
||
|
||
- [ ] Проверить характеристики Orange Pi 5 Pro (RAM, охлаждение, хранилище).
|
||
- [ ] Подключить NVMe SSD и перенести Docker data root.
|
||
- [ ] Установить радиатор + вентилятор (если не стоят).
|
||
- [ ] Настроить LAN-порт (eth1) + Wi-Fi AP.
|
||
- [ ] Создать проект `x0gp` в Coolify.
|
||
- [ ] Развернуть PostgreSQL, Redis, MinIO через Coolify.
|
||
- [ ] Создать базовые сервисы api-gateway, race-engine.
|
||
- [ ] Настроить systemd-сервисы agent-linker и cv-tracker.
|
||
- [ ] Настроить бэкапы.
|
||
- [ ] Заполнить чеклист безопасности.
|
||
- [ ] Запустить PoC (1 машинка + 1 трасса 100×60 см на столе).
|
||
- [ ] Замерить baseline latency и записать в `docs/baselines/`.
|
||
|
||
После стабильной работы PoC в течение 2-4 недель — переходить к MVP (фаза S1
|
||
в `server/PLAN.md`, H1 в `hardware/PLAN.md`).
|