359afb3a59
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>
150 lines
4.8 KiB
Markdown
150 lines
4.8 KiB
Markdown
# Control plane — jeden plik `.env`
|
|
|
|
**Data:** 2026-07-05
|
|
**Status:** wdrożone
|
|
|
|
gpu-fan (agent NVML) i Server UI (panel stacków) używają **jednego** pliku credentials.
|
|
|
|
## Kanoniczne ścieżki
|
|
|
|
| Środowisko | Plik |
|
|
|------------|------|
|
|
| Produkcja (systemd) | `/opt/control-plane/.env` |
|
|
| Dev w repo | `stacks/control-plane/.env` |
|
|
| Szablon | `stacks/control-plane/.env.example` |
|
|
|
|
Oba serwisy systemd:
|
|
|
|
```ini
|
|
EnvironmentFile=-/opt/control-plane/.env
|
|
```
|
|
|
|
- `server-ui.service`
|
|
- `gpu-fan.service`
|
|
|
|
## Zmienne
|
|
|
|
| Zmienna | Opis |
|
|
|---------|------|
|
|
| `API_KEY` | **Wspólny** klucz: auth panelu Server UI (`X-API-Key`) + auth agenta gpu-fan (proxy `/api/gpu-fan/*`) |
|
|
| `SERVER_UI_HOST`, `SERVER_UI_PORT` | Bind Server UI (domyślnie `0.0.0.0:8091`) |
|
|
| `REPO_ROOT` | Ścieżka do `ubuntu-bare-metal` (wymagane dla Docker Server UI) |
|
|
| `DOCKER_GID` | GID grupy docker (Docker install) |
|
|
| `GPU_FAN_AGENT_URL` | URL agenta z perspektywy Server UI (`http://127.0.0.1:18090` native, `http://host.docker.internal:18090` Docker) |
|
|
| `GPU_FAN_API_HOST`, `GPU_FAN_API_PORT` | Bind agenta gpu-fan (domyślnie `127.0.0.1:18090`) |
|
|
| `CURVE_PATH`, `POLL_INTERVAL`, `GPU_INDEX` | Konfiguracja NVML / krzywej wentylatorów |
|
|
|
|
**Usunięte:** `GPU_FAN_AGENT_KEY` — duplikat `API_KEY`.
|
|
|
|
## Ładowanie w Pythonie
|
|
|
|
[`stacks/control-plane/env_loader.py`](../stacks/control-plane/env_loader.py) — `load_control_plane_env(stack_dir)`:
|
|
|
|
**Produkcja** (`stack_dir` pod `/opt/`): tylko `/opt/control-plane/.env` + `os.environ` (systemd).
|
|
|
|
**Dev** (repo `stacks/*`): tylko `stacks/control-plane/.env` + `os.environ`.
|
|
|
|
**Nie ładowane:** `stacks/server-ui/.env`, `/opt/server-ui/.env` (legacy — `API_KEY` usuwany przez `setup-control-plane-env.sh`).
|
|
|
|
Kolejność priorytetu: pliki env → **`os.environ` wygrywa** (systemd `EnvironmentFile`).
|
|
|
|
`api_key_source(stack_dir, values)` — log przy starcie Server UI (bez ujawniania sekretu).
|
|
|
|
Produkcja: `env_loader.py` kopiowany do `/opt/control-plane/env_loader.py` przez `setup-control-plane-env.sh`.
|
|
|
|
## Instalacja / migracja
|
|
|
|
```bash
|
|
sudo bash stacks/server-ui/scripts/setup-control-plane-env.sh
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl restart gpu-fan server-ui
|
|
```
|
|
|
|
Skrypt:
|
|
|
|
- tworzy `/opt/control-plane/.env` z example jeśli brak
|
|
- **migruje** z `/opt/server-ui/.env` i `/opt/gpu-fan/.env` (backup `.env.bak.<timestamp>`)
|
|
- generuje `API_KEY` jeśli brak lub `change-me`
|
|
- **sync** `stacks/control-plane/.env` z produkcją (ten sam `API_KEY`)
|
|
- **usuwa** `API_KEY` / `GPU_FAN_AGENT_KEY` z legacy `stacks/server-ui/.env`
|
|
- wypisuje gotowy URL z kluczem (`print-api-key-instructions.sh`)
|
|
|
|
Instrukcja dla użytkownika po instalacji:
|
|
|
|
```bash
|
|
bash stacks/server-ui/scripts/show-api-key.sh
|
|
```
|
|
|
|
Pełna instalacja:
|
|
|
|
```bash
|
|
sudo bash stacks/server-ui/scripts/install-control-plane.sh
|
|
```
|
|
|
|
## Weryfikacja
|
|
|
|
```bash
|
|
bash stacks/server-ui/scripts/show-api-key.sh
|
|
|
|
API_KEY=$(sudo grep ^API_KEY= /opt/control-plane/.env | cut -d= -f2)
|
|
|
|
# Test klucza w panelu
|
|
curl -s -X POST http://127.0.0.1:8091/api/auth/verify \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"api_key\":\"${API_KEY}\"}"
|
|
|
|
# Agent bezpośrednio
|
|
curl -s http://127.0.0.1:18090/api/status -H "X-API-Key: ${API_KEY}"
|
|
|
|
# Proxy przez Server UI
|
|
curl -s http://127.0.0.1:8091/api/gpu-fan/health -H "X-API-Key: ${API_KEY}"
|
|
```
|
|
|
|
Oczekiwane: JSON z danymi / `"ok": true`.
|
|
|
|
## Docker Server UI
|
|
|
|
[`stacks/server-ui/docker-compose.yml`](../stacks/server-ui/docker-compose.yml):
|
|
|
|
```yaml
|
|
env_file:
|
|
- ../control-plane/.env
|
|
```
|
|
|
|
## Auth flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Browser
|
|
participant ServerUI
|
|
participant GpuFanAgent
|
|
Browser->>ServerUI: X-API-Key: API_KEY
|
|
ServerUI->>GpuFanAgent: X-API-Key: API_KEY (ten sam)
|
|
GpuFanAgent-->>ServerUI: status JSON
|
|
ServerUI-->>Browser: proxy response
|
|
```
|
|
|
|
## Poza scope
|
|
|
|
Sekrety workloadów Docker (`LOCALAI_API_KEY`, `HF_TOKEN`, `INITIAL_ADMIN_PASSWORD`, …) pozostają w `stacks/<nazwa>/.env` — edycja portów przez Server UI bez zmian.
|
|
|
|
## Pliki zmienione (implementacja)
|
|
|
|
- `stacks/control-plane/` — `.env.example`, `env_loader.py`
|
|
- `stacks/server-ui/scripts/setup-control-plane-env.sh`
|
|
- `server-ui.service`, `gpu-fan.service`
|
|
- `server-ui/app.py`, `gpu_fan_proxy.py`, `gpu-fan/fan_daemon.py`, `gpu-fan/app.py`
|
|
- Instalatory: `install-control-plane.sh`, `install.sh`, `install-docker.sh`, `gpu-fan/install.sh`
|
|
- Skrypty dev: `start.sh`, `deploy-gpu-fan-fix.sh`, `restart-stack.sh`, `enable-lan.sh`, `status.sh`
|
|
|
|
## Troubleshooting — Invalid API key
|
|
|
|
1. Klucz tylko z `/opt/control-plane/.env` (`sudo grep ^API_KEY= …`)
|
|
2. UI: **Zapisz** → **Sprawdź klucz**
|
|
3. Sync: `sudo bash stacks/server-ui/scripts/setup-control-plane-env.sh`
|
|
4. Tutorial: [`manual-tutorial/04a-api-key.md`](../manual-tutorial/04a-api-key.md)
|
|
|
|
## Legacy
|
|
|
|
Stare pliki `/opt/server-ui/.env` i `/opt/gpu-fan/.env` nie są już czytane przez systemd. Po migracji można je usunąć (backup w `.env.bak.*`).
|