# 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:** 15–20 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, , % ``` ```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) | | 1–29% | **Niedozwolone** przez API | | 30–100% | 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. ~50–65%). ### 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://: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) - 3–7 punktów - temperatury rosnąco, unikalne - prędkość: 0 lub 30–100 --- ## 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