vLLM on a VPS: High-Throughput LLM Inference Server with OpenAI-Compatible API

vLLM on a VPS: High-Throughput LLM Inference Server with OpenAI-Compatible API

vLLM is a high-throughput LLM inference engine from UC Berkeley, optimized for serving language models to multiple concurrent users efficiently. Its key innovation — PagedAttention — manages GPU/CPU memory like an operating system manages virtual memory, enabling 24× higher throughput than naive inference implementations. For teams serving LLMs to multiple users simultaneously, vLLM significantly outperforms Ollama in throughput while maintaining the same OpenAI-compatible API.

vLLM vs Ollama: When to Choose Each

Factor vLLM Ollama
Concurrent users Excellent (continuous batching) Good (sequential or limited parallel)
Single user latency Similar Similar
CPU-only inference Supported (slower setup) Excellent (optimized for CPU)
Model management Manual (HuggingFace download) Automatic (ollama pull)
Ease of setup More complex Very simple
Best for Multi-user API service, production Local dev, single user, simple setup

Server Requirements

  • GPU (optimal): NVIDIA GPU with 8+ GB VRAM for 7B models, CUDA 12.1+
  • CPU (supported): 16+ GB RAM for 7B models, 4+ vCPU; uses AVX2/AVX-512 for optimized inference
  • Python 3.9+, 50+ GB disk for model storage

Step 1: Install vLLM (CPU Mode for Standard VPS)

<code"># For standard VPS (CPU inference):
sudo apt install -y python3.11 python3.11-venv python3-pip
python3.11 -m venv /opt/vllm-env
source /opt/vllm-env/bin/activate

# Install vLLM with CPU support
pip install vllm --extra-index-url https://download.pytorch.org/whl/cpu

# Verify installation
python -c "import vllm; print(vllm.__version__)"

# For GPU VPS (NVIDIA with CUDA):
# pip install vllm   # Default install uses CUDA

Step 2: Download a Model

<code"># Install HuggingFace Hub CLI
pip install huggingface_hub

# Log in (free account at huggingface.co)
huggingface-cli login

# Download a model (example: Mistral 7B Instruct, quantized for CPU)
huggingface-cli download \
    mistralai/Mistral-7B-Instruct-v0.3 \
    --local-dir /opt/models/mistral-7b-instruct

# Or use a GGUF-quantized model for faster CPU inference:
huggingface-cli download \
    bartowski/Mistral-7B-Instruct-v0.3-GGUF \
    Mistral-7B-Instruct-v0.3-Q4_K_M.gguf \
    --local-dir /opt/models/

# Lighter model for limited RAM VPS:
huggingface-cli download \
    microsoft/Phi-3-mini-4k-instruct \
    --local-dir /opt/models/phi3-mini

Step 3: Start vLLM Server

<code"># Serve Mistral 7B (CPU — will be slow but functional)
source /opt/vllm-env/bin/activate

python -m vllm.entrypoints.openai.api_server \
    --model /opt/models/mistral-7b-instruct \
    --host 127.0.0.1 \
    --port 8000 \
    --dtype bfloat16 \
    --max-model-len 4096 \      # Limit context window to save RAM
    --served-model-name mistral-7b \
    --device cpu \              # Explicit CPU mode
    --num-cpu-blocks 512        # KV cache blocks for CPU

Step 4: Systemd Service

<code">sudo nano /etc/systemd/system/vllm.service
<code">[Unit]
Description=vLLM OpenAI-Compatible Server
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt
ExecStart=/opt/vllm-env/bin/python -m vllm.entrypoints.openai.api_server \
    --model /opt/models/mistral-7b-instruct \
    --host 127.0.0.1 \
    --port 8000 \
    --dtype bfloat16 \
    --max-model-len 4096 \
    --device cpu
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
<code">sudo systemctl daemon-reload
sudo systemctl enable vllm
sudo systemctl start vllm
journalctl -u vllm -f

Step 5: Nginx with API Key Authentication

<code">sudo nano /etc/nginx/sites-available/vllm
<code">server {
    listen 443 ssl http2;
    server_name llm.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/llm.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/llm.yourdomain.com/privkey.pem;

    location / {
        # Validate API key
        if ($http_authorization != "Bearer YOUR_STRONG_API_KEY") {
            return 401 '{"error": "Unauthorized"}';
        }

        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_read_timeout 600s;
        proxy_buffering off;
    }
}

Step 6: Use the OpenAI-Compatible API

<code"># Direct API call (identical to OpenAI API)
curl https://llm.yourdomain.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_STRONG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral-7b",
    "messages": [{"role": "user", "content": "Explain vLLM in one sentence."}],
    "max_tokens": 100
  }'

# Python with OpenAI SDK — just change base_url:
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_STRONG_API_KEY",
    base_url="https://llm.yourdomain.com/v1",
)

response = client.chat.completions.create(
    model="mistral-7b",
    messages=[{"role": "user", "content": "Write a Python function to sort a list"}],
    stream=True,
)
for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end='', flush=True)

Step 7: Serving Multiple Models

<code"># vLLM can serve multiple models using multiple instances
# Run on different ports, proxy with Nginx:

# Instance 1: General model
python -m vllm.entrypoints.openai.api_server \
    --model /opt/models/mistral-7b-instruct \
    --port 8000 --served-model-name general &

# Instance 2: Code model
python -m vllm.entrypoints.openai.api_server \
    --model /opt/models/codestral \
    --port 8001 --served-model-name code &

# Nginx routes by model name in request path

Performance: CPU vs GPU

  • CPU (4 vCPU): 3–8 tokens/second for 7B models — adequate for async use cases
  • CPU (16 vCPU): 8–20 tokens/second with AVX-512 optimization
  • GPU (RTX 4090): 80–120 tokens/second — required for real-time interactive use
  • For interactive chat, CPU inference is usable; for document processing pipelines, token rate is less critical

Getting Started

vLLM on CPU works on any Ubuntu VPS at VPS.DO, though model inference speed depends heavily on CPU count and RAM. For CPU inference of 7B models, 16 GB RAM and 8+ vCPUs provide acceptable performance for batch document processing use cases. vLLM’s OpenAI-compatible API means it integrates with every tool that supports OpenAI — LangChain, LlamaIndex, Open WebUI, and custom applications.

Conclusion

vLLM provides production-grade LLM inference with continuous batching, PagedAttention memory management, and an OpenAI-compatible API. For teams serving LLMs to multiple concurrent users, vLLM’s throughput advantage over sequential inference is significant. CPU deployment on a high-core-count VPS is viable for batch processing workloads; GPU deployment is required for interactive, real-time applications. The drop-in OpenAI API compatibility makes migration from cloud LLM APIs straightforward.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!