AI Automation

Self-host API LLM với Ollama trên VPS

Bạn đang xây dựng ứng dụng AI nhưng muốn tránh phụ thuộc vào API đám mây tốn phí theo từng request? Self-host LLM API với Ollama trên VPS là hướng đi đang được nhiều dev lựa chọn trong 2026. Bài này mình sẽ hướng dẫn chi tiết từ cài đặt Ollama trên Ubuntu 24.04, tải model, expose API tương thích chuẩn OpenAI, đến bảo mật bằng Nginx reverse proxy kèm xác thực API key. Cuối bài bạn sẽ có một backend LLM hoàn chỉnh chạy trên VPS của mình, sẵn sàng cho ứng dụng gọi vào.

Mô hình self-host LLM API nghĩa là bạn tự chạy model ngôn ngữ lớn trên máy chủ riêng, thay vì gọi đến OpenAI, Anthropic hay Google. Ollama là công cụ phổ biến nhất cho việc này vì cài đặt đơn giản, quản lý model dễ, và đặc biệt là API của nó tương thích với chuẩn OpenAI - nghĩa là code cũ viết cho OpenAI chỉ cần đổi base URL là chạy được.

Tóm tắt nhanh

  • Ollama chạy tốt trên VPS Linux với RAM từ 8GB trở lên, model 7B-8B cần khoảng 5-6GB RAM khả dụng.
  • API của Ollama mặc định listen trên port 11434 và tương thích chuẩn OpenAI ở endpoint /v1/chat/completions.
  • Không nên expose port 11434 ra Internet trực tiếp - hãy đặt sau Nginx reverse proxy kèm xác thực API key.
  • Model Llama 3.1 8B và Qwen 2.5 7B là hai lựa chọn phổ biến nhất cho VPS tầm trung năm 2026.

Yêu cầu trước khi bắt đầu

  • Một VPS chạy Ubuntu 24.04 LTS với tối thiểu 8GB RAM (4GB là chạy được model nhỏ nhưng rất chật). Nếu chưa có, bạn có thể thuê VPS Linux với cấu hình NVMe để tăng tốc độ load model.
  • User sudo không dùng root trực tiếp (mặc định mình khuyên nên tạo user riêng).
  • Tên miền trỏ về IP VPS nếu muốn expose API qua HTTPS (khuyến nghị).
  • Hiểu cơ bản về Nginx và systemd - nếu chưa rõ thì đọc thêm bài cài đặt Nginx reverse proxy trên Ubuntu 24.04 của mình.

Vì sao nên self-host LLM API thay vì gọi API đám mây?

Chi phí là lý do đầu tiên. Gọi API đám mây tính phí theo token, với ứng dụng xử lý hàng nghìn request mỗi ngày, hóa đơn hàng tháng có thể lên đến vài triệu đồng. Self-host chỉ tốn chi phí VPS cố định. Với mức giá thuê VPS hàng tháng từ khoảng 189.000đ, bạn chạy không giới hạn số lượng request trong khả năng phần cứng.

Quyền riêng tư là lý do thứ hai. Dữ liệu nhạy cảm của khách hàng, code nội bộ, hay nội dung chat không cần gửi ra bên ngoài. Mọi thứ xử lý ngay trên VPS của bạn. Với doanh nghiệp Việt Nam, yêu cầu dữ liệu ở trong nước ngày càng phổ biến - self-host LLM trên VPS Linux đặt tại Việt Nam giải quyết triệt để vấn đề này.

Lý do thứ ba là kiểm soát. Bạn tự chọn model, tự tinh chỉnh tham số, tự update khi có phiên bản mới. Không lo bị vendor lock-in, không lo API thay đổi giá giữa chừng.

Bước 1 - Cài đặt Ollama trên VPS

Ollama cung cấp script cài đặt tự động. SSH vào VPS và chạy lệnh sau:

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

Script này tự thêm repository apt của Ollama, cài package và tạo systemd service. Sau khi cài xong, kiểm tra service đã chạy chưa:

sudo systemctl status ollama

Output mong đợi có dòng Active: active (running). Mặc định Ollama listen trên 127.0.0.1:11434, chưa expose ra ngoài - đây là trạng thái an toàn, ta sẽ giữ nguyên và đặt Nginx phía trước.

Bước 2 - Tải model LLM về VPS

Ollama dùng khái niệm "model library" - bạn tải model về máy bằng lệnh ollama pull. Chạy lệnh sau để tải Llama 3.1 8B - model đa dụng hàng đầu cho VPS tầm trung hiện tại:

ollama pull llama3.1:8b

Dung lượng khoảng 4.7GB, tốc độ tải tùy thuộc băng thông quốc tế của VPS. Nếu bạn dùng VPS Việt Nam thì chặng tải từ registry quốc tế có thể chậm hơn, kiên nhẫn chờ.

Muốn thử model khác, ví dụ Qwen 2.5 7B (model Trung Quốc, hỗ trợ tiếng Việt khá tốt và nhẹ hơn Llama):

ollama pull qwen2.5:7b

Xem danh sách model đã tải:

ollama list

Output hiện tên model, tag, ID và dung lượng. Lưu ý thời điểm model tải xong chỉ chiếm dung lượng ổ đĩa, RAM chỉ được dùng khi có request gọi vào.

Bước 3 - Test API LLM cục bộ trước khi expose

Trước khi đưa ra Internet, test API trên chính VPS. Chạy lệnh curl gọi đến endpoint chat completion:

curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.1:8b",
    "messages": [
      {"role": "user", "content": "Xin chào, giới thiệu ngắn về bạn"}
    ]
  }'

Output là JSON chuẩn OpenAI, chứa choices, message.content và thông tin usage token. Đây là điểm mạnh của Ollama: client code viết cho OpenAI chỉ cần đổi base URL từ https://api.openai.com sang http://VPS_IP:11434 là hoạt động.

Một điểm cần lưu ý: model 8B trên CPU thuần sẽ cho tốc độ khoảng 10-15 token/giây. Nếu VPS có GPU (hiếm ở phân khúc VPS giá rẻ) thì nhanh hơn nhiều, nhưng với hầu hết trường hợp, tốc độ CPU là chấp nhận được cho chatbot, summarization, hay automation không yêu cầu real-time gắt.

Bước 4 - Cấu hình Nginx reverse proxy cho Ollama API

Không nên expose port 11434 ra Internet trực tiếp. Lý do: không có xác thực, ai biết IP đều gọi được, và traffic không mã hóa. Thay vào đó, đặt Nginx phía trước, thêm xác thực API key ở tầng Nginx. Cài Nginx nếu chưa có:

sudo apt update
sudo apt install nginx -y

Tạo file cấu hình cho site:

sudo nano /etc/nginx/sites-available/ollama

Nội dung file cấu hình reverse proxy:

server {
    listen 80;
    server_name llm.example.com;

    location / {
        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Tăng timeout cho request dài
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

Kích hoạt site và kiểm tra cú pháp:

sudo ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Lúc này API đã có thể gọi qua HTTP. Nhưng vẫn chưa có xác thực - bước tiếp theo sẽ xử lý.

Bước 5 - Thêm xác thực API key bằng Nginx auth_request

Cách đơn giản nhất để bảo vệ LLM API là dùng header Authorization: Bearer và kiểm tra ở tầng Nginx. Sửa file cấu hình ở trên:

sudo nano /etc/nginx/sites-available/ollama

Thay toàn bộ nội dung bằng:

geo $api_key_ok {
    default 0;
    "API_KEY_DAU_TIEN" 1;
    "API_KEY_THU_HAI" 1;
}

server {
    listen 80;
    server_name llm.example.com;

    location / {
        if ($http_authorization !~* "Bearer (.+)") {
            return 401;
        }

        set $key $1;
        if ($api_key_ok = 0) {
            return 401;
        }

        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

Thay API_KEY_DAU_TIENAPI_KEY_THU_HAI bằng chuỗi key thật của bạn - dùng lệnh sau để sinh key ngẫu nhiên an toàn:

openssl rand -base64 32

Test lại cấu hình và reload:

sudo nginx -t
sudo systemctl reload nginx

Giờ thử gọi API kèm key:

curl http://llm.example.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer API_KEY_DAU_TIEN" \
  -d '{
    "model": "llama3.1:8b",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

Nếu gọi không kèm key, bạn sẽ nhận HTTP 401. Đây là lớp bảo vệ đầu tiên; ứng dụng của bạn sẽ gửi key này trong mọi request.

Bước 6 - Cài HTTPS bằng Let's Encrypt

HTTP trần nghĩa là API key và nội dung prompt đi qua mạng không mã hóa. Trong môi trường production, điều này không chấp nhận được. Dùng Certbot để cấp chứng chỉ SSL miễn phí:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d llm.example.com

Certbot tự động sửa cấu hình Nginx, thêm SSL và redirect HTTP sang HTTPS. Sau khi hoàn tất, mọi request phải qua https://llm.example.com.

Kiểm tra chứng chỉ đã hoạt động:

sudo certbot certificates

Output hiện domain, ngày hết hạn và đường dẫn file chứng chỉ. Certbot tự gia hạn qua systemd timer, bạn không cần can thiệp. Nếu muốn tự động hóa việc cấp và gia hạn SSL wildcard cho nhiều subdomain, tham khảo bài tự động cấp và gia hạn SSL wildcard với acme.sh của mình.

Bước 7 - Cấu hình Ollama cho production

Mặc định Ollama giới hạn số request đồng thời và dùng RAM không giới hạn. Với VPS tầm trung, bạn nên siết lại. Sửa file service override:

sudo systemctl edit ollama

Thêm nội dung sau:

[Service]
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_KEEP_ALIVE=5m"

Giải thích:

  • OLLAMA_NUM_PARALLEL=1 - chỉ xử lý một request tại một thời điểm, tránh quá tải RAM khi nhiều request cùng đến.
  • OLLAMA_MAX_LOADED_MODELS=1 - chỉ giữ một model trong RAM, model khác khi được gọi sẽ load lại, tốn thời gian nhưng tiết kiệm RAM.
  • OLLAMA_KEEP_ALIVE=5m - model ở lại RAM 5 phút sau request cuối, sau đó giải phóng. Giảm RAM rảnh cho ứng dụng khác.

Restart service để áp dụng:

sudo systemctl daemon-reload
sudo systemctl restart ollama

Một lưu ý nữa: model 7B-8B khi load chiếm khoảng 5-6GB RAM. Trên VPS 8GB, bạn còn khoảng 2GB cho hệ điều hành, Nginx và các tiến trình khác. Nếu VPS của bạn chỉ có 4GB RAM, hãy dùng model nhỏ hơn như llama3.2:3b hoặc qwen2.5:3b. Nếu bạn đang dùng VPS NVMe thì swap trên NVMe cũng giúp ích, nhưng tốc độ sẽ chậm hơn nhiều so với RAM thật.

Bước 8 - Giám sát và log Ollama API

Production cần biết API đang hoạt động ra sao. Kiểm tra log Ollama realtime:

sudo journalctl -u ollama -f

Output hiện từng request, model được gọi, và thời gian xử lý. Nếu có lỗi, log nằm ở đây. Log Nginx cho biết traffic đến API:

sudo tail -f /var/log/nginx/access.log

Muốn giám sát có dashboard đẹp, bạn có thể đẩy metric của VPS lên Prometheus và Grafana - tham khảo bài giám sát VPS với Prometheus và Grafana. Ít nhất nên theo dõi RAM và CPU, vì LLM là workload rất ngốn tài nguyên.

Nếu ứng dụng của bạn là chatbot hoặc agent, cân nhắc giới hạn số token output và thời gian request để tránh một request dài chiếm model quá lâu. Tham số max_tokens trong request là công cụ hữu ích.

Xử lý lỗi thường gặp

Lỗi "model not found" khi gọi API

Kiểm tra model đã tải về đúng tên chưa. Chạy ollama list xem tên chính xác. Tên trong request phải khớp rất cao, ví dụ llama3.1:8b chứ không phải llama3.

API trả về timeout khi generation dài

Mặc định Nginx proxy timeout 60s, model trên CPU có thể mất 2-3 phút cho output dài. Bạn đã thêm proxy_read_timeout 300s trong cấu hình ở trên, kiểm tra lại xem đã áp dụng đúng chưa. Nếu vẫn timeout, tăng lên 600s cho bài toán generation rất dài, hoặc giảm max_tokens ở phía client.

VPS bị OOM khi chạy model 8B

Đây là lỗi phổ biến nhất với VPS 8GB RAM. Kiểm tra bằng dmesg | tail -20 xem có dòng Out of memory không. Giải pháp: dùng model 3B, hoặc giới hạn context length trong request (tham số num_ctx), hoặc thêm swap. Xem thêm bài cấu hình swap cho VPS RAM thấp của mình.

API key bị lộ trong log

Ứng dụng của bạn nên đọc API key từ biến môi trường, không hardcode trong source code. Trên client, dùng os.environ["API_KEY"] (Python) hoặc process.env.API_KEY (Node.js). Kiểm tra log Nginx không ghi header Authorization: cấu hình mặc định của Nginx không ghi header, nhưng nếu bạn custom log format, hãy chắc chắn không include $http_authorization.

Câu hỏi thường gặp

Ollama có tương thích hoàn toàn với API OpenAI không?

Về cơ bản là có cho endpoint /v1/chat/completions. Code viết cho OpenAI chỉ cần đổi base URL và API key là chạy. Tuy nhiên một số tính năng nâng cao như function calling, vision, hay streaming có thể khác biệt nhỏ, cần kiểm tra từng trường hợp cụ thể.

VPS cấu hình bao nhiêu RAM để chạy Ollama?

Model 7B-8B cần tối thiểu 8GB RAM, model 3B chạy được trên 4GB. Nếu bạn muốn chạy model 13B-14B thì cần 16GB. VPS của thueVPS có gói từ 2GB đến 16GB RAM, chọn theo model bạn định dùng.

Có cần GPU để chạy self-host LLM không?

Không bắt buộc. Model 8B chạy trên CPU cho tốc độ 10-15 token/giây, đủ dùng cho chatbot và automation. GPU cho tốc độ nhanh hơn 5-10 lần nhưng chi phí VPS GPU rất cao, thường không đáng với bài toán cá nhân hoặc doanh nghiệp nhỏ.

Làm sao để ứng dụng của tôi gọi vào Ollama API?

Chỉ cần đổi base URL trong client OpenAI sang https://llm.example.com/v1 và dùng API key bạn đã cấu hình. Ví dụ Python với openai library: client = OpenAI(base_url="https://llm.example.com/v1", api_key="API_KEY_DAU_TIEN").

Self-host LLM có rẻ hơn API đám mây không?

Với lượng request lớn và đều đặn thì rẻ hơn rõ rệt. VPS 8GB RAM giá khoảng vài trăm nghìn mỗi tháng, trong khi API đám mây cho cùng lượng request có thể lên đến vài triệu. Nhưng nếu request ít và không thường xuyên, API đám mây vẫn tiện hơn vì không phải tự vận hành.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.