SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-09-15

Ollama Cloud và server riêng: khác nhau ở đâu?

Ollama Cloud và Ollama tự host dùng chung CLI, REST API nhưng khác tên model và nơi lưu credential. Xem prompt nào rời máy bạn, kèm cách cấu hình fallback local.

Ollama Cloud thay đổi gì và không thay đổi gì

Ollama Cloud chạy model trên ollama.com thay vì trên phần cứng của bạn, đồng thời giữ nguyên lệnh ollama và REST API mà bạn đang gọi. Có 2 thay đổi: tên model bạn yêu cầu và nơi lưu credential. Phần còn lại của ứng dụng vẫn giữ nguyên.

Sự tiện lợi này cũng đi kèm rủi ro. Trong code, request đến cloud model trông giống hệt request đến model local, nên bạn dễ mất dấu prompt nào chạy trên máy mình kiểm soát và prompt nào được gửi đến một công ty mà bạn không kiểm soát. Hướng dẫn này phân định rõ hai trường hợp, sau đó chỉ cách giữ một model local làm fallback để một giá trị cấu hình duy nhất quyết định request chạy ở phía nào.

Nếu bạn chưa dựng xong phía local, trước tiên hãy bắt đầu với chạy Ollama trên VPS của bạn. Toàn bộ phần dưới đây giả định bạn đã có một ollama đang hoạt động trên máy Linux.

Hai cách truy cập Ollama Cloud

Có 2 cách truy cập các model được host, và chúng không thể thay thế cho nhau. Cách bạn chọn quyết định credential được lưu ở đâu, bạn ghi tên model nào và packet capture trên server sẽ hiển thị gì.

Cách một: daemon cục bộ chuyển tiếp request. Bạn đăng nhập 1 lần, rồi gọi một model có tên kết thúc bằng -cloud.

ollama signin
ollama pull gpt-oss:120b-cloud
ollama run gpt-oss:120b-cloud

ollama signin liên kết máy này với tài khoản ollama.com của bạn. ollama signout hủy liên kết. Sau khi đăng nhập, application vẫn tiếp tục gọi đến local port mà nó luôn sử dụng:

curl http://localhost:11434/api/chat -d '{
  "model": "gpt-oss:120b-cloud",
  "messages": [{"role": "user", "content": "Why is the sky blue?"}],
  "stream": false
}'

Hãy đọc lại URL đó. URL ghi localhost, nhưng inference không chạy tại đó. Daemon cục bộ nhận biết hậu tố -cloud, chuyển tiếp request đến ollama.com rồi stream câu trả lời về cho bạn. Đây là mục đích của cách một: application đã trỏ đến Ollama API trên port 11434 không cần thay đổi code, chỉ cần đổi chuỗi model.

Cách hai: client gọi trực tiếp đến ollama.com. Ở cách này, daemon cục bộ hoàn toàn không tham gia. Tạo key tại https://ollama.com/settings/keys, rồi gửi key đó dưới dạng bearer token.

export OLLAMA_API_KEY=your_api_key
curl https://ollama.com/api/chat \
  -H "Authorization: Bearer $OLLAMA_API_KEY" \
  -d '{
    "model": "gpt-oss:120b",
    "messages": [{"role": "user", "content": "Why is the sky blue?"}],
    "stream": false
  }'

Hãy chú ý tên model. Ở cách hai, tên model là gpt-oss:120b, không có hậu tố -cloud. Hậu tố này dùng để báo cho daemon cục bộ chuyển tiếp request lên upstream, nên chỉ thuộc về cách một. Khi gọi https://ollama.com, bạn đã gọi trực tiếp đến đó và chỉ cần ghi tên thuần. Danh sách tên chính xác lấy từ chính host:

curl https://ollama.com/api/tags

Hãy chạy lệnh đó thay vì tin vào bất kỳ danh sách model nào được in trong một bài viết, kể cả bài này. Catalogue có thể thay đổi, còn api/tags luôn là bản hiện tại.

Client nào thay đổi, client nào không

Các thư viện Python và JavaScript chính thức nhận host và headers khi bạn khởi tạo client. Sau dòng đó, không có phần nào khác thay đổi. Ở hướng thứ nhất, constructor để trống vì mặc định là daemon cục bộ:

from ollama import Client

client = Client()

messages = [{'role': 'user', 'content': 'Why is the sky blue?'}]

for part in client.chat('gpt-oss:120b-cloud', messages=messages, stream=True):
  print(part['message']['content'], end='', flush=True)

Ở hướng thứ hai, constructor chứa host và token:

import os
from ollama import Client

client = Client(
    host="https://ollama.com",
    headers={'Authorization': 'Bearer ' + os.environ.get('OLLAMA_API_KEY')}
)

messages = [{'role': 'user', 'content': 'Why is the sky blue?'}]

for part in client.chat('gpt-oss:120b', messages=messages, stream=True):
  print(part['message']['content'], end='', flush=True)

Lệnh gọi client.chat(), vòng lặp streaming, danh sách message và cấu trúc response giống hệt nhau trong cả hai trường hợp. Vì vậy, chuyển đổi giữa dịch vụ hosted và self-hosted chỉ là thay đổi cấu hình, không phải viết lại ứng dụng. Giao diện tương thích với OpenAI cũng hoạt động theo cách tương tự khi chạy cục bộ: trỏ OpenAI SDK đến http://localhost:11434/v1/ cùng với api_key='ollama'. Local server yêu cầu giá trị này nhưng sau đó sẽ bỏ qua nó.

Thông tin xác thực nằm ở đâu và ai có thể sử dụng

Ở cách 2, thông tin xác thực nằm trong OLLAMA_API_KEY của môi trường của bạn. Không để thông tin này xuất hiện trong shell history hoặc repository. Với systemd service, hãy đặt nó trong dòng Environment= hoặc trong một environment file do root sở hữu với mode 600.

Cách 1 là điều khiến nhiều người bất ngờ. Thông tin đăng nhập thuộc về daemon, không thuộc về bạn. Ollama FAQ ghi lại identity của service trên Linux tại /usr/share/ollama/.ollama/id_ed25519.pub. File này thuộc sở hữu của service user ollama. Local API không có cơ chế authentication cho từng request. Vì vậy, mọi caller có thể truy cập port 11434 đều dùng account của bạn và tiêu quota của bạn. Điều này không sao khi daemon chỉ listen trên loopback. Ngay khi bạn đặt OLLAMA_HOST=0.0.0.0:11434 để truy cập từ máy khác, một port mở sẽ trở thành một quan hệ billing mở. Vì vậy, hãy đọc cách đặt authentication trước một Ollama endpoint trước khi mở rộng bind address.

Vì sao cùng một model lại có context ít hơn khi chạy local

Đây là khác biệt dễ bị bỏ qua nếu bạn cho rằng model hoạt động giống hệt trên cả hai cách chạy. Thực tế không phải vậy, và nguyên nhân là memory.

Ollama chọn context length mặc định cho local dựa trên video memory mà nó phát hiện trên máy.

ChartOllama documented default context length by local VRAM, August 2026
The data behind this chart
[
  {
    "label": "Under 24 GiB VRAM",
    "default_context_tokens": "4,096"
  },
  {
    "label": "24 to 48 GiB VRAM",
    "default_context_tokens": "32,768"
  },
  {
    "label": "48 GiB VRAM or more",
    "default_context_tokens": "262,144"
  }
]

VPS không có GPU nằm ở tier thấp nhất. Vì vậy, local model bắt đầu với context 4,096 token, trong khi máy có card lớn bắt đầu với 262,144 token. Cloud model bỏ qua các tier này. Theo tài liệu của Ollama, chúng mặc định được đặt ở context length tối đa vì memory chứa context đó không thuộc về bạn.

Vì vậy, cùng một prompt hoạt động với gpt-oss:120b-cloud có thể bị cắt ngầm khi chạy với local model trên máy có ít tài nguyên. Hãy đặt rõ giới hạn local:

OLLAMA_CONTEXT_LENGTH=32768 ollama serve

Với systemd, đặt giá trị này bằng Environment="OLLAMA_CONTEXT_LENGTH=32768" cùng với systemctl edit ollama.service, sau đó chạy systemctl daemon-reload && systemctl restart ollama. Hãy lưu ý tác động của việc này: context dài hơn cần key-value cache lớn hơn, và cache đó sử dụng RAM ngoài phần RAM cần cho weights của model. Nếu đặt quá cao, quá trình generation sẽ chậm lại hoặc model không thể load. Cấu hình num_ctx và OLLAMA_CONTEXT_LENGTH đúng cách giải thích cách tính, còn model nào phù hợp với dung lượng memory bạn thực sự có giải thích phần weights.

Những gì thực sự rời khỏi máy của bạn

Hãy hiểu chính xác điểm này, vì đây là lý do ban đầu khiến phần lớn người đọc tự host.

Nếu chạy cục bộ thì không có dữ liệu nào rời khỏi máy. Chính sách quyền riêng tư của Ollama nêu rõ rằng khi sử dụng cục bộ: "Chúng tôi không thu thập, lưu trữ, truyền hoặc có quyền truy cập vào prompt, response, tương tác với model hay nội dung khác mà bạn xử lý cục bộ." Có một ngoại lệ cần lưu ý: việc tải model vẫn là một lượt download từ ollama.com, và chính sách liệt kê "metadata về lượt tải model" cùng địa chỉ IP của bạn trong số các dữ liệu được thu thập. Registry biết bạn đã tải những model nào. Registry không biết bạn đã hỏi chúng điều gì.

Nếu chạy qua cloud path thì toàn bộ prompt và toàn bộ completion sẽ được gửi cho bên thứ ba. Không có phiên bản nào chỉ gửi một phần. Mọi token bạn gửi và mọi token bạn nhận đều được xử lý trên ollama.com. Chính sách nêu rằng công ty xử lý "prompt và response của bạn trong thời gian ngắn để cung cấp dịch vụ", đồng thời "không sử dụng input hoặc output của bạn để train bất kỳ AI model nào", và mô tả "các biện pháp kỹ thuật nhằm giảm thiểu thời gian lưu giữ nội dung prompt và response." Đây là một cam kết hợp lý. Tuy nhiên, đó vẫn là cam kết của một bên khác về dữ liệu bạn đã giao cho họ, không phải đặc tính của chính máy bạn. Hãy đánh giá cam kết này như mọi lời hứa của vendor khác, và đọc lại chính sách trước khi gửi bất kỳ dữ liệu nào mà theo hợp đồng hoặc pháp luật bạn bắt buộc phải giữ trên hạ tầng của mình.

Bẫy nằm ở path one. Code của bạn ghi http://localhost:11434, các rule của firewall không thay đổi, nhưng prompt vẫn đi qua Internet, vì hậu tố -cloud trong tên model quyết định việc định tuyến. URL localhost không cho bạn biết inference diễn ra ở đâu. Tên model mới cho biết điều đó.

Giữ model local làm phương án dự phòng

Vì cả hai đường đi đều dùng cùng một API, bạn có thể đặt lựa chọn này thành một thiết lập lúc runtime thay vì tách nhánh trong code.

Cách đơn giản nhất không cần viết thêm code. Giữ application trỏ đến local daemon và đặt tên model trong configuration. Đặt thành llama3.2 để chạy trên máy của bạn. Đặt thành gpt-oss:120b-cloud để cùng daemon chuyển tiếp request đến ollama.com. Chỉ cần một biến môi trường, không cần redeploy.

Khi muốn model local là mặc định và cloud nhận phần tải vượt quá khả năng xử lý, hãy khởi tạo cả hai client rồi chọn theo từng request:

import os
from httpx import ConnectError
from ollama import Client, ResponseError

LOCAL_MODEL = os.environ.get("LOCAL_MODEL", "llama3.2")
CLOUD_MODEL = os.environ.get("CLOUD_MODEL", "gpt-oss:120b")

local = Client(host="http://127.0.0.1:11434")
cloud = Client(
    host="https://ollama.com",
    headers={"Authorization": "Bearer " + os.environ["OLLAMA_API_KEY"]},
)

def chat(messages):
    try:
        return local.chat(LOCAL_MODEL, messages=messages)
    except (ConnectError, ResponseError) as err:
        print(f"local inference failed ({err}); sending this prompt to ollama.com")
        return cloud.chat(CLOUD_MODEL, messages=messages)

httpx được cài kèm theo package ollama, nên không cần cài thêm gì. ConnectError xử lý trường hợp daemon đang dừng. ResponseError xử lý trường hợp daemon đang chạy nhưng từ chối request, chẳng hạn khi model local chưa từng được pull.

Dòng print không phải để trang trí. Fallback im lặng nghĩa là prompt bạn định giữ trên phần cứng của mình có thể âm thầm được gửi đến bên thứ ba ngay lần đầu daemon restart trong lúc upgrade. Hãy log mọi lần fallback. Với dữ liệu nhạy cảm, hãy trả về error thay vì fallback. Chính sách fallback an toàn nhất cho deployment ưu tiên quyền riêng tư là fail rõ ràng.

Còn một điểm giúp local side trở thành lựa chọn mặc định đáng tin cậy: giữ model trong memory. Cold load trên VPS chỉ dùng CPU có thể mất hàng chục giây. Đây chính là lý do ban đầu khiến người dùng chuyển sang cloud path. Giữ model trong memory bằng keep_alive loại bỏ độ trễ của request đầu tiên.

Những điều cần so sánh trước khi cam kết

Đừng chỉ so sánh giá, và đừng tin một mức giá bạn đọc trong bài viết, kể cả ngày đăng của bài này. Hãy so sánh 4 yếu tố và kiểm tra từng yếu tố trên chính trang của nhà cung cấp:

  • Mức độ sẵn có của model. Chạy curl https://ollama.com/api/tags để xem catalogue hosted hiện tại. Những model bạn có thể chạy local bị giới hạn bởi RAM và VRAM của bạn.
  • Giới hạn context. Model hosted mặc định dùng mức tối đa. Model local mặc định theo mức VRAM như trên. Nếu workload của bạn là các tài liệu dài, yếu tố này tự nó có thể quyết định lựa chọn.
  • Rate limit. Inference hosted được tính theo mức sử dụng. Vượt giới hạn thì API trả về 429 Too Many Requests. Server riêng của bạn không có rate limit, nhưng có giới hạn concurrency cứng; đây là một dạng lỗi khác và thường nghiêm trọng hơn.
  • Chính sách lưu giữ dữ liệu. Đọc nội dung chính sách thực tế, ghi lại ngày bạn đọc, rồi kiểm tra lại trước mỗi lần gia hạn.

Về chi phí, đừng tính lại phép toán ở đây. Khi GPU VPS có lợi hơn cách tính phí theo token phân tích đúng điểm hòa vốn, bao gồm cả phần nhiều người quên: GPU server không hoạt động vẫn bị tính phí như khi đang bận.

Còn router đứng trước nhiều provider thì sao?

Lựa chọn thứ ba là router, một proxy cung cấp một API duy nhất cho ứng dụng của bạn rồi phân phối request đến nhiều backend. Bạn có thể dùng LiteLLM proxy tự host hoặc một service được host như OpenRouter. Lợi ích là rõ ràng: chỉ cần một cấu hình client, dùng được nhiều model và có failover khi một provider gặp sự cố tạm thời. Đây là phần mở rộng tự nhiên của mẫu fallback ở trên, được tổng quát hóa cho nhiều hơn 2 backend.

Tuy nhiên, bạn cần hiểu rõ chi phí. Một router được host là thêm một đơn vị vận hành có thể thấy prompt của bạn. Vì vậy, câu hỏi về thời gian lưu trữ dữ liệu mà bạn đặt ra với một vendor giờ phải đặt ra với 2 vendor. Router tự host giữ hop này trên máy của bạn, nhưng bạn phải vận hành, cập nhật bản vá và monitor thêm một service. Router giải quyết việc chọn model và tính sẵn sàng. Router không giải quyết vấn đề privacy, vì prompt cuối cùng vẫn được gửi đến nơi mà route chỉ định.

Các lỗi bạn thực sự sẽ thấy

API mô tả các mã trạng thái, và mỗi mã chỉ ra một vấn đề khác nhau. 429 Too Many Requests nghĩa là bạn đã chạm giới hạn rate limit, vì vậy hãy chờ rồi thử lại thay vì reconnect liên tục trong một vòng lặp. 502 Bad Gateway là mã riêng của chủ đề này: mã này được trả về khi không thể kết nối đến cloud model, nên trên path one, điều đó có nghĩa là daemon của bạn vẫn hoạt động còn upstream thì không. 404 Not Found khi đi cùng tên model thường có nghĩa là suffix không khớp với host, một tên -cloud được gửi thẳng đến https://ollama.com, hoặc một tên không có tiền tố được gửi đến daemon mà bạn chưa đăng nhập. Lỗi được trả về dưới dạng JSON. Khi đang truyền dữ liệu, lỗi xuất hiện dưới dạng một dòng như {"error":"an error was encountered while running the model"} bên trong response NDJSON. Vì vậy, streaming client đơn giản có thể in ra một phần câu trả lời rồi dừng mà không giải thích. Hãy parse từng dòng được stream và kiểm tra key error.

Ở phía local, lỗi kinh điển là connection refused trên port 11434. Điều đó có nghĩa là daemon chưa chạy: hãy kiểm tra systemctl status ollama. Lỗi kinh điển khác là request chạy được từ shell nhưng thất bại từ container, vì localhost của container không phải là localhost của host.

Còn một tình huống lỗi không hiển thị thông báo nào: không có Internet. Cloud path ngừng hoạt động hoàn toàn, còn local path không nhận thấy vấn đề. Nếu máy của bạn đang di chuyển hoặc nhà cung cấp gặp sự cố định tuyến, khác biệt đó chính là toàn bộ giá trị của sản phẩm.

Khi nào nên chọn từng phương án

Dùng Ollama Cloud khi workload tăng giảm theo đợt, khi model quá lớn so với VPS của bạn, hoặc khi bạn vẫn đang đánh giá model đó có đáng để xây dựng hệ thống dựa trên nó hay không. Trả tiền theo request tốt hơn trả tiền cho một GPU nhàn rỗi chỉ chạy 20 phút mỗi ngày. Model có 120 tỷ tham số sẽ không thể chạy trên một máy được thuê với mức giá chỉ bằng một bữa trưa.

Tự chạy model khi prompt không được phép rời khỏi hạ tầng của bạn, khi máy phải hoạt động offline, hoặc khi tải đủ ổn định để GPU thuê luôn bận. Tải ổn định là dấu hiệu đáng tin cậy: inference tính phí theo mức sử dụng trở nên đắt chính vì nó chạy liên tục. Nếu đạt đến mức throughput của một request trên Ollama trở thành bottleneck, vLLM xử lý tải đồng thời tốt hơn Ollama, và đây là thay đổi engine chứ không phải thay đổi host.

Phần lớn hệ thống triển khai thực tế đều dùng cả hai. Điều đó hoàn toàn ổn nếu bạn phân chia vai trò một cách có chủ đích. Đặt tên model trong configuration, ghi log mọi lần fallback, và bạn sẽ luôn trả lời được câu hỏi duy nhất quan trọng ở đây: những prompt nào đã rời khỏi hệ thống?

FAQ

Ollama Cloud có thấy prompt của tôi không?

Có. Với đường dẫn hosted, toàn bộ prompt và completion được gửi đến ollama.com để xử lý tại đó. Chính sách quyền riêng tư của Ollama nêu rằng họ xử lý “prompt và response của bạn trong thời gian ngắn để cung cấp dịch vụ” và “không dùng input hoặc output của bạn để huấn luyện bất kỳ AI model nào”, đồng thời mô tả các biện pháp nhằm giảm thời gian lưu giữ dữ liệu. Đây là cam kết của vendor đối với dữ liệu bạn đã gửi cho họ. Với local model, chính sách tương tự nêu rằng công ty “không thu thập, lưu trữ, truyền hoặc truy cập prompt, response, tương tác với model hay nội dung khác mà bạn xử lý cục bộ”. Nếu yêu cầu là nội dung không bao giờ rời khỏi hạ tầng của bạn, chỉ đường dẫn local mới đáp ứng được yêu cầu đó.

Tại sao app của tôi vẫn trỏ đến localhost khi model chạy trên cloud?

Vì local daemon đang hoạt động như một proxy. Khi bạn chạy ollama signin rồi request một model có tên kết thúc bằng -cloud, daemon sẽ forward request đó đến ollama.com và stream câu trả lời về qua port 11434. URL của ứng dụng không thay đổi; đó chính là mục đích của cơ chế này: không cần sửa code. Điều này cũng có nghĩa là địa chỉ localhost không cho biết inference diễn ra ở đâu. Hãy kiểm tra tên model, không phải URL. Suffix -cloud cho biết prompt đã đi qua Internet.

Tại sao cùng một model lại có context ngắn hơn nhiều khi chạy local?

Ollama chọn giá trị local mặc định dựa trên video memory khả dụng: khoảng 4k token khi VRAM dưới 24 GiB, 32k khi VRAM từ 24 đến 48 GiB, và 256k khi VRAM từ 48 GiB trở lên. VPS không có GPU sẽ thuộc tier thấp nhất. Cloud model mặc định được đặt ở context length tối đa, vì phần memory dùng để chứa context thuộc về provider. Tăng giá trị local bằng OLLAMA_CONTEXT_LENGTH, theo dạng OLLAMA_CONTEXT_LENGTH=32768 ollama serve hoặc bằng một dòng Environment= trong systemctl edit ollama.service. Hãy nhớ rằng context dài hơn cần key-value cache lớn hơn trong RAM. Vì vậy, tăng giá trị này trên server nhỏ có thể làm chậm việc sinh nội dung hoặc khiến model không load được.

Tôi có thể tự động chuyển về local model khi cloud không truy cập được không?

Có. Bạn chỉ cần vài dòng vì cả hai đường dẫn đều dùng cùng một API. Tạo hai object Client: một object không có host argument cho local daemon và một object có host="https://ollama.com" cùng header Authorization: Bearer. Sau đó bắt httpx.ConnectErrorollama.ResponseError quanh lần gọi đầu tiên. Hãy chủ động quyết định hướng chuyển đổi. Dùng local trước rồi fallback sang cloud có nghĩa là prompt bạn định giữ riêng tư có thể rời khỏi máy trong lúc daemon restart định kỳ. Vì vậy, hãy log mọi lần fallback. Với workload nhạy cảm, hãy raise error thay vì fallback.