Turn any gaming laptop into a headless AI + rendering server — controlled from a thin-client laptop over LAN or the internet.
A two-machine portable AI lab you can pack in a backpack:
| Role | Machine | GPU |
|---|---|---|
| 🖥️ GPU Host (headless server) | Acer Predator Desktop.home |
NVIDIA RTX 3050 Ti Laptop (4 GB VRAM) |
| 💻 Control Client (thin client) | Dell Precision 3560 | NVIDIA T500 (2 GB) + Intel Iris Xe |
The GPU box runs headless services; the laptop is a thin client that drives them over fast LAN or Tailscale. This repo documents the full setup and ships the scripts that make it reproducible on any similar pair of machines.
💡 Got a gaming laptop collecting dust? It can be your personal AI server while your work laptop stays lightweight.
- Local LLM inference — run Llama 3, Mistral, Phi-3 locally; no cloud API bills
- CUDA notebooks — full PyTorch + CUDA environment, accessible from any browser on your network
- GPU-accelerated Blender rendering — OptiX rendering streamed via Moonlight
- Zero cloud dependency — everything runs on hardware you own
- Reproducible — scripts + docs mean you can rebuild from scratch in under an hour
Dell Precision 3560 (client) Acer Predator "Desktop.home" (GPU host)
├─ NVIDIA T500 (2 GB) + Intel Iris Xe ├─ NVIDIA RTX 3050 Ti Laptop (4 GB) + Intel iGPU
├─ Moonlight ──────── stream ──────────▶ ├─ Sunshine :47990
├─ ollama CLI ──────── HTTP ───────────▶ ├─ Ollama :11434
├─ Browser ──────── HTTP ───────────▶ ├─ JupyterLab :8888
├─ ssh ──────── SSH ───────────▶ ├─ OpenSSH :22
└─ Z: drive ──────── SMB ───────────▶ └─ SMB share "Portable RTX Compute"
The host is reached as Desktop.home. Its LAN IP is DHCP-assigned (a DHCP reservation is recommended); Desktop.local (mDNS) also resolves on the same network.
For remote access over the internet, see docs/REMOTE-ACCESS.md (Tailscale + WireGuard guide).
| Service | Endpoint | Notes |
|---|---|---|
| Ollama | http://Desktop.home:11434 |
Set OLLAMA_HOST on the client, use ollama CLI |
| JupyterLab | http://Desktop.home:8888 |
PyTorch/CUDA notebooks — see security note |
| SSH | ssh <user>@Desktop.home |
Key-based auth (see docs/SETUP.md) |
| Sunshine | https://Desktop.home:47990 |
Pair a Moonlight client against it |
| SMB | \\Desktop.home\Portable RTX Compute |
Shared notebooks/scripts |
| Package | Version |
|---|---|
| CUDA | 12.x |
| PyTorch | 2.11.0+cu128 |
| JupyterLab | 4.x |
| Ollama | 0.31.1 |
| Blender | 5.1.2 (GPU / OptiX rendering) |
| Sunshine | latest (desktop streaming to Moonlight) |
Verified on the live setup — see docs/GPU-VERIFICATION.md for full evidence.
| Channel | Runs on RTX? | Detail |
|---|---|---|
| PyTorch / Jupyter | ✅ Fully | torch.cuda → RTX 3050 Ti |
| Ollama (LLM) | ✅ If model fits 4 GB | Big models spill to CPU; use a ≤~3.5 GB model or force full offload |
| Moonlight streaming | RTX renders; video encode is Intel QuickSync (muxless Optimus — NVENC unavailable) | |
| Dell local (T500) | n/a (not an RTX) | T500 is the Dell's own dGPU; force via Windows "High performance" |
Key constraint: the RTX 3050 Ti Laptop GPU has only 4 GB VRAM. Keep Ollama models under ~3.5 GB to run 100% on GPU. This repo ships a full-offload Modelfile (scripts/host/llama3.2-3b-gpu.Modelfile).
# Clone this repo
git clone https://github.com/eli-labz/Portable-RTX-Compute-Node.git
cd Portable-RTX-Compute-Node
# Start services
scripts\host\Start-JupyterLab.bat # Launch JupyterLab on :8888
scripts\host\Pull-AI-Models.bat # Pull recommended Ollama models
# (Optional) Auto-start Ollama silently at logon
scripts\host\ollama-serve-hidden.vbsFollow docs/SETUP.md to:
- Add the
Desktop.homehosts entry - Install an SSH key and configure
~/.ssh/configusing scripts/client/ssh-config.template - Set
OLLAMA_HOST=http://Desktop.home:11434 - Map the SMB share as
Z: - Pair Moonlight with Sunshine
# On the host — watch utilisation climb
nvidia-smi -l 1
# From the client — quick Python check over SSH
ssh Desktop.home "python -c \"import torch; print(torch.cuda.get_device_name(0))\""Full verification steps: docs/GPU-VERIFICATION.md
Portable-RTX-Compute-Node/
├── docs/
│ ├── SETUP.md # End-to-end setup walkthrough
│ ├── GPU-VERIFICATION.md # How to confirm the RTX is doing the work
│ └── REMOTE-ACCESS.md # Tailscale / WireGuard remote access guide
├── scripts/
│ ├── host/
│ │ ├── Start-JupyterLab.bat # Launch JupyterLab server
│ │ ├── Pull-AI-Models.bat # Pull Ollama models
│ │ ├── ollama-serve-hidden.vbs # Silent background Ollama at logon
│ │ ├── check-gpu-health.ps1 # GPU health + VRAM dashboard
│ │ └── llama3.2-3b-gpu.Modelfile # Llama 3.2 3B pinned to GPU offload
│ └── client/
│ ├── ssh-config.template # Drop-in SSH config for the client
│ └── connect-node.ps1 # One-click connection helper
├── CONTRIBUTING.md
├── .gitignore
├── LICENSE
└── README.md
This architecture is not specific to the Acer + Dell combination. Any two machines where one has a discrete NVIDIA GPU works:
- GPU host — any Windows machine with an RTX GPU and a wired or fast wireless LAN connection
- Client — any laptop/desktop capable of running Moonlight, SSH, and a browser
- Swap hostnames in
docs/SETUP.mdand the SSH config template; everything else is identical
- JupyterLab requires token authentication. The token is set in the host's local
~/.jupyter/jupyter_server_config.py(IdentityProvider.token) — it is not stored on the SMB share or in this repo. The launcher no longer disables auth. See docs/SETUP.md to set or rotate it. - Never commit secrets. SSH private keys,
sunshine_state.json(contains the salted web-UI password hash), and.envfiles are excluded via.gitignore. Keep it that way. - SMB share is LAN-only by default. Do not expose port 445 to the internet.
Issues, corrections, and improvements welcome — see CONTRIBUTING.md.
If this saved you time, consider giving it a ⭐ — it helps others find it.
Apache 2.0 © eli-labz