Engineering Case Study - AI Infrastructure

Building a Local AI Infrastructure Platform

This was not simply an AI installation project. It was an infrastructure engineering effort involving architecture decisions, operational troubleshooting, platform validation, recovery planning, and the creation of a repeatable AI infrastructure baseline.

Validated Stack Operational
  • VirtualizationProxmox
  • GPURTX 3090
  • DriverNVIDIA 595.80
  • RuntimeCUDA 13.2
  • ContainerLXC
  • InterfaceOpen WebUI
  • ServingOllama
  • Validated ModelGPT-OSS 20B

Operating Objective

Build a controlled local AI platform that could be validated, recovered, documented, and extended.

Engineering Scope

The project combined infrastructure operations, GPU platform validation, Linux administration, AI runtime integration, documentation, and recovery planning. The success criterion was a trustworthy platform state, not just a working demo.

Final Result

The rebuilt environment successfully hosted and executed Qwen 7B, Qwen 14B, and GPT-OSS 20B with GPU acceleration, then established a recoverable baseline through snapshots, NAS backups, and GitHub documentation.

Executive Context

The business value was creating a trustworthy platform state, not just getting a model to answer.

Business Problem

Platform confidence had dropped

GPU driver conflicts, runtime failures, and accumulated troubleshooting changes made the AI platform hard to trust as a baseline for future work.

Decision Made

Rebuild from a clean baseline

Rebuild on Proxmox, resolve GPU ownership issues, validate NVIDIA/CUDA/Open WebUI/Ollama/model execution, then protect the working state.

Outcome

Recoverable AI platform baseline

Established a validated local AI platform with RTX 3090 acceleration, model execution, documentation, snapshots, and NAS backup.

Risk Reduced

Less drift and recovery uncertainty

Reduced platform drift, GPU/runtime troubleshooting risk, and uncertainty around whether the environment could be restored or repeated.

Operating Improvement

From demo to managed infrastructure

Added root cause analysis, validation steps, documentation, snapshots, backups, benchmarking, and observability work around the AI platform.

Architecture Overview

The platform separates infrastructure, GPU enablement, runtime services, application access, and model validation into clear operating layers.

Infrastructure LayerProxmox host, storage, network, NAS backup path
Virtualization LayerLXC container boundary and platform control
GPU LayerRTX 3090, NVIDIA 595.80, driver ownership validation
Runtime LayerCUDA 13.2 and Ollama model serving
Application LayerOpen WebUI user access and workflow validation
Model LayerQwen models and GPT-OSS 20B execution
Architecture Diagram Planned Physical topology, GPU path, container boundary, runtime services, recovery flow
Local AI infrastructure platform architecture overview diagram
Figure 1 - Local AI Infrastructure Platform Architecture Overview
Validated Logical Flow
  1. Proxmox
  2. RTX 3090
  3. NVIDIA 595.80
  4. CUDA 13.2
  5. LXC Container
  6. Open WebUI
  7. Ollama
  8. Qwen Models
  9. GPT-OSS 20B
Runtime Diagram Planned Runtime request path and model validation sequence

Engineering Timeline

The build progressed from initial deployment through driver investigation, rebuild, validation, recovery, and portfolio integration.

  1. 01Initial AI Platform Deployment
  2. 02GPU Validation Challenges
  3. 03VFIO Investigation
  4. 04Ollama Runtime Failures
  5. 05Platform State Confidence Review
  6. 06Decision to Rebuild
  7. 07Fresh Proxmox Deployment
  8. 08NovaCore Conflict Discovery
  9. 09NVIDIA 595.80 Installation
  10. 10CUDA 13.2 Validation
  11. 11Open WebUI Validation
  12. 12Ollama Validation
  13. 13Qwen Model Validation
  14. 14GPT-OSS 20B Validation
  15. 15Snapshot Creation
  16. 16NAS Backup Creation
  17. 17GitHub Documentation
  18. 18Portfolio Integration

Key Decisions

The project hinged on engineering judgment: when to keep troubleshooting, when to challenge assumptions, and when to protect the validated state.

Decision 1

Continue troubleshooting versus rebuild from a trusted baseline

Outcome: Fresh rebuild selected.

Reason: Confidence in platform state had become too low.

Decision 2

Assume AI runtime issue versus validate GPU ownership

Outcome: NovaCore conflict identified.

Reason: Root cause analysis revealed a driver ownership conflict.

Decision 3

Move on after validation versus establish recovery strategy

Outcome: Snapshot and NAS backup created.

Reason: A stable platform is only valuable if it can be recovered.

Root Cause Analysis

The investigation treated runtime failures as symptoms of a deeper platform state and GPU ownership problem.

01

VFIO Investigation

GPU behavior was reviewed at the host and passthrough layers to determine whether the device was being held by the wrong subsystem.

02

GPU Ownership Analysis

The RTX 3090 needed a clear ownership path before CUDA and model execution could be trusted.

03

NovaCore Conflict Discovery

A conflicting driver stack involving NovaCore was identified as a blocker for clean NVIDIA driver attachment.

04

Driver Attachment Issues

NVIDIA installation failures and inconsistent module behavior were traced back to the underlying ownership conflict.

05

Platform State Drift

Accumulated troubleshooting changes reduced confidence in the environment, making a clean rebuild the stronger engineering path.

Key Outcomes Dashboard

The final platform state was validated across compute, driver, runtime, application, models, and recovery controls.

OperationalRTX 3090 Infrastructure
OperationalNVIDIA 595.80
OperationalCUDA 13.2
OperationalOpen WebUI
OperationalOllama
ValidatedQwen 7B
ValidatedQwen 14B
ValidatedGPT-OSS 20B
RecoverySnapshot Strategy
RecoveryNAS Backup Strategy

Benchmarking & Observability

The project moved beyond running a local model into measuring runtime behavior under load.

The next phase of the lab added vLLM serving, Prometheus metrics, Grafana dashboards, and Locust load testing so the platform could be judged by throughput, latency, queue depth, and GPU behavior rather than a single successful response.

Benchmark results were captured using Locust, Prometheus, Grafana, and NVIDIA GPU telemetry while serving Qwen 2.5 7B through vLLM on an EVGA RTX 3090 FTW3 Ultra.

Test Users Generation Tokens/sec Prompt Tokens/sec Avg Latency P95 Latency Waiting Requests Failures
Baseline 1 ~33.07 ~6.58 ~4.18s ~4.20-4.88s 0 0
Concurrency Test 5 ~159.31 ~29.6 ~4.22s ~4.30-4.88s 0 0
Load Test 25 ~751.76 ~141 ~4.54s ~4.60-4.88s 0 0
Sustained Load Test 50 ~1439.93 ~262 ~4.76-4.92s ~4.89-5.0s 0 0

Understanding the Dashboard

Three layers: observability health, runtime behavior, and saturation signals.

The dashboard is meant to show whether the monitoring box is healthy, how the AI runtime is behaving, and whether requests are starting to queue.

Server Health

CT203 CPU Usage %

Shows whether Prometheus, Grafana, Node Exporter, and Locust are using enough CPU to become part of the benchmark problem.

Server Health

CT203 Memory Usage %

Shows whether the observability and load-testing container has enough RAM headroom during benchmark runs.

Server Health

CT203 Disk Usage %

Tracks local disk pressure on the observability server, which matters because Prometheus stores time-series data locally.

Throughput

Generation Tokens/sec

Measures output throughput: how many response tokens Qwen 2.5 7B generates per second.

Throughput

Prompt Tokens/sec

Measures input throughput: how many prompt tokens are processed before responses are generated.

Saturation

Requests Running

Shows active inference requests currently being processed by vLLM. It is the current concurrency view.

Saturation

Requests Waiting

Shows queued requests waiting for GPU/runtime resources. Zero means requests are not backing up.

User Experience

Average Request Latency

Shows average request completion time. It is one of the main user-facing performance metrics.

User Experience

P95 Request Latency

Shows the response time experienced by 95% of requests, which helps expose slow outliers.

Runtime Memory

KV Cache Usage %

Shows how much of the runtime's short-term memory workspace is being used. 0-30% is plenty of headroom, 30-70% is normal, 70-90% needs attention, and 90%+ can become bottleneck territory.

GPU Validation

RTX 3090 Runtime Validation

During the 50-user benchmark, the EVGA RTX 3090 FTW3 Ultra reached 100% utilization and 249W power draw while staying around 56 degrees C. VRAM usage was approximately 21.9GB out of 24GB. There were zero failed requests and zero queued requests.

Baseline Validation 1 User
Grafana Runtime Metrics
Locust Load Test Results

Initial baseline validation showing approximately 33 generation tokens/sec, stable latency, and zero failures.

Sustained Load Validation 50 Users
Grafana Runtime Metrics
Locust Load Test Results
NVIDIA GPU Validation

Sustained load test showing approximately 1440 generation tokens/sec, 100% GPU utilization, 249W power draw, and zero queued requests.

Implementation Notes

Dashboard v1.1 added host separation and custom GPU telemetry.

These notes document what was actually configured: the vLLM runtime command, Prometheus scrape targets, Node Exporter textfile collection, the GPU metrics script, and the systemd timer that keeps the dashboard current.

Runtime

vLLM startup command

CT202 serves Qwen/Qwen2.5-7B-Instruct through vLLM on port 8000.

source ~/vllm-env/bin/activate
vllm serve Qwen/Qwen2.5-7B-Instruct \
  --host 0.0.0.0 \
  --port 8000 \
  --tensor-parallel-size 1 \
  --gpu-memory-utilization 0.90 \
  --max-model-len 8192
Scraping

Prometheus scrape jobs

CT203 runs Prometheus and Grafana. Prometheus scrapes the vLLM metrics endpoint and the CT202 Node Exporter endpoint.

vLLM scrape target:
192.168.50.104:8000

CT202 node exporter scrape target:
192.168.50.104:9100
Node Exporter

Textfile collector

CT202 exposes custom GPU metrics by enabling the Node Exporter textfile collector.

/etc/default/prometheus-node-exporter
ARGS="--collector.textfile.directory=/var/lib/node_exporter/textfile_collector"
GPU Metrics

Custom exporter script

The gpu-metrics.sh script uses nvidia-smi and writes gpu.prom for Node Exporter. It collects utilization, temperature, power draw, and VRAM usage.

#!/usr/bin/env bash
set -euo pipefail

OUT="/var/lib/node_exporter/textfile_collector/gpu.prom"
TMP="${OUT}.$$"

read -r GPU_UTIL GPU_TEMP GPU_POWER GPU_MEM_USED < <(
  nvidia-smi --query-gpu=utilization.gpu,temperature.gpu,power.draw,memory.used \
    --format=csv,noheader,nounits | head -n 1 | tr -d ','
)

cat > "$TMP" <<EOF
# HELP gpu_utilization_percent GPU utilization percentage from nvidia-smi.
# TYPE gpu_utilization_percent gauge
gpu_utilization_percent $GPU_UTIL
# HELP gpu_temperature_celsius GPU temperature in Celsius from nvidia-smi.
# TYPE gpu_temperature_celsius gauge
gpu_temperature_celsius $GPU_TEMP
# HELP gpu_power_watts GPU power draw in watts from nvidia-smi.
# TYPE gpu_power_watts gauge
gpu_power_watts $GPU_POWER
# HELP gpu_memory_used_mb GPU memory used in MB from nvidia-smi.
# TYPE gpu_memory_used_mb gauge
gpu_memory_used_mb $GPU_MEM_USED
EOF

mv "$TMP" "$OUT"
Automation

systemd service and timer

gpu-metrics.service runs the exporter, and gpu-metrics.timer runs it every 15 seconds so Grafana has a current GPU view without Prometheus shelling out to nvidia-smi.

# gpu-metrics.service
[Unit]
Description=Collect NVIDIA GPU metrics for Node Exporter

[Service]
Type=oneshot
ExecStart=/usr/local/bin/gpu-metrics.sh

# gpu-metrics.timer
[Unit]
Description=Run GPU metrics collection every 15 seconds

[Timer]
OnBootSec=15s
OnUnitActiveSec=15s
Unit=gpu-metrics.service

[Install]
WantedBy=timers.target
Dashboard v1.1

Separated host and GPU views

The dashboard now separates CT203 observability host metrics from CT202 AI runtime host metrics. GPU panels include utilization, temperature, power draw, and VRAM usage.

With Qwen 2.5 7B loaded and idle/ready, the RTX 3090 showed about 21,996 MB of VRAM used.

Model Evaluation

Qwen3-14B-AWQ vLLM Evaluation

This test evaluated whether Qwen3-14B-AWQ could run reliably on a single RTX 3090 24GB using vLLM, Open WebUI, Prometheus, Grafana, and GPU telemetry.

Evaluation Goal

The goal was not just to get a model process running. The real check was whether the runtime, API, frontend, and telemetry stack could make the model usable and understandable on homelab hardware.

Current Status

Qwen3-14B-AWQ is successfully running under vLLM on the RTX 3090. Open WebUI can connect to it, API testing works, and Grafana captures GPU/runtime telemetry.

OOM Investigation

Qwen3-14B failed with CUDA out-of-memory

The non-quantized Qwen3-14B attempt failed when vLLM tried to allocate additional GPU memory while the RTX 3090 was already near full VRAM usage.

torch.OutOfMemoryError: CUDA out of memory
GPU had ~23.55 GiB total capacity
Only a small amount of VRAM was free

That confirmed full-precision or larger model loading was not practical on a single 24GB card without quantization or model parallelism.

Operational Takeaway

24GB VRAM is usable, but format matters

The RTX 3090 is still a very useful local AI card, but model format and quantization matter more than parameter count alone. The same class of model can fail or run depending on how it is packaged.

Quantization

Why Quantization Matters

Quantization reduces model weight precision, which lowers VRAM requirements. AWQ allowed the 14B model to fit where the non-quantized model failed.

The tradeoff is possible small quality loss, but the deployability improvement on consumer GPUs is huge. For homelab AI infrastructure, quantization turns "the model theoretically exists" into "the model actually runs."

Successful Runtime

Qwen/Qwen3-14B-AWQ served through vLLM

  • ModelQwen/Qwen3-14B-AWQ
  • RuntimevLLM 0.22.0
  • APIOpenAI-compatible :8000
  • FrontendOpen WebUI
  • GPURTX 3090 24GB

vLLM served /v1/models and /v1/chat/completions successfully. Open WebUI displayed and used the Qwen3-14B-AWQ model.

Validation Commands

Runtime, API, and telemetry checks

ps -ef | grep vllm
ss -tulpn | grep 8000
curl http://localhost:8000/health
curl http://localhost:8000/v1/models
nvidia-smi
cat /var/lib/node_exporter/textfile_collector/gpu.prom
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-14B-AWQ",
    "messages": [
      {
        "role": "user",
        "content": "Explain Terraform state locking in plain English."
      }
    ],
    "max_tokens": 200
  }'

3090 VRAM Utilization

Qwen3-14B-AWQ ran close to the card's practical VRAM ceiling.

Qwen3-14B-AWQ used roughly 20.9GB to 22GB of RTX 3090 VRAM while loaded. nvidia-smi showed around 20902MiB to 21996MiB used during testing. GPU power ranged from low idle values around 23W up to roughly 249W during active generation, utilization reached 100% during prompt generation, and temperature stayed reasonable at around 29C to 36C in the screenshots.

Grafana Observability

The dashboard connected model behavior to GPU pressure, latency, and request activity.

Grafana made it possible to correlate model behavior with GPU load, VRAM pressure, latency, and request activity instead of guessing from a terminal window.

HostCT202 CPU Usage %
HostCT202 Memory Usage %
HostCT202 Disk Usage %
ThroughputCurrent Model Prompt Tokens/sec
ThroughputCurrent Model Generation Tokens/sec
QueuevLLM num_requests_waiting
RuntimevLLM num_requests_running
LatencyP95 Request Latency
LatencyAverage Request Latency
GPURTX 3090 GPU Util %
GPURTX 3090 GPU Power (W)
GPURTX 3090 GPU Temp (C)
GPURTX 3090 VRAM Used (MB)
Runtime MemoryKV Cache Usage %

Architecture Diagram

Open WebUI talks to vLLM, vLLM runs the AWQ model, and Prometheus/Grafana watch the runtime.

Request Path
  1. Open WebUI
  2. vLLM OpenAI-compatible API :8000
  3. Qwen3-14B-AWQ
  4. RTX 3090 24GB
Prometheus ScrapesvLLM /metrics, Node exporter, GPU textfile collector
Grafana VisualizesRequest metrics, tokens/sec, latency, GPU utilization, power, temperature, and VRAM usage
Additional Evidence Planned Queued
Planned Image

qwen3-14b-awq-grafana.png

Final Grafana dashboard screenshot during a controlled Qwen3-14B-AWQ test.

Planned Image

qwen3-14b-awq-openwebui.png

Open WebUI showing the Qwen3-14B-AWQ model connected through the vLLM endpoint.

Planned Image

qwen3-14b-awq-nvidia-smi.png

nvidia-smi output showing RTX 3090 VRAM, utilization, power, and temperature during testing.

Model Comparison Notes

The AWQ model was the practical 14B path on a single RTX 3090.

Model Result Notes
Qwen3-14B non-quantized Failed CUDA OOM on a single RTX 3090
Qwen3-14B-AWQ Successful Successful on a single RTX 3090
Qwen2.5-7B-Instruct Successful baseline Lower VRAM, faster/smaller baseline
GPT-OSS 20B Not yet fully evaluated in vLLM Previously liked in Ollama; needs compatible vLLM model format review

Matt's Notes

Quantization was the difference between "almost fits" and "actually runs."

What surprised me

  • A 14B model can still fail on a 24GB RTX 3090 depending on format and precision.
  • The quantized AWQ version worked where the non-quantized version failed.
  • Grafana made the VRAM and GPU utilization story obvious.

What broke

  • The non-quantized Qwen3-14B run failed with CUDA out-of-memory.
  • The RTX 3090 had almost no free VRAM left during the failed load.
  • The first assumption that "14B should fit" was too simplistic.

What I learned

  • Quantization matters as much as parameter count.
  • AWQ can make larger models practical on consumer GPUs.
  • Observability is not optional when building local AI infrastructure.

What I would do differently

  • Check quantized model options first.
  • Capture nvidia-smi and Grafana screenshots during every test.
  • Compare models with the same prompts and load profile.
  • Treat VRAM like a budget, not a suggestion.

Current Status

Qwen3-14B-AWQ is successfully running under vLLM on the RTX 3090.

Open WebUI can connect to it, API testing works, and Grafana captures GPU/runtime telemetry. The non-quantized 14B model failed with CUDA OOM, making AWQ quantization the practical path for this GPU.

Next Steps

Turn the successful single-model test into a measured runtime comparison.

  • Capture final Grafana screenshots
  • Run a small Locust load test
  • Compare against Qwen2.5-7B
  • Evaluate GPT-OSS 20B in vLLM
  • Add RAG as the next phase

Primary Lesson

"Trusting a clean baseline can be more valuable than endlessly troubleshooting an unknown environment."

Symptoms are not always root causes.

Ollama failures and slow model responses pointed toward runtime issues, but the deeper issue was GPU ownership.

Documentation accelerates troubleshooting.

Notes, screenshots, configuration details, and validation results reduced repeated work and improved decision quality.

Recovery planning should be part of the build process.

Snapshots and NAS backups converted a working state into a recoverable platform baseline.

AI infrastructure is still infrastructure.

Architecture, reliability, security, monitoring, recovery, and documentation remain core operating concerns.

Business Value

The project demonstrates enterprise-relevant infrastructure capability across operations, platform engineering, AI infrastructure, and recovery discipline.

Infrastructure Operations

Validated host state, service behavior, backup posture, and operational reliability.

GPU Infrastructure

Managed driver installation, CUDA validation, GPU visibility, and workload execution.

Linux Administration

Worked through host-level behavior, kernel-level ownership, runtime services, and containerized execution.

Platform Engineering

Created a repeatable baseline with documented decisions, validation steps, and recovery controls.

AI Infrastructure

Integrated Open WebUI, Ollama, local model execution, and future-ready platform patterns.

Disaster Recovery

Established snapshot and NAS backup strategy immediately after successful validation.

Documentation and Repeatability

Converted troubleshooting and implementation work into artifacts that support future rebuilds.

Operational Decision Making

Selected rebuild over continued troubleshooting when confidence in platform state became too low.

Future Roadmap

Future initiatives extend the validated baseline into broader AI platform engineering capabilities.

  • llama.cpp
  • vLLM
  • Vector Database Platform
  • RAG Knowledge Platform
  • Secret Management
  • AI Operations Agent
  • AI Platform Engineering Lab