# 04 — Dysk danych 1 TB + vLLM stack > **Cel rozdziału:** dodać dysk 1 TB jako `/data` (aplikacje, modele, Docker), a na dysku systemowym 128 GB zostawić wyłącznie Ubuntu. Następnie uruchomić vLLM z mountami na `/data`. **Szacowany czas:** - Dysk 1 TB + migracja Docker: 20–40 minut - Pierwsze uruchomienie vLLM: 20–60 minut (pobieranie obrazu i modelu) **Wymagania:** ukończone rozdziały [01](01-system-update-and-docker.md)–[03](03-nvidia-container-toolkit.md) oraz [03b — Narzędzia bazowe](03b-system-tools.md) --- ## Spis treści **Część A — dysk danych** 1. [Architektura dysków](#1-architektura-dysków) 2. [Wykrycie i partycjonowanie dysku 1 TB](#2-wykrycie-i-partycjonowanie-dysku-1-tb) 3. [Montowanie `/data` i wpis w fstab](#3-montowanie-data-i-wpis-w-fstab) 4. [Struktura katalogów na `/data`](#4-struktura-katalogów-na-data) 5. [Przeniesienie Docker data-root na `/data`](#5-przeniesienie-docker-data-root-na-data) **Część B — vLLM** 6. [Jak działa vLLM (bez UI)](#6-jak-działa-vllm-bez-ui) 7. [Mapowanie ustawień z LM Studio](#7-mapowanie-ustawień-z-lm-studio) 8. [Struktura plików stacku](#8-struktura-plików-stacku) 9. [Przygotowanie stacku (bez modelu)](#9-przygotowanie-stacku-bez-modelu) 10. [Wybór modelu i start](#10-wybór-modelu-i-start) 11. [Test API](#11-test-api) 12. [Tuning po starcie (jeśli OOM)](#12-tuning-po-starcie-jeśli-oom) 13. [Zmiana modelu](#13-zmiana-modelu) 14. [Zarządzanie stackiem](#14-zarządzanie-stackiem) 15. [Weryfikacja](#15-weryfikacja) 16. [Troubleshooting](#16-troubleshooting) 17. [Czego nie robimy w tym kroku](#17-czego-nie-robimy-w-tym-kroku) 18. [Następny krok](#18-następny-krok) --- # Część A — Dysk danych 1 TB ## 1. Architektura dysków | Dysk | Rozmiar | Mount | Przeznaczenie | |------|---------|-------|---------------| | NVMe systemowy | 128 GB (`nvme1n1`) | `/` | Ubuntu, konfiguracja, repo tutoriala | | Dysk danych | 1 TB (`nvme0n1`) | `/data` | Docker, modele LLM, ComfyUI, cache | ```mermaid flowchart TB subgraph systemDisk ["128GB NVMe — /"] os["Ubuntu 26.04"] etc["/etc /boot"] home["/home"] repo["cursor/ubuntu-bare-metal"] end subgraph dataDisk ["1TB — /data"] docker["/data/docker — Docker images/volumes"] vllm["/data/apps/vllm/huggingface"] comfyui["/data/apps/comfyui/*"] end docker --> vllm docker --> comfyui ``` **Zasada:** Na dysku systemowym nie trzymamy modeli ani obrazów Docker. Wszystko ciężkie idzie na `/data`. **Uwaga:** Fizycznie zamontuj dysk 1 TB w GMKtec K11 przed wykonaniem sekcji 2. Po podłączeniu zrób reboot lub rescann PCI/NVMe. --- ## 2. Wykrycie i partycjonowanie dysku 1 TB ### 2.1 Wykrycie nowego dysku ```bash lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,MODEL ``` Oczekiwany układ **po** podłączeniu dysku 1 TB na GMKtec K11: ``` nvme1n1 119G # dysk SYSTEMOWY — NIE DOTYKAĆ ├─nvme1n1p1 1G /boot/efi └─nvme1n1p2 118G / nvme0n1 931G # dysk DANYCH 1 TB — ten partycjonujemy ``` **Uwaga:** Na tym modelu GMKtec K11 numeracja bywa odwrotna niż intuicyjnie — `nvme0n1` to 1 TB, `nvme1n1` to 128 GB systemu. Zawsze weryfikuj po `SIZE` i `MOUNTPOINT`, nie po numerze. **KRYTYCZNE:** Partycjonuj wyłącznie dysk ~1 TB **bez** mountpointu `/`. Nigdy `nvme1n1`. Zapisz nazwę urządzenia: ```bash # GMKtec K11 — dysk DANYCH 1 TB (sprawdź lsblk!) export DATA_DISK=/dev/nvme0n1 export DATA_PART=/dev/nvme0n1p1 echo "DATA_DISK=$DATA_DISK" echo "DATA_PART=$DATA_PART" lsblk $DATA_DISK # weryfikacja: DATA_DISK nie może mieć mountpoint / lsblk -n -o MOUNTPOINT $DATA_DISK | grep -q '^/$' && echo "BŁĄD: to dysk systemowy!" && exit 1 ``` ### Szybka instalacja (skrypt) Jeśli partycja `nvme0n1p1` już istnieje (lub po ręcznym parted), uruchom w **swoim terminalu SSH** (wymaga hasła sudo): ```bash sudo bash /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/scripts/setup-data-disk.sh ``` Skrypt: formatuje `nvme0n1p1`, montuje `/data`, fstab, katalogi, migracja Docker → `/data/docker`. --- ### 2.2 Partycjonowanie ręczne (jeśli bez skryptu) Partycja: `/dev/nvme0n1p1` (na GMKtec K11). ```bash # OBOWIĄZKOWO ustaw obie zmienne przed każdą komendą! export DATA_DISK=/dev/nvme0n1 export DATA_PART=/dev/nvme0n1p1 # sprawdź jeszcze raz przed zapisem! lsblk $DATA_DISK echo "Partycja: $DATA_PART" sudo parted -s $DATA_DISK mklabel gpt sudo parted -s $DATA_DISK mkpart primary ext4 0% 100% sudo partprobe $DATA_DISK sleep 2 lsblk $DATA_DISK ``` ### 2.3 Formatowanie ext4 ```bash sudo mkfs.ext4 -L data1tb $DATA_PART ``` --- ## 3. Montowanie `/data` i wpis w fstab ### 3.1 Pobranie UUID (stabilniejsze niż /dev/sdX) ```bash sudo blkid $DATA_PART ``` Zapisz UUID, np. `UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. ### 3.2 Montowanie tymczasowe i test ```bash sudo mkdir -p /data sudo mount $DATA_PART /data df -h /data ``` Oczekiwane: ~1 TB dostępne na `/data`. ### 3.3 Wpis w `/etc/fstab` (montowanie przy bootcie) ```bash # zamień YOUR-UUID na rzeczywisty UUID z blkid echo 'UUID=YOUR-UUID /data ext4 defaults,noatime 0 2' | sudo tee -a /etc/fstab ``` **Lepiej edytować ręcznie** — sprawdź składnię: ```bash sudo nano /etc/fstab ``` Dodaj linię (przykład): ``` UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 /data ext4 defaults,noatime 0 2 ``` Test fstab (montuje wszystko bez rebootu): ```bash sudo umount /data sudo mount -a df -h /data ``` Jeśli `mount -a` nie zwraca błędu — fstab jest poprawny. --- ## 4. Struktura katalogów na `/data` ```bash # Docker data-root (własność root) sudo mkdir -p /data/docker # Katalogi aplikacji (własność użytkownika — łatwiejszy dostęp) sudo mkdir -p /data/apps/vllm/huggingface sudo mkdir -p /data/apps/gguf/{qwen3.6-27b,gemma-4-12b} sudo mkdir -p /data/apps/localai/{models,backends,configuration,images,data} sudo mkdir -p /data/apps/comfyui/{models,input,output,custom_nodes} sudo chown -R $USER:$USER /data/apps ``` Docelowa struktura: ``` /data/ ├── docker/ # Docker data-root (obrazy, warstwy, volumes) └── apps/ ├── vllm/ │ └── huggingface/ # cache modeli Hugging Face (AWQ) ├── gguf/ # przyszłe GGUF (llama.cpp) │ ├── qwen3.6-27b/ │ └── gemma-4-12b/ └── comfyui/ # przygotowane pod rozdział 05 ├── models/ ├── input/ ├── output/ └── custom_nodes/ ``` Sprawdź: ```bash tree -L 3 /data 2>/dev/null || find /data -maxdepth 3 -type d df -h / /data ``` --- ## 5. Przeniesienie Docker data-root na `/data` Domyślnie Docker trzyma dane w `/var/lib/docker` na dysku systemowym. Przenosimy na `/data/docker`. ### 5.1 Zatrzymanie Docker ```bash sudo systemctl stop docker sudo systemctl stop docker.socket 2>/dev/null || true ``` Upewnij się, że nie ma uruchomionych kontenerów: ```bash docker ps # powinno być puste lub błąd „cannot connect” — OK ``` ### 5.2 Kopia istniejących danych Docker Jeśli już pobierałeś obrazy (np. `hello-world`, `nvidia/cuda`): ```bash sudo rsync -aHAX --progress /var/lib/docker/ /data/docker/ ``` Jeśli `/var/lib/docker` jest pusty lub mało znaczący: ```bash sudo mkdir -p /data/docker ``` ### 5.3 Aktualizacja `/etc/docker/daemon.json` ```bash sudo python3 -c " import json from pathlib import Path p = Path('/etc/docker/daemon.json') cfg = json.loads(p.read_text()) if p.exists() else {} cfg['data-root'] = '/data/docker' p.write_text(json.dumps(cfg, indent=2) + '\n') print(p.read_text()) " ``` Oczekiwany fragment: ```json { "data-root": "/data/docker", "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "3" }, "runtimes": { "nvidia": { "args": [], "path": "nvidia-container-runtime" } } } ``` ### 5.4 Uruchomienie Docker i weryfikacja ```bash sudo systemctl start docker docker info | grep "Docker Root Dir" ``` Oczekiwane: `Docker Root Dir: /data/docker` ```bash docker run --rm hello-world docker run --rm --gpus all nvidia/cuda:12.6.0-base-ubuntu24.04 nvidia-smi ``` ### 5.5 Opcjonalnie: zwolnienie miejsca na dysku systemowym **Dopiero po potwierdzeniu**, że Docker działa z nowego data-root: ```bash # UWAGA: nieodwracalne — usuwa stare dane Dockera z dysku systemowego sudo rm -rf /var/lib/docker ``` Sprawdź, że dysk systemowy ma więcej wolnego miejsca: ```bash df -h / df -h /data ``` ### Checklist — część A (dysk) - [ ] Dysk 1 TB widoczny w `lsblk` - [ ] Partycja sformatowana ext4 - [ ] `/data` zamontowany, ~1 TB wolne - [ ] Wpis w `/etc/fstab` (UUID) - [ ] `mount -a` bez błędów - [ ] Katalogi `/data/docker` i `/data/apps/*` utworzone - [ ] `Docker Root Dir: /data/docker` - [ ] `hello-world` i test GPU w Dockerze działają **Nie przechodź do vLLM, dopóki checklista części A nie jest ukończona.** --- # Część B — vLLM stack ## 6. Jak działa vLLM (bez UI) vLLM to **serwer API** — nie ma panelu administracyjnego jak LM Studio. | LM Studio | vLLM na serwerze | |-----------|------------------| | Panel UI, suwaki | Plik `.env` + profile + skrypty | | GGUF Q4 (lmstudio-community) | **Nie w vLLM** — przyszły stack [`stacks/llamacpp/`](../stacks/llamacpp/); interim: AWQ z HF | | Hugging Face AWQ | Kontener Docker `vllm/vllm-openai` | | Lokalny chat | HTTP API OpenAI (`/v1/chat/completions`) | Konfiguracja = zmienne w `.env` przekazywane jako flagi `vllm serve`. Test: `curl` + `jq` lub klient OpenAI. **Model nie jest pobierany przy instalacji stacku** — katalog `models.catalog.yaml` + `download-model.sh` na żądanie. `VLLM_MODEL` ustawiasz przez profil dopiero gdy jesteś gotowy. ### GGUF z lmstudio-community — nie działa w standardowym vLLM Linki typu `lmstudio-community/Qwen3.6-27B-GGUF` to pliki **`.gguf`**. Obraz `vllm/vllm-openai` ich nie obsługuje (wymagałby eksperymentalnego `vllm-gguf-plugin` lub osobnego hosta). | Co chcesz | Co robisz | |-----------|-----------| | Q4 jak w LM Studio (GGUF) | `download-model.sh ` → `/data/apps/gguf/` → później `stacks/llamacpp/` | | Q4-odpowiednik **teraz** na vLLM | `download-model.sh qwen3.6-27b-awq-vllm` + profil AWQ | --- ## 7. Mapowanie ustawień z LM Studio Jeśli testowałeś Qwen3.6-27B na Windows (LM Studio / Ollama): | LM Studio / Ollama | vLLM (`.env` / flagi) | |--------------------|----------------------| | Model GGUF Q4 (lmstudio) | Katalog `runtime: llamacpp` — **nie** ten stack vLLM | | Odpowiednik Q4 na vLLM (interim) | `VLLM_MODEL=Qwen/Qwen3.6-27B-Instruct-AWQ`, `QUANTIZATION=awq` | | K Cache Q4_0 | `KV_CACHE_DTYPE=fp8` | | V Cache Q4_0 | j.w. — vLLM **nie ma** `Q4_0` (format GGUF/llama.cpp) | | Context 128K | `MAX_MODEL_LEN=131072` | | 1 wątek | `MAX_NUM_SEQS=1` | | GPU layers max | `GPU_MEMORY_UTILIZATION=0.95` | Alternatywa KV cache (więcej miejsca, bliżej Q4): `KV_CACHE_DTYPE=turboquant_k8v4` — testuj po udanym starcie z `fp8`. > Później porównamy z kopią ustawień LM Studio na Windows i doprecyzujemy parametry. --- ## 8. Struktura plików stacku ``` stacks/vllm/ ├── README.md ├── models.catalog.yaml # GGUF + vLLM AWQ, bez auto-pobierania ├── docker-compose.yml ├── .env.example ├── profiles/ │ ├── _template.env │ └── qwen3.6-27b-awq-128k.env └── scripts/ ├── list-models.sh ├── download-model.sh ├── switch-model.sh ├── start.sh └── vllm-entrypoint.sh ``` Dane na dysku 1 TB: ``` /data/apps/vllm/huggingface/ ← cache AWQ (Hugging Face) /data/apps/gguf/ ← przyszłe GGUF (tworzone przez skrypty) /data/docker/ ← obrazy Docker (vLLM ~10 GB) ``` ```bash cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm ``` ### Kluczowe elementy `docker-compose.yml` | Element | Po co | |---------|-------| | `profiles: [vllm]` | Serwis nie startuje przypadkowo bez `--profile vllm` | | `ipc: host` | Shared memory — wymagane przez PyTorch | | `vllm-entrypoint.sh` | Buduje flagi z `.env` (`QUANTIZATION`, `VLLM_EXTRA_ARGS`) | | `QUANTIZATION` | Opcjonalne — puste = model pełnej precyzji | | `VLLM_EXTRA_ARGS` | Flagi per profil (Qwen: `--reasoning-parser qwen3`) | Domyślne flagi w profilu Qwen (przekazywane przez `VLLM_EXTRA_ARGS`): | Flaga | Po co | |-------|-------| | `--language-model-only` | Bez vision encoder — więcej VRAM na KV cache | | `--enforce-eager` | Mniej overhead CUDA graphs na 24 GB | | `--max-num-seqs 1` | Jedna sekwencja naraz (jak 1 wątek w LM Studio) | | `--kv-cache-dtype fp8` | Kompresja KV cache (`KV_CACHE_DTYPE`) | | `--max-model-len 131072` | Okno kontekstu 128K (`MAX_MODEL_LEN`) | --- ## 9. Przygotowanie stacku (bez modelu) ### 9.1 Utwórz `.env` z szablonu ```bash cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm cp .env.example .env cat .env ``` Oczekiwane — `VLLM_MODEL` **pusty**: ```env DATA_ROOT=/data VLLM_MODEL= SERVED_MODEL_NAME=qwen3.6-27b MAX_MODEL_LEN=131072 MAX_NUM_SEQS=1 GPU_MEMORY_UTILIZATION=0.95 KV_CACHE_DTYPE=fp8 QUANTIZATION=awq VLLM_EXTRA_ARGS=--language-model-only --enforce-eager --reasoning-parser qwen3 ``` Na tym etapie **nic nie pobierasz** — stack jest gotowy do konfiguracji. ### 9.2 Katalog modeli ```bash ./scripts/list-models.sh ``` Pokazuje wpisy z `models.catalog.yaml` i czy pliki są już na dysku (`ON DISK`). ### 9.3 Sprawdź katalogi cache ```bash mkdir -p /data/apps/vllm/huggingface df -h /data ``` --- ## 10. Wybór modelu i start ### 10.1 Pobierz model (on demand) ```bash cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm # vLLM interim — AWQ (~15 GB) do cache HF ./scripts/download-model.sh qwen3.6-27b-awq-vllm ``` GGUF (na później, pod llama.cpp): ```bash # ./scripts/download-model.sh qwen3.6-27b-q4-gguf # ./scripts/download-model.sh gemma-4-12b-q4-gguf ``` ### 10.2 Preset Qwen3.6-27B AWQ @ 128K ```bash ./scripts/switch-model.sh qwen3.6-27b-awq-128k ``` Alternatywa — ręcznie: ```bash cp profiles/qwen3.6-27b-awq-128k.env .env ``` ### 10.3 Uruchomienie ```bash ./scripts/start.sh # lub profil w jednej komendzie: # ./scripts/start.sh qwen3.6-27b-awq-128k ``` Skrypt sprawdza: `VLLM_MODEL` ustawiony, brak `.gguf`, `/data` zamontowany, Docker działa. Alternatywa ręczna: ```bash docker compose --profile vllm pull docker compose --profile vllm up -d ``` ### 10.4 Pierwszy start — czego się spodziewać 1. Pobranie obrazu `vllm/vllm-openai` (~8–12 GB) → `/data/docker` 2. Pobranie modelu AWQ (~15 GB) → `/data/apps/vllm/huggingface` 3. Ładowanie wag do VRAM — **10–30+ minut** ```bash docker compose --profile vllm logs -f vllm ``` Szukaj: ``` INFO: Uvicorn running on http://0.0.0.0:8000 ``` ### 10.5 Monitorowanie ```bash # terminal 1 watch -n 1 nvidia-smi # terminal 2 watch -n 5 'df -h /data; du -sh /data/apps/vllm/huggingface 2>/dev/null' ``` --- ## 11. Test API Użyj `SERVED_MODEL_NAME` z `.env` (domyślnie `qwen3.6-27b-awq` w presecie). ### 11.1 Lista modeli ```bash curl -s http://localhost:8000/v1/models | jq . ``` ### 11.2 Health check ```bash curl -s http://localhost:8000/health ``` ### 11.3 Chat completion ```bash curl -s http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3.6-27b-awq", "messages": [{"role": "user", "content": "Say hello in one word."}], "max_tokens": 32 }' | jq . ``` Pole `"model"` musi odpowiadać `SERVED_MODEL_NAME` z `.env`. --- ## 12. Tuning po starcie (jeśli OOM) Kolejność — zmieniaj w `.env` i restartuj: ```bash docker compose --profile vllm down # edytuj .env docker compose --profile vllm up -d ``` | Krok | Zmiana | Kiedy | |------|--------|-------| | 1 | `MAX_MODEL_LEN=98304` lub `65536` | OOM przy ładowaniu lub długim prompcie | | 2 | `GPU_MEMORY_UTILIZATION=0.90` | Nadal OOM | | 3 | `KV_CACHE_DTYPE=turboquant_k8v4` | Potrzeba więcej miejsca na KV (bliżej Q4_0) | --- ## 13. Zmiana modelu (A / B na dysku, jeden w VRAM) Kilka modeli może leżeć na `/data` — **aktywny jest tylko jeden** w VRAM. Przełączenie = profil + restart kontenera. ```bash cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm # sprawdź co jest na dysku ./scripts/list-models.sh # pobierz drugi model (jeśli potrzeba) # ./scripts/download-model.sh # przełącz profil vLLM i zrestartuj ./scripts/switch-model.sh qwen3.6-27b-awq-128k ``` Nowy profil: skopiuj `profiles/_template.env`, dostosuj `VLLM_MODEL`, `QUANTIZATION`, `VLLM_EXTRA_ARGS`. `start.sh` **odrzuca** `.gguf` w `VLLM_MODEL` — GGUF wymaga przyszłego `stacks/llamacpp/`. Sprawdź miejsce przed większym modelem: ```bash df -h /data du -sh /data/apps/vllm/huggingface ``` --- ## 14. Zarządzanie stackiem ```bash cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm docker compose --profile vllm ps docker compose --profile vllm logs -f vllm docker compose --profile vllm restart vllm docker compose --profile vllm down ``` --- ## 15. Weryfikacja ### Checklist — cały rozdział 04 **Dysk:** - [ ] `/data` ~1 TB zamontowany (fstab) - [ ] `Docker Root Dir: /data/docker` **vLLM:** - [ ] `.env` z ustawionym `VLLM_MODEL` - [ ] `docker compose --profile vllm ps` — `vllm` running - [ ] `nvidia-smi` — proces vLLM, VRAM w użyciu - [ ] `curl http://localhost:8000/v1/models` — JSON z modelem - [ ] `curl .../v1/chat/completions` — odpowiedź tekstowa - [ ] Model na `/data/apps/vllm/huggingface` ### Szybki test końcowy ```bash df -h / /data docker info | grep "Docker Root Dir" curl -s http://localhost:8000/v1/models | jq . du -sh /data/apps/vllm/huggingface /data/docker ``` --- ## 16. Troubleshooting ### 16.1 `/data` nie montuje się po reboot ```bash sudo mount -a cat /etc/fstab ``` ### 16.2 `VLLM_MODEL is empty` lub `.gguf` rejected ```bash ./scripts/list-models.sh ./scripts/download-model.sh qwen3.6-27b-awq-vllm ./scripts/switch-model.sh qwen3.6-27b-awq-128k ``` Jeśli wpisałeś ścieżkę `.gguf` — użyj AWQ (vLLM) lub poczekaj na stack llama.cpp. ### 16.3 OOM na GPU (CUDA out of memory) Zobacz sekcję 12 (tuning). Typowy zestaw na start po OOM: ```env MAX_MODEL_LEN=65536 GPU_MEMORY_UTILIZATION=0.90 KV_CACHE_DTYPE=fp8 ``` ### 16.4 Błąd kwantyzacji AWQ Upewnij się, że model ma suffix `-AWQ` i `QUANTIZATION=awq` w `.env`. ### 16.5 `connection refused` na :8000 Model jeszcze się ładuje — `docker compose --profile vllm logs -f vllm`. ### 16.6 Wolny pierwszy prefill przy długim kontekście Normalne przy 128K — pierwsze żądanie z długim promptem trwa dłużej. ### 16.7 Brak miejsca na `/data` ```bash df -h /data docker system df ``` --- ## 17. Czego nie robimy w tym kroku | Element | Gdzie | |---------|-------| | ComfyUI | Rozdział 06 | | LocalAI (UI + GGUF) | Rozdział 05 | | Open WebUI (panel do vLLM) | później, opcjonalnie | | Pełny Docker llama.cpp / GGUF | placeholder: [`stacks/llamacpp/`](../stacks/llamacpp/) — LocalAI może obsłużyć GGUF | | Context 262K | start 128K; tuning później | | Firewall | Rozdział 07 | --- ## 18. Następny krok Po przejściu checklisty z sekcji 15: 1. Zgłoś w rozmowie z Cursorem, że krok 04 jest gotowy. 2. Przejdź do rozdziału **05 — LocalAI stack** ([`05-localai-stack.md`](05-localai-stack.md)). --- ## Podsumowanie wykonanych zmian Po ukończeniu tego rozdziału: - Dysk 1 TB: `/data` (Docker + modele) - Stack vLLM gotowy bez domyślnego modelu - Katalog modeli (`models.catalog.yaml`) + skrypty list/download/switch - Po wyborze: Qwen3.6-27B AWQ (interim Q4), kontekst 128K, KV cache fp8 - GGUF lmstudio — ścieżki na `/data/apps/gguf/`, host llama.cpp planowany - API OpenAI na porcie 8000