Virtualization

Tự host LLM cục bộ trên VPS bằng Ollama: CPU-only, tính RAM theo Q4 và bảo mật API

Chạy một Large Language Model ngay trên VPS của bạn không còn là chuyện của phòng lab. Với Ollama, bạn có một runtime gọn nhẹ để tải và phục vụ các model mở như Llama 3.x, Qwen3, Mistral hay Gemma 3, kèm sẵn một REST API tương thích để ứng dụng gọi vào. Bài này tập trung vào tình huống thực tế nhất với dân vận hành server: đa số VPS không có GPU, nên chúng ta sẽ đi sâu vào chạy CPU-only, cách tính RAM theo quantization Q4 để không chọn nhầm gói, cách expose API cho ứng dụng khác, và cách khoá lại để không biến server thành cửa mở cho cả Internet.

Ollama là gì và vì sao tự host

Ollama là một daemon chạy nền, quản lý vòng đời model (pull, load, unload) và expose một HTTP API ở cổng 11434. Về bản chất nó bọc llama.cpp lại thành trải nghiệm một dòng lệnh: bạn gõ tên model, nó tự tải trọng số ở định dạng đã quantize và nạp vào RAM. Tự host mang lại ba thứ mà API đám mây không cho: dữ liệu prompt không rời khỏi server của bạn, chi phí cố định theo VPS thay vì tính theo token, và toàn quyền chọn model cùng cấu hình context.

Đổi lại, bạn gánh phần hạ tầng: đủ RAM để nạp trọng số, đủ NVMe để chứa file model (mỗi model 7B đã quantize nặng cỡ 4 đến 5 GB), và chấp nhận tốc độ CPU-only chậm hơn GPU nhiều lần.

Cài đặt Ollama trên Linux

Trên hầu hết distro (Ubuntu, Debian, các bản dựa trên systemd), script cài đặt chính thức sẽ đặt Ollama thành một systemd service chạy nền:

curl -fsSL https://ollama.com/install.sh | sh

Sau khi cài, kiểm tra service và phiên bản:

systemctl status ollama
ollama --version

Daemon lắng nghe mặc định ở 127.0.0.1:11434, tức chỉ máy cục bộ gọi được. Đây là mặc định an toàn, chúng ta sẽ giữ nguyên cho tới phần bảo mật. Thử ngay với một model nhỏ:

ollama run llama3.2:3b

Lần chạy đầu Ollama tải trọng số về (lưu ở /usr/share/ollama/.ollama/models khi chạy dưới systemd), rồi mở một phiên chat ngay trong terminal. Gõ /bye để thoát.

GPU hay CPU-only: thực tế trên VPS

Ollama tự phát hiện GPU NVIDIA/AMD nếu có driver phù hợp và dùng nó; không có thì fallback về CPU. Đa số VPS phổ thông không kèm GPU, nên bạn sẽ chạy CPU-only, và điều đó hoàn toàn khả thi với các model nhỏ và vừa. Điểm cần chấp nhận là throughput: với model 7B trên một CPU đời mới, thực tế thường rơi vào khoảng 2 đến 8 token/giây, tuỳ số core, tốc độ RAM và mức quantization.

Vài nguyên tắc để CPU-only chạy được việc thật:

  • Ưu tiên model 3B đến 8B ở mức Q4. Nhảy lên 70B trên CPU thuần gần như không dùng được cho tương tác thời gian thực.
  • RAM là yếu tố quyết định có nạp được model hay không; số core quyết định nhanh hay chậm.
  • Giảm num_ctx (độ dài context) nếu bạn không cần cửa sổ lớn, vì KV cache ăn thêm RAM theo context.

Kiểm tra model đang nạp bằng CPU hay GPU và mức RAM chiếm dụng:

ollama ps

Cột PROCESSOR sẽ báo 100% CPU khi chạy CPU-only.

Tính RAM theo quantization Q4

Quantization là cách nén trọng số model từ float 16-bit xuống số nguyên ít bit hơn để giảm dung lượng và RAM, đổi lại mất một chút chất lượng. Mức phổ biến nhất cho CPU là Q4_K_M: mỗi tham số tốn xấp xỉ 0,55 byte. Từ đó có công thức ước lượng nhanh:

RAM cần thiết ≈ (số tỉ tham số × 0,55 GB) × ~1,2 hệ số overhead + KV cache theo context

Áp vào các cỡ model quen thuộc ở Q4_K_M:

  • 7B đến 8B: file trọng số cỡ 4 đến 5 GB, cộng 1 đến 2 GB cho KV cache và overhead hệ thống. VPS 8 GB RAM là mức tối thiểu chạy thoải mái.
  • 13B đến 14B: cần khoảng 16 GB RAM.
  • 32B: cần khoảng 24 GB RAM trở lên.

Lưu ý phần KV cache: nó phình theo độ dài context, không phải hằng số. Một model 8B ở context 2K chỉ tốn thêm vài trăm MB, nhưng đẩy context lên rất cao thì KV cache một mình đã có thể ngốn nhiều GB. Nếu RAM eo hẹp, giữ num_ctx ở mức 2048 đến 4096 là cách rẻ nhất để tiết kiệm.

Bạn có thể chọn thẳng biến thể quantization khi pull, và ghim context bằng Modelfile:

ollama pull llama3.1:8b-instruct-q4_K_M

cat > Modelfile <<'EOF'
FROM llama3.1:8b-instruct-q4_K_M
PARAMETER num_ctx 2048
EOF

ollama create llama31-lean -f Modelfile
ollama run llama31-lean

Chọn model cho VPS CPU-only

Vài lựa chọn thực dụng ở năm 2026, tất cả đều pull được thẳng từ thư viện Ollama:

  • ollama run llama3.2:3b — nhẹ, phản hồi nhanh trên CPU, hợp cho chat và tóm tắt.
  • ollama run mistral:7b — cân bằng tốc độ và chất lượng, mạnh ở tóm tắt và Q&A nhanh.
  • ollama run qwen3:8b — thế hệ Qwen mới, chất lượng chung tốt ở cỡ vừa.
  • ollama run qwen2.5-coder:7b — chuyên code, hợp làm trợ lý lập trình cục bộ.
  • ollama run gemma3:4b — gọn, chất lượng khá trên phần cứng khiêm tốn.

Nguyên tắc chọn: bắt đầu từ cỡ nhỏ nhất giải quyết được việc, đo tốc độ và chất lượng, rồi mới cân nhắc leo lên cỡ lớn hơn nếu RAM và tốc độ cho phép.

Expose API cho ứng dụng gọi vào

Ollama cung cấp REST API ngay tại 11434. Gọi cục bộ để sinh văn bản:

curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2:3b",
  "prompt": "Giải thích inode trong ext4 bằng 3 câu.",
  "stream": false
}'

Có sẵn endpoint kiểu chat và một lớp tương thích OpenAI (/v1/chat/completions), nên nhiều SDK trỏ base URL về Ollama là chạy. Xem chi tiết ở tài liệu chính thức.

Nếu ứng dụng nằm ở máy khác và bạn muốn Ollama nghe trên mọi interface, đổi địa chỉ bind qua biến OLLAMA_HOST. Vì Ollama chạy dưới systemd, biến export trong shell không có tác dụng; phải khai trong unit của service:

sudo systemctl edit ollama.service

Thêm khối sau rồi lưu:

[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"

Nạp lại và khởi động lại service:

sudo systemctl daemon-reload
sudo systemctl restart ollama

Bảo mật: đừng phơi API ra Internet

Đây là phần dân vận hành hay bỏ sót. Ollama không có lớp xác thực tích hợp: bất kỳ ai chạm được tới cổng 11434 đều có thể gọi model, nạp model lạ hay vét cạn tài nguyên server. Các đợt quét toàn Internet đầu 2025 đã tìm thấy khoảng 175.000 instance Ollama phơi ra ngoài, phần lớn là do vô ý sau khi đặt bind 0.0.0.0 mà không chặn firewall.

Quy tắc tối thiểu:

  1. Giữ mặc định 127.0.0.1 nếu ứng dụng gọi Ollama chạy cùng máy. Đây là cấu hình an toàn nhất.
  2. Firewall trước, bind sau. Nếu buộc phải nghe 0.0.0.0, chặn cổng 11434 với thế giới và chỉ mở cho IP tin cậy:
    sudo ufw deny 11434/tcp
    sudo ufw allow from 203.0.113.10 to any port 11434 proto tcp
  3. Đặt reverse proxy có xác thực. Cho truy cập từ xa, dựng Nginx phía trước để làm SSL termination và bắt buộc API key hoặc HTTP Basic Auth trước khi request chạm tới cổng nội bộ. Không bao giờ trỏ thẳng 11434 ra Internet trần.
  4. Hoặc dùng VPN. Đặt Ollama trong một mạng riêng (WireGuard/Tailscale) và chỉ cho client trong VPN gọi vào là cách gọn và kín.

Sau khi cấu hình, kiểm tra lại cổng đang nghe ở đâu để chắc chắn không lỡ mở rộng ra ngoài:

sudo ss -tlnp | grep 11434

Tóm lược

Tự host LLM bằng Ollama trên VPS là việc làm được ngay cả khi không có GPU: chọn model 3B đến 8B ở Q4_K_M, ước lượng RAM theo công thức xấp xỉ 0,55 byte mỗi tham số cộng KV cache, và bắt đầu từ một VPS 8 GB RAM với NVMe đủ rộng cho file model. Khi cần cho ứng dụng khác gọi vào, expose API qua OLLAMA_HOST trong systemd, nhưng luôn đặt firewall, reverse proxy có xác thực hoặc VPN phía trước, vì bản thân Ollama không tự bảo vệ cổng của nó. Một VPS đủ RAM và NVMe nhanh sẽ giúp việc nạp model và phục vụ API mượt hơn hẳn.