mirror of
https://github.com/IS1DI/x0gp.git
synced 2026-07-16 20:47:55 +00:00
feat: add fast Docker build script and home server documentation
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
# 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`).
|
||||
Reference in New Issue
Block a user