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:
tomasz-syn-grzegorza
2026-07-05 12:02:04 +00:00
commit 359afb3a59
153 changed files with 18169 additions and 0 deletions
+356
View File
@@ -0,0 +1,356 @@
# 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