Files
tomasz-syn-grzegorza 359afb3a59 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>
2026-07-05 12:02:04 +00:00

357 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 06 — Sterowanie wentylatorami GPU
> **Cel rozdziału:** skonfigurować sterowanie wentylatorami RTX 3090 Ti na headless serwerze — krzywa temp → prędkość, web UI w sieci lokalnej, usługa systemd.
**Szacowany czas:** 1520 minut
**Wymagania:** ukończony rozdział [02 — Sterowniki NVIDIA](02-nvidia-driver.md) (`nvidia-smi` działa)
---
## Spis treści
1. [Dlaczego własny stack](#1-dlaczego-własny-stack)
2. [Weryfikacja punktu startowego](#2-weryfikacja-punktu-startowego)
3. [Instalacja](#3-instalacja)
4. [Web UI w sieci lokalnej](#4-web-ui-w-sieci-lokalnej)
5. [Krzywa max cooling](#5-krzywa-max-cooling)
6. [Zarządzanie usługą](#6-zarządzanie-usługą)
7. [Weryfikacja pod obciążeniem](#7-weryfikacja-pod-obciążeniem)
8. [Troubleshooting](#8-troubleshooting)
9. [Następny krok](#9-następny-krok)
---
## 1. Dlaczego własny stack
Na headless Ubuntu **nie działają** narzędzia oparte na `nvidia-settings` + CoolBits (wymagają display servera).
Od sterownika NVIDIA **520+** sterowanie wentylatorami GeForce jest dostępne przez **NVML** — działa bez monitora i bez X11.
Stack [`stacks/gpu-fan/`](../stacks/gpu-fan/):
- daemon NVML (Python + `pynvml`)
- web UI do edycji krzywej
- preset agresywny pod długie obciążenie LocalAI / vLLM
`nvidia-smi` pokazuje tylko odczyty — **nie ustawia** prędkości wentylatorów.
---
## 2. Weryfikacja punktu startowego
```bash
nvidia-smi --query-gpu=name,driver_version,temperature.gpu,fan.speed --format=csv,noheader
# Oczekiwane:
# NVIDIA GeForce RTX 3090 Ti, 595.x, <temp>, <fan> %
```
```bash
python3 -c "import pynvml; pynvml.nvmlInit(); h=pynvml.nvmlDeviceGetHandleByIndex(0); print(pynvml.nvmlDeviceGetName(h)); pynvml.nvmlShutdown()"
```
Jeśli `ModuleNotFoundError: pynvml``install.sh` doinstaluje zależności. Możesz też:
```bash
sudo apt install -y python3-pynvml
```
---
## 3. Instalacja
Z katalogu repozytorium na serwerze:
```bash
cd ~/cursor/ubuntu-bare-metal/stacks/gpu-fan
cp .env.example .env
# opcjonalnie: edytuj GPU_FAN_PORT, API_KEY
sudo scripts/install.sh
sudo scripts/enable-lan.sh
sudo systemctl status gpu-fan
```
**Co robi `install.sh`:**
| Krok | Efekt |
|------|-------|
| `apt install python3-venv` | Środowisko Python |
| Kopiuje pliki do `/opt/gpu-fan` | Kod aplikacji |
| Tworzy `/etc/gpu-fan/curve.json` | Domyślna krzywa max cooling |
| `systemctl enable gpu-fan` | Start przy bootcie |
Logi:
```bash
journalctl -u gpu-fan -f
```
---
## 4. Web UI w sieci lokalnej
Domyślnie UI nasłuchuje na **0.0.0.0:8090** — dostępne z każdego urządzenia w LAN.
```bash
# IP serwera
hostname -I | awk '{print $1}'
# API key
grep ^API_KEY= /opt/control-plane/.env
```
W przeglądarce na laptopie / telefonie w tej samej sieci:
```
http://192.168.100.5:8090/?api_key=TWÓJ_KLUCZ_Z_.env
```
Klucz można też podać w promptcie UI przy pierwszym wejściu (bez `?api_key=` w URL).
### Tylko localhost (opcjonalnie)
W `/opt/control-plane/.env`:
```bash
GPU_FAN_HOST=127.0.0.1
API_KEY=
```
```bash
sudo systemctl restart gpu-fan
```
Dostęp przez SSH tunnel:
```bash
ssh -L 8090:127.0.0.1:8090 tomasz-syn-grzegorza@gmktec-k11
```
Otwórz: **http://localhost:8090**
### Funkcje UI
- Wykres krzywej — przeciąganie punktów; podziałka temperatury (°C) i prędkości (%), siatka pomocnicza i linijki z kreskami na zewnętrznych krawędziach osi
- Tabela temp / speed
- Status live: temperatura, wentylatory, moc, wykorzystanie GPU
- **Zapisz krzywą** — zapis do `/etc/gpu-fan/curve.json`
- **Tryb auto** — oddaje sterowanie driverowi NVIDIA
- **Manual 100%** — awaryjne pełne obroty
### API key
Przy dostępie z LAN **API_KEY jest wymagany** (generowany przy `install.sh` lub ustaw ręcznie w `.env`):
```bash
sudo nano /opt/control-plane/.env
```
```bash
sudo systemctl restart gpu-fan
```
---
## 5. Krzywa max cooling
Domyślny plik `/etc/gpu-fan/curve.json`:
```json
{
"30": 50,
"40": 65,
"50": 80,
"55": 90,
"60": 100,
"70": 100
}
```
Edycja ręczna:
```bash
sudo nano /etc/gpu-fan/curve.json
sudo systemctl reload gpu-fan
```
### Ograniczenia API NVIDIA
| Wartość | Znaczenie |
|---------|-----------|
| 0% | Oddaj sterowanie driverowi (auto) |
| 129% | **Niedozwolone** przez API |
| 30100% | Dozwolone w trybie manual |
RTX 3090 Ti w trybie **auto** może mieć **0 RPM** przy niskiej temperaturze — to normalne zachowanie karty.
---
## 6. Zarządzanie usługą
```bash
sudo systemctl start gpu-fan # start
sudo systemctl stop gpu-fan # stop + przywrócenie auto
sudo systemctl restart gpu-fan # restart
sudo systemctl reload gpu-fan # przeładuj curve.json (SIGHUP)
```
Test API z serwera:
```bash
curl -s http://127.0.0.1:8090/api/status | python3 -m json.tool
```
```bash
curl -s -X POST http://127.0.0.1:8090/api/mode \
-H 'Content-Type: application/json' \
-d '{"mode":"manual","speed":100}'
```
```bash
curl -s -X POST http://127.0.0.1:8090/api/mode \
-H 'Content-Type: application/json' \
-d '{"mode":"auto"}'
```
---
## 7. Weryfikacja pod obciążeniem
### 7.1 Idle
```bash
watch -n2 'curl -s http://127.0.0.1:8090/api/status | python3 -m json.tool'
```
W trybie `curve` przy ~40°C oczekuj target_speed zgodnego z krzywą (np. ~5065%).
### 7.2 Obciążenie GPU
Uruchom inference (LocalAI lub vLLM), np.:
```bash
# LocalAI (jeśli działa)
curl -s http://localhost:8070/v1/models
# lub krótki stress (opcjonalnie, wymaga cuda w kontenerze)
# docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi dmon -s puc -d 1 -c 30
```
Obserwuj w UI lub przez API:
- `temperature_c` rośnie pod loadem
- `target_speed_pct` podąża za krzywą
- `fan_speeds_pct` dążą do `target_speed_pct`
### 7.3 Graceful shutdown
```bash
sudo systemctl stop gpu-fan
nvidia-smi --query-gpu=fan.speed --format=csv,noheader
```
Po stopie usługi wentylatory powinny wrócić do polityki drivera (auto).
### Checklist
- [ ] `systemctl status gpu-fan` — active (running)
- [ ] Web UI dostępne z LAN (`http://<ip>:8090`)
- [ ] Zapis krzywej w UI działa
- [ ] Pod loadem temp rośnie, wentylatory przyspieszają
- [ ] Po `stop` — tryb auto drivera
---
## 8. Troubleshooting
### 8.1 `Insufficient Permissions`
Sterowanie wentylatorami wymaga **root**. Uruchamiaj przez systemd lub `sudo scripts/start.sh`.
### 8.2 `Failed to initialize NVML: Driver/library version mismatch`
Po aktualizacji kernela lub sterownika:
```bash
sudo reboot
```
### 8.3 Wentylatory nie schodzą poniżej 30%
To ograniczenie API NVIDIA w trybie manual — nie błąd aplikacji. Dla ciszy przy idle użyj **Tryb auto** w UI.
### 8.4 Port 8090 zajęty / `address already in use`
**Nie zmieniaj portu na 8091, 8092…** — to tylko maskuje problem. Przy kolejnym podwójnym starcie następny port też będzie zajęty.
Diagnostyka:
```bash
cd ~/cursor/ubuntu-bare-metal/stacks/gpu-fan
scripts/status.sh
sudo ss -tlnp | grep -E ':809[0-9]'
jobs -l # zawieszone Ctrl+Z w tej sesji SSH
```
Czyszczenie:
```bash
sudo scripts/status.sh --cleanup
sudo systemctl start gpu-fan
```
Typowe przyczyny:
| Objaw | Przyczyna | Rozwiązanie |
|-------|-----------|-------------|
| Błąd po `systemctl restart` + `start.sh` | Dwie instancje | Używaj **albo** systemd **albo** `start.sh` |
| `[n]+ Stopped start.sh` w terminalu | Ctrl+Z zamiast Ctrl+C | `kill %n` lub `sudo scripts/status.sh --cleanup` |
| Port zajęty po reboot | `gpu-fan.service` włączone (`enable`) | Normalne — nie uruchamiaj drugiej kopii |
| Zmiana portu w repo `.env` bez efektu | Produkcja czyta `/opt/control-plane/.env` | Edytuj `/opt/control-plane/.env` lub uruchom `setup-control-plane-env.sh` |
Po zmianach w kodzie UI (np. monitoring GPU):
```bash
sudo scripts/install.sh && sudo systemctl restart gpu-fan
```
Foreground debug (tylko gdy systemd zatrzymany):
```bash
sudo systemctl stop gpu-fan
sudo scripts/start.sh
# Zakończ: Ctrl+C (nie Ctrl+Z!)
```
### 8.5 Krzywa odrzucona (400)
- 37 punktów
- temperatury rosnąco, unikalne
- prędkość: 0 lub 30100
---
## 9. Następny krok
Po przejściu checklisty:
1. Zostaw `gpu-fan` włączony przy workloadach AI (LocalAI, ComfyUI, vLLM).
2. Rozdział **07 — ComfyUI stack** — generowanie obrazów w Dockerze.
3. Rozważ `API_KEY` przed ewentualnym wystawieniem portu w rozdziale firewall (08).
Powrót do roadmapy: [README.md](../README.md)
---
## Podsumowanie
Po ukończeniu rozdziału:
- Działa `gpu-fan.service` na hoście (NVML, root)
- Krzywa w `/etc/gpu-fan/curve.json`
- Web UI na **0.0.0.0:8090** (dostęp z sieci lokalnej, z API key)
- Stop usługi przywraca auto drivera NVIDIA