Files
ubuntu-bare-metal/manual-tutorial/06-gpu-fan-control.md
T
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

8.5 KiB
Raw Blame History

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 (nvidia-smi działa)


Spis treści

  1. Dlaczego własny stack
  2. Weryfikacja punktu startowego
  3. Instalacja
  4. Web UI w sieci lokalnej
  5. Krzywa max cooling
  6. Zarządzanie usługą
  7. Weryfikacja pod obciążeniem
  8. Troubleshooting
  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/:

  • 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

nvidia-smi --query-gpu=name,driver_version,temperature.gpu,fan.speed --format=csv,noheader

# Oczekiwane:
# NVIDIA GeForce RTX 3090 Ti, 595.x, <temp>, <fan> %
python3 -c "import pynvml; pynvml.nvmlInit(); h=pynvml.nvmlDeviceGetHandleByIndex(0); print(pynvml.nvmlDeviceGetName(h)); pynvml.nvmlShutdown()"

Jeśli ModuleNotFoundError: pynvmlinstall.sh doinstaluje zależności. Możesz też:

sudo apt install -y python3-pynvml

3. Instalacja

Z katalogu repozytorium na serwerze:

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:

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.

# 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:

GPU_FAN_HOST=127.0.0.1
API_KEY=
sudo systemctl restart gpu-fan

Dostęp przez SSH tunnel:

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):

sudo nano /opt/control-plane/.env
sudo systemctl restart gpu-fan

5. Krzywa max cooling

Domyślny plik /etc/gpu-fan/curve.json:

{
  "30": 50,
  "40": 65,
  "50": 80,
  "55": 90,
  "60": 100,
  "70": 100
}

Edycja ręczna:

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ą

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:

curl -s http://127.0.0.1:8090/api/status | python3 -m json.tool
curl -s -X POST http://127.0.0.1:8090/api/mode \
  -H 'Content-Type: application/json' \
  -d '{"mode":"manual","speed":100}'
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

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.:

# 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

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:

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:

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:

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):

sudo scripts/install.sh && sudo systemctl restart gpu-fan

Foreground debug (tylko gdy systemd zatrzymany):

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


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