Initial import: bare-metal stacks, Server UI, GPU fan, tutorials.
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI, control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
# GPU Fan Control stack
|
||||
|
||||
Sterowanie wentylatorami **RTX 3090 Ti** na headless Ubuntu przez NVML — bez `nvidia-settings` i bez GUI.
|
||||
|
||||
**Panel webowy** jest w **Server UI** (`http://<host>:8091` → zakładka **GPU Fan**). Ten stack uruchamia tylko **agenta API** na localhost.
|
||||
|
||||
## Porty
|
||||
|
||||
| Serwis | Port | Dostęp |
|
||||
|--------|------|--------|
|
||||
| GPU Fan agent API | **18090** | `127.0.0.1` tylko (systemd, root) |
|
||||
| GPU Fan UI | — | Server UI **:8091** (zakładka GPU Fan) |
|
||||
|
||||
Port **8090** nie jest już używany w produkcji.
|
||||
|
||||
## Jak to działa
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
browser["Przeglądarka :8091"]
|
||||
serverUI["server-ui"]
|
||||
agent["fan_daemon.py :18090"]
|
||||
nvml["NVML / pynvml"]
|
||||
gpu["RTX 3090 Ti"]
|
||||
|
||||
browser --> serverUI
|
||||
serverUI -->|"proxy /api/gpu-fan"| agent
|
||||
agent --> nvml
|
||||
nvml --> gpu
|
||||
```
|
||||
|
||||
| Element | Opis |
|
||||
|---------|------|
|
||||
| Agent | `fan_daemon.py` — pętla NVML + API REST |
|
||||
| Dev UI | `app.py` — monolit z UI (tylko dev / DRY_RUN) |
|
||||
| Logika | `fan_controller.py` — interpolacja krzywej |
|
||||
| Konfiguracja | `/etc/gpu-fan/curve.json` |
|
||||
| systemd | `gpu-fan.service` (root, auto-restart) |
|
||||
|
||||
## Wymagania
|
||||
|
||||
- Sterownik NVIDIA ≥ 520 (testowane: **595-server-open**)
|
||||
- Root / sudo (zapis NVML wymaga uprawnień root)
|
||||
- Python 3 + venv (instalowane przez `install.sh`)
|
||||
- **Server UI** na :8091 (proxy do agenta)
|
||||
|
||||
## Szybki start
|
||||
|
||||
```bash
|
||||
cd stacks/gpu-fan
|
||||
cp ../control-plane/.env.example ../control-plane/.env
|
||||
|
||||
sudo scripts/install.sh
|
||||
sudo systemctl start gpu-fan
|
||||
|
||||
cd ../server-ui
|
||||
sudo scripts/install.sh
|
||||
```
|
||||
|
||||
Panel: `http://<IP-serwera>:8091` → zakładka **GPU Fan**.
|
||||
|
||||
Po zmianach w kodzie:
|
||||
|
||||
```bash
|
||||
sudo scripts/install.sh && sudo systemctl restart gpu-fan
|
||||
cd ../server-ui && sudo scripts/install.sh && sudo systemctl restart server-ui
|
||||
```
|
||||
|
||||
Konfiguracja: produkcja `/opt/control-plane/.env`, dev `stacks/control-plane/.env`.
|
||||
|
||||
### Klucz API
|
||||
|
||||
Jeden wspólny `API_KEY` w `/opt/control-plane/.env` — auth panelu Server UI i agenta gpu-fan (proxy `/api/gpu-fan/*`).
|
||||
|
||||
W panelu Server UI wpisz ten sam klucz w polu **API Key** (lub `?api_key=...` w URL).
|
||||
|
||||
## Preset max cooling
|
||||
|
||||
Domyślna krzywa w [`curve.default.json`](curve.default.json):
|
||||
|
||||
| Temp | Speed |
|
||||
|------|-------|
|
||||
| 30°C | 50% |
|
||||
| 40°C | 65% |
|
||||
| 50°C | 80% |
|
||||
| 55°C | 90% |
|
||||
| 60°C | 100% |
|
||||
| 70°C+ | 100% |
|
||||
|
||||
## Tryby
|
||||
|
||||
| Tryb | Opis |
|
||||
|------|------|
|
||||
| `curve` | Krzywa z JSON — interpolacja liniowa |
|
||||
| `manual` | Stała prędkość (np. 100% awaryjnie) |
|
||||
| `auto` | Oddaje sterowanie driverowi NVIDIA |
|
||||
|
||||
## API agenta (localhost :18090)
|
||||
|
||||
| Endpoint | Metoda | Opis |
|
||||
|----------|--------|------|
|
||||
| `/api/status` | GET | Temperatura, wentylatory, moc, tryb |
|
||||
| `/api/curve` | GET/PUT | Odczyt / zapis krzywej |
|
||||
| `/api/mode` | POST | `{"mode":"auto\|curve\|manual","speed":100}` |
|
||||
| `/api/reload` | POST | Przeładuj `curve.json` (jak `SIGHUP`) |
|
||||
|
||||
Z LAN używaj proxy Server UI: `/api/gpu-fan/status`, `/api/gpu-fan/curve`, itd.
|
||||
|
||||
## Ograniczenia NVIDIA
|
||||
|
||||
- `nvidia-smi` **nie steruje** wentylatorami — tylko odczyt
|
||||
- API akceptuje **0%** (= auto) lub **30–100%**
|
||||
- Po `systemctl stop gpu-fan` wentylatory wracają do trybu auto drivera
|
||||
|
||||
## Struktura
|
||||
|
||||
```
|
||||
stacks/gpu-fan/
|
||||
├── README.md
|
||||
├── fan_daemon.py # produkcja — agent API
|
||||
├── app.py # dev — UI + API (opcjonalnie)
|
||||
├── fan_controller.py
|
||||
├── curve.default.json
|
||||
├── requirements.txt
|
||||
├── gpu-fan.service
|
||||
├── .env.example
|
||||
├── static/index.html # referencja UI (wbudowane w server-ui)
|
||||
└── scripts/
|
||||
├── install.sh
|
||||
├── enable-lan.sh # konfiguruje agent + wskazówka :8091
|
||||
└── status.sh
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**`Insufficient Permissions`** — uruchom jako root (`sudo systemctl start gpu-fan`).
|
||||
|
||||
**Panel GPU Fan pusty / 502** — sprawdź agent: `curl -s http://127.0.0.1:18090/api/status -H "X-API-Key: ..."`
|
||||
|
||||
**Port 18090 zajęty** — `scripts/status.sh` / `sudo scripts/status.sh --cleanup`
|
||||
|
||||
**Przeładuj krzywą bez restartu:**
|
||||
|
||||
```bash
|
||||
sudo systemctl reload gpu-fan
|
||||
```
|
||||
|
||||
## Dokumentacja
|
||||
|
||||
| Dokument | Opis |
|
||||
|----------|------|
|
||||
| [docs/00-START-TUTAJ.md](docs/00-START-TUTAJ.md) | Mapa — zacznij tutaj |
|
||||
| [docs/02-OTWIERANIE-UI-W-PRZEGLADARCE.md](docs/02-OTWIERANIE-UI-W-PRZEGLADARCE.md) | Panel w Server UI :8091 |
|
||||
| [docs/05-DLACZEGO-NIE-DOCKER.md](docs/05-DLACZEGO-NIE-DOCKER.md) | Dlaczego host, nie Docker |
|
||||
Reference in New Issue
Block a user