- Hardware context
- Services
- Management tool
- Usage
- Operations
- Why lazy-loading + manual control
- Thunderbolt Hot-Unplug Caveat
Whisper, RAG and Qwen3-TTS share the same 8 GB GPU. Use gpu-service to
start, stop and switch between them.
- GPU: NVIDIA RTX 2070 Super 8GB (via eGPU, USB-C/Thunderbolt)
- Total VRAM: 8192 MiB
- Run one GPU service at a time.
VRAM usage per service (approximate):
- Whisper (transcription + diarization): ~3.5 GB
- RAG library (embeddings + reranker): ~1.2 GB
- Qwen3-TTS 1.7B (voice cloning): ~4.3 GB
Combined: ~9 GB → exceeds 8 GB VRAM
GPU service behavior:
-
whisper-web.service(port 8060,/whisperendpoint)- Auto-loading: Frontend always active, GPU model loads on first job
- Auto-unloads after 120 seconds of inactivity
- Auto-starts on boot
-
qwen3-tts.service(port 8070,/ttsendpoint)- Auto-loading: Frontend always active, GPU model loads on first job
- Auto-unloads after 120 seconds of inactivity
- Auto-starts on boot
-
rag-library-ingest.service(SFTP inbox watcher)- Manual control: Must be started/stopped manually with
gpu-service - Does not start at boot
- Runs continuously when active (no auto-unload)
- Manual control: Must be started/stopped manually with
Whisper and TTS queue jobs and process them sequentially.
/usr/local/bin/gpu-service — CLI tool for monitoring and manual control
gpu-service statusOutput:
- Service states (active/inactive)
- GPU memory usage per process
- Total VRAM used/available
gpu-service start whisper
gpu-service start rag
gpu-service start ttsStart one GPU service at a time.
gpu-service stop whisper
gpu-service stop rag
gpu-service stop ttsStop all:
gpu-service stop allTo switch from one GPU service to another:
gpu-service stop whisper
gpu-service start ttsWait 2-3 seconds between stop and start for VRAM cleanup.
Transcription job (automatic):
- Navigate to
https://beachlab.org/whisper/ - Upload audio and submit job
- GPU model loads automatically (first job may take 10-20s)
- Wait for job to complete
- Download transcript
- Model auto-unloads after 2 minutes of inactivity
Voice cloning (automatic):
- Navigate to
https://beachlab.org/tts/ - Upload reference audio + enter text
- GPU model loads automatically (first job may take 10-20s)
- Wait for generation to complete
- Download wav file
- Model auto-unloads after 2 minutes of inactivity
eBook indexing (manual):
- Check GPU status:
gpu-service status - If Whisper/TTS are idle, proceed. If not, wait or use
gpu-service stop all gpu-service start rag- Upload PDFs/EPUBs via SFTP to
/home/sftpuser/library_inbox - Monitor logs:
journalctl -u rag-library-ingest -f gpu-service stop rag(when inbox is empty)
Automatic (Whisper/TTS):
If you submit a job and GPU memory is full:
- Job will be marked as
failed - Error message: "GPU memory full. Please stop other GPU services (gpu-service stop all) and try again."
- Check
gpu-service statusto see what's using VRAM - Stop conflicting service or wait for auto-unload (120s idle)
Manual (RAG):
Before starting RAG, check for conflicts:
gpu-service statusIf Whisper or TTS are using GPU:
- Wait for auto-unload (check logs for "unloading model" message)
- Or force stop:
gpu-service stop all
Then start RAG:
gpu-service start ragsudo systemctl stop whisper-web rag-library-ingest qwen3-ttsOr kill GPU processes directly (last resort):
sudo pkill -9 -f "whisper-service|rag-library|qwen3-tts"The card has 8 GB of VRAM. Run one service at a time. Whisper and TTS load their models for a job and unload them after 120 seconds idle. RAG keeps processing its inbox until I stop it.
These August 2026 notes describe host hangs during long eGPU sessions. The original logs are missing, so they do not establish the cause.
| Evidence | What it shows |
|---|---|
Heartbeat gaps with bolt=authorized ending in unclean reboot |
Hard hang / forced restart, not systemctl reboot |
| 2026-08-04 ~19:00 UTC → boot ~20:13 | ~12 h continuous attach, then silence (~73 min journal gap) |
| 2026-08-05 ~19:33 UTC → boot ~20:30 | ~22 h continuous attach, then silence (~57 min journal gap); load/RAM healthy minutes before |
| Weekly ~05:00 reboots with Core X off | Clean multi-day uptime without eGPU |
No systemctl reboot in auth.log on those hang days |
Not intentional software reboot |
The working assumption is that long-lived Thunderbolt/PCIe
attachment of the Core X on this NUC+Linux stack is unsafe. Failures are not
limited to heavy CUDA jobs; idle attach for half a day has been enough. Full
“always-on eGPU” on this host is not a reliable goal with the current
NUC11TNKi3 + Razer Core X + Ubuntu 22.04 HWE 6.8 path. Industry reports of
similar TB3 eGPU Xid 79 / bus-loss failures on Linux are common; see
NVIDIA forum Core X Xid 79.
- Cold start with Core X on (preferred): power off NUC → power Core X → TB cable seated → wait a few seconds → power on NUC.
- Confirm GPU:
egpu-session statusornvidia-smi. - Open a session:
egpu-session start "whisper batch". - Run jobs (Whisper / TTS / ComfyUI / RAG). Prefer finishing within ~6 hours.
- End cleanly:
Or:
egpu-session end # power OFF Core X (do not hot-unplug TB while NUC is up) sudo systemctl rebootegpu-session end --rebootafter powering the enclosure off first if you accept an immediate reboot.
| Path | Role |
|---|---|
/usr/local/bin/egpu-session |
status / start / end / doctor |
/usr/local/bin/egpu-watchdog.sh |
loss recovery + max-age iGotify (warn 6 h, critical 10 h) |
/etc/egpu-watchdog.env |
EGPU_WARN_S=21600, EGPU_CRITICAL_S=36000 |
| Repo copies | scripts/egpu/egpu-session.sh, scripts/egpu/egpu-watchdog.sh |
The scripts matched the host copies on 2026-09-10. The thresholds live in
/etc/egpu-watchdog.env; that comparison did not test recovery from a hang.
The recovered egpu-session script sources its state as shell code and does not
quote notes containing spaces when saving them; treat this as a known limitation
of the deployed snapshot, not a validated state-file interface.
Watchdog still skips auto-recovery when boltctl says disconnected (Core X
intentionally off). It cannot prevent a hard freeze once the kernel stops
scheduling; max-age alerts exist so you tear down before that window.
Observed on thebeachlab (NUC11TNKi3 + Razer Core X + RTX 2070 SUPER, June 2026):
- Normal boot with eGPU attached works
boltctlshowsRazer Core Xasauthorizednvidia-smiworks- GPU services (
comfyui,qwen3-tts,whisper-web) can use the card normally
What breaks it reliably:
- Unplugging the Thunderbolt cable while the eGPU is live
- Reconnecting the cable in the same runtime session
- Leaving the Core X authorized for many hours (including idle)
What Linux reports when it breaks (when logs flush):
thunderbolt 0-3: device disconnected
pcieport 0000:00:07.0: pciehp: Slot(0): Link Down
NVRM: Xid (PCI:0000:04:00): 79, GPU has fallen off the bus.
NVRM: Xid (PCI:0000:04:00): 154, GPU recovery action changed ... GPU Reset Required
Hard freezes often leave no final Xid line because the journal never flushes.
Typical broken-state symptoms after reconnect:
- Core X light comes back on
boltctlmay return toauthorizedlspcimay still list the NVIDIA device, sometimes asrev ffnvidia-smifails withNo devices were found- Server fan can ramp hard during the failure window
Operational rules:
- Do not hot-unplug or hot-replug the Thunderbolt cable while the NUC is up
- Treat the eGPU cable as effectively non-hot-swappable for production use
- Do not leave Core X powered for multi-day always-on; use sessions
Recovery:
- Stop touching the Thunderbolt cable
- Reboot the host (hard power if frozen)
- Re-check:
boltctl list
lspci | grep -i nvidia
nvidia-smi
egpu-session statusIf the reboot path does not recover cleanly, escalate to full power-off / power-on of NUC and Core X (see Razer power-cycle notes in gpu.md).
Notes from local testing:
- Updating BIOS from
0073to0078improved overall stability but did not make hot-unplug safe pcie_port_pm=offis kept as part of the stable baseline- On 2026-07-18,
pcie_aspm=offwas added alongside it after confirming that both Thunderbolt root ports still had ASPM L1 enabled. GRUB was regenerated and validated; a cold boot with the Core X connected is required to activate and verify the change - Pre-change GRUB backup:
/etc/default/grub.pre-aspm-20260718 - GSP firmware disabled via
/etc/modprobe.d/nvidia-no-gsp.conf(NVreg_EnableGpuFirmware=0) - The issue matches known Linux/NVIDIA/Thunderbolt reports around
Xid 79and "fallen off the bus" - The old 1500 MHz cap was no longer active on 2026-10-13. See GPU clocks.
These are planned A/B tests from gpu.md, not done yet:
- Same workload on kernel
6.8.0-134-genericvs default6.8.0-136(NVIDIA held at 595.84). - Only if kernels both hang: controlled NVIDIA
595.71.05rollback with matched packages. - Physical: alternate TB port + known-good short certified cable (≤60 cm).
Do not expect a pure software patch to make always-on Core X safe until an A/B test proves a regression and a rollback holds under continuous attach.
Historical context: The Razer Core X PSU died on 2026-03-04, so GPU services were disabled for a while to avoid continuous errors and freezes.
| Service | State |
|---|---|
whisper-web |
enabled + active |
qwen3-tts |
enabled + active |
comfyui |
enabled + active |
nvidia-persistenced |
enabled + active |
egpu-watchdog.timer |
enabled + active |
Telegraf inputs.nvidia_smi |
enabled |
Current runtime after restore:
- eGPU:
Razer Core Xauthorized via Thunderbolt - GPU:
NVIDIA GeForce RTX 2070 SUPER - Driver:
595.71.05 nvidia-smi: OK- Persistence mode: ON
1. Prefer cold boot, not hot-plug:
- Power off host
- Connect/power the Razer Core X
- Wait 5-10 seconds
- Boot host
2. Verify the GPU is visible:
boltctl
lspci | grep -i nvidia
nvidia-smiIf nvidia-smi fails, try:
sudo modprobe nvidia
nvidia-smi3. Re-enable GPU services if they were disabled:
sudo systemctl enable --now nvidia-persistenced
sudo systemctl enable --now whisper-web
sudo systemctl enable --now qwen3-tts
sudo systemctl enable --now comfyui
sudo systemctl enable --now egpu-watchdog.timer4. Re-enable Telegraf monitoring if needed:
Ensure /etc/telegraf/telegraf.d/nuc-timescale.conf contains:
[[inputs.nvidia_smi]]
bin_path = "/usr/local/bin/nvidia-smi-safe.sh"
timeout = "5s"Then:
sudo systemctl restart telegraf
sudo journalctl -u telegraf -n 10 --no-pager | grep -E "Error|nvidia"5. Verify watchdog + heartbeat instrumentation:
systemctl status egpu-watchdog.timer host-heartbeat-log.timer --no-pager
tail -n 20 /var/log/host-heartbeat.logExpected behavior:
- one alert when the eGPU is lost
- one alert when it recovers
- no repeating half-hour alerts while it remains missing
- heartbeat log includes explicit transition lines such as:
event=egpu_lost last_ok=2026-06-15T05:03:29Z detected_at=2026-06-15T05:04:33Z
event=egpu_recovered missing_since=2026-06-15T05:04:33Z detected_at=2026-06-15T05:18:12Z
6. Verify telemetry:
DRY_RUN=true bash /home/pink/.openclaw/workspace/scripts/publish_telemetry.sh | python3 -m json.tool | grep gpuThe gpu field should show real temp/util values instead of null.
7. Quick service test:
curl -I http://localhost:8060/ # whisper-web
curl -I http://localhost:8070/ # qwen3-tts
curl -I http://localhost:8188/ # comfyui
curl http://localhost:8060/openapi.json | jq '.info'
curl http://localhost:8070/openapi.json | jq '.info'Note: whisper-web and qwen3-tts do not expose /health; use /, /docs, or /openapi.json instead.
journalctl -k -b | grep -iE 'NVRM|Xid|nvidia|thunderbolt|bolt'On the 2026-06-10 restore there were no Xid errors after boot. Only one benign-looking line appeared during bring-up:
nvidia-gpu 0000:04:00.3: i2c timeout error e0000000