box धीमा होने के बजाय जम गया
मॉडल और उसका context cache मिलकर RAM से ज़्यादा हो गए और kernel हर टोकन पर weights को page करने लगा। memory में फ़िट हों या एक साइज़ छोटा मॉडल लें — इसके बीच का कोई setting नहीं है।

अपने ही hardware पर जवाब देने वाले एक LLM तक पहुँचने के छह चरण — वह गणित जो box ख़रीदने से पहले आपके tokens per second का अंदाज़ा दे देता है, 4, 8, 16 या 32 GB में कौन-सा मॉडल फ़िट होता है, वह authentication जो Ollama साथ नहीं देता, और उन कामों की एक ईमानदार सूची जो फ़िट नहीं बैठते। Debian 12 पर tested।
आकार
Bandwidth, cores नहीं
Install करें
Ollama
मापें
आपके अपने tokens/s
सुरक्षित करें
TLS + एक टोकन
Connect करें
एक base URL
इसे सीमित करें
Context, RAM, डिस्क
LLM को locally चलाने के बारे में जो कुछ भी लिखा गया है, वह लगभग सब graphics card के बारे में है, जो तब बेकार है जब आपके पास एक virtual machine हो। असली उपयोगी mental model GPU वाली बहस से कहीं आसान है, और यह एक वाक्य में आ जाता है: एक टोकन बनाने के लिए, एक dense मॉडल को अपने हर weight को memory से पढ़ना पड़ता है। कुछ नहीं — सभी को, हर टोकन पर एक बार।
यह एक तथ्य ही पूरे performance वाले सवाल का जवाब तय कर देता है। Generation की रफ़्तार इससे तय नहीं होती कि आपने कितने cores rent किए; यह इससे तय होती है कि machine मॉडल को RAM से कितनी तेज़ी से stream कर सकती है। जिससे आपको एक ceiling मिल जाती है जिसे आप कुछ भी ख़र्च करने से पहले लिफ़ाफ़े की पीठ पर compute कर सकते हैं:
tokens per second ≈ memory bandwidth (GB/s) ÷ model size (GB)
एक quantised 8B मॉडल क़रीब 5 GB घेरता है। एक virtualised host पर जहाँ आप असल में लगभग 20 GB/s के आसपास stream कर सकते हैं, ceiling क़रीब चार टोकन प्रति सेकंड है, और जो नंबर आप असल में देखेंगे वह शायद उसका आधा से दो-तिहाई होगा। मोटे तौर पर तीन शब्द प्रति सेकंड। इसे workload के बारे में एक तथ्य समझें, निराशा नहीं: यह किसी chat window के लिए धीमा है और किसी ऐसे काम के लिए बिलकुल पर्याप्त है जो एक document को classify करे और एक लाइन JSON लौटाए।
Cores अब भी मायने रखते हैं, बस उस वजह से नहीं जो लोग मान लेते हैं। ज़्यादा threads तब तक मदद करते हैं जब तक वे memory path को saturate न कर दें, जो इन machines पर जल्दी हो जाता है — अक्सर चार से आठ threads के आसपास। उसके बाद extra cores बेकार बैठे रहते हैं जबकि बाक़ी सब RAM का इंतज़ार करता है। यही वजह है कि एक sixteen-core box text generate करने में एक four-core box से चार गुना तेज़ नहीं होता, और यही वजह है कि रफ़्तार की उम्मीद में cores के लिए पैसे देना ग़लत टियर ख़रीदने का सबसे आम तरीक़ा है।
पढ़ना तेज़ है, लिखना धीमा। हर request में दो phases होते हैं और दोनों बिलकुल अलग तरह से बर्ताव करते हैं। prompt को process करना — यानी prefill — पूरे input पर एक साथ चलने वाला एक compute-bound matrix operation है, और यह generation से कई गुना तेज़ चलता है। जवाब बनाना वह memory-bound हिस्सा है जो ऊपर बताया गया, एक बार में एक टोकन। तो मॉडल को दो-हज़ार-शब्दों का document थमाकर तीन वाक्य माँगना एक आरामदायक workload है, जबकि उससे दो-हज़ार-शब्दों का essay माँगना नहीं। अपने prompts को इसी असंतुलन के हिसाब से design करें और एक CPU box अपने token rate के मुक़ाबले कहीं बेहतर महसूस होता है।
| स्तर | मेमोरी | सबसे बड़ा आरामदायक मॉडल | परिमाण का क्रम | यह किसलिए है |
|---|---|---|---|---|
| Sentinel · $3.90 | 4 GB | Q4 पर 3B (~2 GB) | एक वाक्य प्रति सेकंड | वर्गीकरण, टैगिंग, रूटिंग, embeddings |
| Garrison · $7.90 | 8 GB | Q4 पर 8B (~5 GB) | कुछ शब्द प्रति सेकंड | Default। Summaries, JSON extraction, RAG जवाब |
| Ravelin · $16.90 | 16 GB | Q4 पर 14B (~9 GB) | ऊपर वाले का लगभग आधा | मुश्किल reasoning, लंबा context, batch pipelines |
| Bulwark · $32.90 | 32 GB | Q4 पर 32B (~20 GB) | एक शब्द प्रति सेकंड से कम | रफ़्तार से ज़्यादा quality। सिर्फ़ asynchronous काम |
| Citadel · $62.90 | 64 GB | Q4 पर 70B (~40 GB) | मिनट प्रति जवाब | यह फ़िट होता है। यह interactive नहीं है। रात भर चलने वाले काम |
मॉडल के आकार सामान्य Q4_K_M quantisation वाले हैं, जो memory का आधे से भी कम इस्तेमाल करने के बदले quality का एक छोटा और आमतौर पर न दिखने वाला हिस्सा देते हैं। speed वाला column ऊपर की division से निकाला गया एक order of magnitude है, कोई benchmark नहीं — चरण 03 का मक़सद यही है कि आप किसी table पर भरोसा करने के बजाय अपनी ख़ुद की machine मापें, इस table पर भी नहीं।
इस section का ईमानदार version किसी उत्साही version से कहीं ज़्यादा काम का है, क्योंकि किसी self-hosted मॉडल को छोड़ देने का सबसे तेज़ तरीक़ा उसे उसी एक काम पर लगाना है जिसमें वह सबसे कमज़ोर है, और फिर यह मान लेना कि पूरा idea ही बेवक़ूफ़ी था।
आराम से फ़िट होता है। कोई भी ऐसा काम जिसमें output छोटा हो और value prose में नहीं बल्कि judgement में हो। किसी message को मुट्ठी-भर buckets में से एक में classify करना। यह तय करना कि कोई support ticket urgent है या नहीं। किसी invoice से पाँच fields को JSON के रूप में निकालना। किसी thread को तीन वाक्यों में summarise करना। किसी document को tag करना। किसी product description को rewrite करना। किसी छोटी string का अनुवाद करना। यह पता लगाना कि दो records एक ही व्यक्ति के बारे में हैं या नहीं। किसी paragraph के कहीं और जाने से पहले उसमें से नाम redact करना। इनमें से हर एक काम एक लंबा input खाता है और एक छोटा output देता है, और यही वह असंतुलन है जिसे एक CPU अच्छे से संभालता है।
फ़िट होता है, पर धैर्य के साथ। ऐसा काम जिस पर कोई इंसान इंतज़ार नहीं कर रहा। रात भर चलने वाले batches, queue workers, दिन भर के documents पर एक रात वाला pass, एक scheduled report। अगर जवाब पर कुछ भी नहीं रुका है, तो जो token rate किसी chat window में असहनीय होगी वह बिलकुल भी मायने नहीं रखती — रात के तीन बजे छह मिनट चलने वाला काम बस एक ऐसा काम है जो चल गया।
फ़िट नहीं होता। एक ऐसा interactive assistant जिसे लोग सचमुच पसंद करके इस्तेमाल करें: इन rates पर cursor रेंगता है और experience बिना assistant से भी बुरा हो जाता है। Long-form generation — मुझे दो हज़ार शब्द लिख दो — जहाँ पूरा output ही धीमा हिस्सा है। Coding agents जो किसी बड़े repository पर iterate करते हैं, जहाँ context और quality bar दोनों एक छोटे मॉडल की क्षमता से ज़्यादा हैं। कोई भी चीज़ जिसे एक लाख-टोकन context चाहिए, जहाँ अकेला cache ही machine से बड़ा हो जाता है। और image या video मॉडल, जो पूरी तरह एक अलग discipline हैं और जिन्हें सचमुच GPU चाहिए।
अगर आपका workload उस आख़िरी group में आता है, तो समझदारी भरा जवाब बड़ा CPU box ख़रीदना नहीं है — यह एक hybrid है। ज़्यादातर calls के लिए एक local मॉडल रखें और जिन थोड़े-से को frontier reasoning चाहिए उन्हें किसी hosted API पर भेजें, जो ठीक वही shape है जो AI एजेंट को 24/7 चलाने की गाइड runtime वाले हिस्से के लिए बताती है। उस गाइड ने जानबूझकर मॉडल को ही scope से बाहर रखा था। यह गाइड वही बाक़ी आधा हिस्सा है।
काम से उल्टी दिशा में सोचें। तय करें कि मॉडल को क्या करना है, वह सबसे छोटा आकार चुनें जो यह कर दे, देखें कि Q4_K_M पर वह आकार कितनी जगह घेरता है, फिर overheads जोड़ें:
RAM needed = model file + KV cache + ~2 GB for the system
3B Q4_K_M ≈ 2.0 GB KV cache at 8k context ≈ 0.5–1 GB
8B Q4_K_M ≈ 4.9 GB KV cache at 32k context ≈ 2–4 GB
14B Q4_K_M ≈ 9.0 GB
32B Q4_K_M ≈ 20.0 GB
70B Q4_K_M ≈ 40.0 GB
key-value cache वह overhead है जिसे लोग भूल जाते हैं। conversation में मौजूद हर टोकन memory में रखा जाता है ताकि मॉडल उसे दोबारा compute न करे, और यह store उतना ही बढ़ता है जितना context आप allow करते हैं। context को दोगुना करने से यह भी लगभग दोगुना हो जाता है। जो मॉडल 4k context पर फ़िट होता है वह 32k पर फ़िट होने में फ़ेल हो सकता है, और वह पहली नहीं बल्कि दसवीं request पर फ़ेल होगा, जिससे यह किसी गणित की ग़लती के बजाय एक रहस्य जैसा लगता है।
यहाँ कोई graceful degradation नहीं है। जब कुल जोड़ RAM से ज़्यादा हो जाता है तो kernel शराफ़त से धीमा नहीं होता: वह हर एक टोकन पर मॉडल के weights को disk से और disk पर page करने लगता है। एक चार-सेकंड की generation चार मिनट की बन जाती है, load average दहाइयों में चढ़ जाता है, और box पर बाक़ी सब कुछ — database, web server, आपका SSH session — इसके साथ तकलीफ़ उठाता है। memory में फ़िट होना कोई optimisation नहीं है। यह एक ज़रूरत है।
panel में: Order → VPS → वह टियर जिस पर गणित ने इशारा किया, image Debian 12। account खोलने के लिए किसी email address की ज़रूरत नहीं, किसी भी क़दम पर कोई identity document नहीं माँगा जाता, और invoice Monero, Bitcoin, Lightning या किसी और supported asset में settle होता है — जो यहाँ किसी आम web server से कहीं ज़्यादा मायने रखता है, उन वजहों से जो anonymous VPS hosting की pillar गाइड में बताई गई हैं और जिन्हें नीचे privacy वाला अध्याय ख़ासतौर पर prompts पर लागू करता है।
पहले machine को सख़्त करें — सिर्फ़ key वाला SSH, एक ऐसा firewall जो वही चीज़ जाने दे जो आपने माँगी हो, unattended security upgrades। पहले घंटे की checklist में क़रीब एक घंटा लगता है, और यह वह box है जो जल्द ही आपके पूछे हर सवाल को संभालेगा।
फिर runner install करें। Ollama दरअसल llama.cpp ही है जिसके चारों ओर एक model registry, एक REST API और एक systemd unit लिपटी हुई है, और एक-लाइन का installer तीनों को सेट कर देता है:
apt update && apt install -y curl
curl -fsSL https://ollama.com/install.sh | sh
systemctl status ollama --no-pager
ss -ltnp | grep 11434
# → 127.0.0.1:11434 — loopback only. Leave it that way.
वह आख़िरी लाइन ऐसी है जिसे दो बार पढ़ना चाहिए। out of the box यह service loopback interface पर सुनती है, जो बिलकुल सही है, और अगले दस मिनट में होने वाली सबसे आम ग़लती OLLAMA_HOST को 0.0.0.0 पर set कर देना है, क्योंकि किसी दूसरी machine से यह पहुँच में नहीं आ रहा था। चरण 04 यही बताता है कि इस तक सही तरीक़े से कैसे पहुँचा जाए; इसका कोई भी version ऐसा नहीं है जहाँ port 11434 सीधे internet के सामने हो।
दो settings ऐसी हैं जिन्हें बाद में खोजने के बजाय अभी जगह पर लगा देना बेहतर है। मॉडल default रूप से /usr/share/ollama के नीचे store होते हैं और वे बड़े होते हैं, इसलिए इसे वहाँ point करें जहाँ आपके पास जगह हो। और default आख़िरी request के बाद पाँच मिनट तक मॉडल को RAM में resident रखता है, जो उस box पर काफ़ी उदार है जो और भी काम कर रहा है:
systemctl edit ollama
[Service]
Environment="OLLAMA_MODELS=/var/lib/ollama/models"
Environment="OLLAMA_KEEP_ALIVE=30m"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
systemctl daemon-reload && systemctl restart ollama
Parallel requests और एक साथ कई loaded मॉडल दोनों ही memory का इस्तेमाल गुणा कर देते हैं, और ठीक एक मॉडल के हिसाब से sized machine पर दूसरी copy के लिए एक भी अतिरिक्त gigabyte नहीं बचता। queue को serialise करना इस hardware की कोई सीमा नहीं है; यही वह अकेला configuration है जो गिरता नहीं।
एक मॉडल pull करें। पहले measurement के लिए मौजूदा 8B-class instruct मॉडलों में से कोई भी चलेगा — वे आकार में इतने पास हैं कि timing मॉडल के बारे में नहीं बल्कि hardware के बारे में बताती है:
ollama pull llama3.1:8b # ~4.9 GB at Q4_K_M
ollama list
ollama ps # nothing resident yet
अब timings चालू करके एक generation चलाएँ। जो नंबर मायने रखता है वह है eval rate — prompt पढ़े जाने के बाद प्रति सेकंड बनने वाले टोकन:
ollama run llama3.1:8b --verbose "Reply with exactly one sentence about the Baltic Sea."
total duration: 14.2s
load duration: 3.1s
prompt eval count: 24 token(s)
prompt eval rate: 92.11 tokens/s ← reading: fast
eval count: 38 token(s)
eval rate: 3.42 tokens/s ← writing: the real ceiling
दो लाइनें, दो अलग दुनियाएँ। Reading लगभग नब्बे टोकन प्रति सेकंड पर चली; writing साढ़े तीन पर। यह अनुपात ही वह असंतुलन है जो गणित वाले अध्याय से निकला, आपके अपने metal पर मापा गया, और आज आप जो सबसे काम का तथ्य इकट्ठा करेंगे वह यही है। यह कहता है: इस box को लंबे inputs दें और छोटे outputs माँगें।
वही measurement API के ज़रिए, जो असल में वही चीज़ है जो आप चाहते हैं अगर आप दो या तीन मॉडल आकारों के बीच comparison को script करना चाहते हैं:
apt install -y jq
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "List three Nordic capitals.",
"stream": false
}' | jq '{
tokens: .eval_count,
seconds: (.eval_duration / 1000000000),
rate: (.eval_count / (.eval_duration / 1000000000))
}'
नीचे वाला आकार और ऊपर वाला आकार मापें, फिर रुक जाएँ। एक 3B और एक 14B pull करें, दोनों में एक ही prompt चलाएँ, और तीनों rates लिख लें। अब आपको ठीक-ठीक पता है कि इस machine पर यह trade क्या क़ीमत रखता है — आमतौर पर हर दिशा में लगभग दोगुना — और अब आप राय के बजाय काम के हिसाब से चुन सकते हैं। फिर जिन मॉडलों को नहीं रखना, उन्हें हटा दें, क्योंकि हर एक कई gigabyte का है।
किसी भी मॉडल के पहले run पर एक caveat: उस output में मौजूद load duration वह समय है जो weights को disk से RAM में पढ़ने में लगता है। यह तभी चुकाना पड़ता है जब मॉडल पहले से resident न हो, और यही वह चीज़ है जिसे OLLAMA_KEEP_ALIVE control करता है। rates compare करते समय इसे शामिल न करें, और इससे घबराएँ भी नहीं — NVMe पर यह बस कुछ सेकंड का है, और सिर्फ़ एक बार होता है।
गाइड का यह हिस्सा किसी बुरी चीज़ को होने से रोकता है, इसलिए इसे बिना लाग-लपेट के कहा जा रहा है: Ollama के API में कोई password नहीं, कोई टोकन नहीं, कोई user मॉडल नहीं और कोई permission system नहीं है। जो कुछ भी port 11434 पर TCP connection खोल सकता है वह आपके CPU पर text generate कर सकता है, आपके pull किए मॉडलों की गिनती कर सकता है, नए pull कर सकता है और जिन्हें आप इस्तेमाल करते हैं उन्हें मिटा सकता है। यहाँ चालू करने के लिए कोई setting नहीं है, क्योंकि चालू करने के लिए कोई mechanism ही नहीं है।
Port 11434 लगातार scan होता है, एक साफ़ वजह से: एक खुला model runner किसी और का free compute है। इसका लक्षण कोई alert नहीं होता। यह एक ऐसी machine होती है जो दो हफ़्ते तक धीमी महसूस होती है और एक bandwidth graph जो आपके किए किसी भी काम से मेल नहीं खाता। service को loopback पर ही रखें, और उसके आगे कुछ ऐसा लगाएँ जो पूछे कि call कौन कर रहा है।
अगर इस machine के बाहर किसी को भी मॉडल की ज़रूरत नहीं, तो यहीं रुक जाएँ — आपका काम पहले ही पूरा हो चुका है। Loopback के साथ एक firewall ही पूरा जवाब है, और उसी VPS पर चल रहा कोई एजेंट, कोई automation stack या कोई web app आगे बताई किसी भी चीज़ के बिना 127.0.0.1 पर मॉडल तक पहुँच जाता है। आगे तभी बढ़ें जब किसी दूसरी machine पर मौजूद किसी चीज़ को इसे call करना हो।
proxy, और टोकन। एक लंबा random टोकन generate करें, एक A record को box पर point करें, और certificate व दरवाज़ा दोनों Caddy को संभालने दें:
openssl rand -hex 32 # → the bearer token, store it in a password manager
apt install -y caddy
/etc/caddy/Caddyfile
llm.example.com {
@unauthorised not header Authorization "Bearer PASTE_THE_HEX_TOKEN_HERE"
respond @unauthorised "unauthorised" 401
reverse_proxy 127.0.0.1:11434 {
# Generation is slow by nature — do not let the proxy give up first.
transport http {
read_timeout 10m
}
}
}
systemctl reload caddy
ufw allow 80,443/tcp
ufw status # 11434 must appear nowhere
basic authentication के बजाय bearer टोकन चुनने में एक छोटी-सी elegance है। Ollama एक OpenAI-compatible API देता है, हर OpenAI client अपनी key को ठीक उसी header के रूप में भेजता है, तो जो टोकन आपने अभी generate किया वही वह API key बन जाता है जिसे आपके applications पहले से carry करना जानते हैं। किसी custom header की ज़रूरत नहीं, और access को rotate करना बस Caddyfile की एक लाइन और caller पर एक environment variable भर है।
किसी ऐसी machine से verify करें जो server न हो। पहली call को मना कर देना चाहिए और दूसरी को जवाब देना चाहिए:
curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
# → 401
curl -s https://llm.example.com/api/tags -H "Authorization: Bearer THE_TOKEN" | jq '.models[].name'
# → the list of models you pulled
अगर मॉडल को आपकी बजाय एजेंटों द्वारा call किया जाना है, तो exposure वाला सवाल remote MCP server होस्ट करने की गाइड में ज़्यादा पूरी तरह से समझाया गया है — TLS, टोकन और कहाँ से क्या reachable होना चाहिए, इसी तर्क को उस service पर लागू करते हुए जो टोकन नहीं बल्कि tools देती है।
Ollama अपने API के साथ-साथ /v1 पर एक OpenAI-compatible surface भी देता है। पूरी integration की कहानी बस इतनी है: OpenAI के लिए बनी कोई भी चीज़ — official SDKs, framework wrappers, automation nodes — बस base URL और key बदलने से काम करने लगती है, और कुछ और नहीं बदलता।
curl -s https://llm.example.com/v1/chat/completions \
-H "Authorization: Bearer THE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.1:8b",
"messages": [{"role":"user","content":"Reply with the word OK."}]
}' | jq -r '.choices[0].message.content'
Python से, किसी hosted setup से अलग बस दो लाइनें ऊपर की हैं:
from openai import OpenAI
client = OpenAI(
base_url="https://llm.example.com/v1",
api_key="THE_TOKEN",
)
r = client.chat.completions.create(
model="llama3.1:8b",
messages=[{"role": "user", "content": "Classify: 'the invoice is overdue'"}],
)
print(r.choices[0].message.content)
JSON माँगें, और JSON पाएँ। automation के लिए सबसे काम की एक ही feature है: constrained output। Ollama मॉडल के सही व्यवहार की उम्मीद करने के बजाय जवाब को valid JSON होने पर मजबूर कर सकता है, जो एक छोटे मॉडल को एक अविश्वसनीय narrator से एक भरोसेमंद parser में बदल देता है — और यही फ़र्क़ है एक ऐसे workflow में जो बिना निगरानी के चलता है और एक ऐसे में जो हर चालीसवें item पर टूट जाता है:
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "Extract the total and the currency: Invoice 4021, 1 249,90 EUR due 30 days.",
"format": "json",
"stream": false
}' | jq -r .response
# → {"total": 1249.90, "currency": "EUR"}
किसी automation stack में भी यही लागू होता है: n8n में एक dedicated Ollama node आता है, और उसका OpenAI node एक custom base URL स्वीकार करता है, तो एक मौजूदा workflow सिर्फ़ एक credential बदलकर local inference पर चला जाता है। n8n self-hosting गाइड automation engine को ख़ुद कवर करती है; अगर हो सके तो दोनों को अलग-अलग boxes पर चलाएँ, क्योंकि 700 MB पर idle रहने वाला engine और पाँच gigabyte माँगने वाला मॉडल, आठ-gigabyte वाली machine पर एक-दूसरे के नाख़ुश पड़ोसी होते हैं।
और embeddings endpoint, जहाँ यह box अपनी क़ीमत असल में चुकाता है। Embedding मॉडल generation मॉडल से दो order of magnitude छोटे होते हैं और वे हर chunk पर एक pass करते हैं जिसमें कुछ generate नहीं करना होता, इसलिए एक CPU उन्हें इतनी रफ़्तार से संभाल लेता है जो instant जैसी महसूस होती है:
ollama pull nomic-embed-text # ~275 MB
curl -s http://127.0.0.1:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["the first chunk of a document", "the second chunk"]
}' | jq '.embeddings | length'
context को cap करें। context की लंबाई ही memory के इस्तेमाल का मुख्य dial है, और default एक छोटे box को जितनी ज़रूरत है उससे ज़्यादा उदार है। इसे globally उतना ही set करें जितना आपके सबसे लंबे वास्तविक prompt को असल में चाहिए — ज़्यादातर classification और extraction का काम चार हज़ार टोकन के अंदर आराम से हो जाता है — और उस दुर्लभ call पर per request इसे बढ़ा लें जिसे ज़्यादा चाहिए:
Environment="OLLAMA_CONTEXT_LENGTH=4096"
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "…a long document…",
"options": { "num_ctx": 16384 },
"stream": false
}'
तय करें कि मॉडल कितनी देर memory में रहेगा। resident मॉडल को call करना तुरंत होता है और यह कई gigabyte को बंधक बना लेता है। किसी ऐसी machine पर जो सिर्फ़ inference के लिए है, इसे हमेशा loaded रखें; किसी shared machine पर, कुछ समय बाद इसे गिर जाने दें। यह value per request भी तय होती है, तो एक nightly batch अपने run के लिए मॉडल को pin कर सकता है और अंत में release कर सकता है:
OLLAMA_KEEP_ALIVE=-1 # resident until the service restarts
OLLAMA_KEEP_ALIVE=30m # a sensible default on a shared box
OLLAMA_KEEP_ALIVE=0 # unload immediately after each request
ollama ps # what is resident right now, and how much it holds
queue को serialise करें। एक ही मॉडल पर दो concurrent requests दोगुनी रफ़्तार से नहीं चलतीं; वे एक ही saturated memory path के लिए होड़ करती हैं और हर एक धीमी हो जाती है, और अगर Ollama उन्हें serve करने के लिए दूसरी copy load करने का फ़ैसला करे तो box का RAM ख़त्म हो जाता है। इस तरह के hardware पर एक बार में एक request, आगे एक queue के साथ, ही सबसे तेज़ भी है और अकेला safe configuration भी — यही वजह है कि OLLAMA_NUM_PARALLEL और OLLAMA_MAX_LOADED_MODELS को चरण 02 में ही एक पर pin कर दिया गया था।
disk पर नज़र रखें। चार मॉडलों को compare करने पर चार मॉडल पीछे रह जाते हैं, और पाँच-पाँच gigabyte के हिसाब से एक disk चुपचाप भरती जाती है जबकि कोई शिकायत नहीं करता। cleanup को comparison का ही हिस्सा बनाएँ, बाद के किसी काम की तरह नहीं:
ollama list
du -sh /var/lib/ollama/models
ollama rm mistral:7b qwen2.5:14b
आख़िर में, उसी चीज़ का backup लें जो reproducible नहीं है। मॉडल weights reproducible हैं — एक pull उन्हें वापस ला देता है। जो चीज़ किसी repository के लायक़ है वह है configuration, Caddyfile, टोकन, वे prompt जिन्हें आपने तीन हफ़्तों में refine किया, और अगर आपने एक बनाया है तो आपके retrieval के पीछे का vector index। encrypted backups गाइड इसकी mechanics बताता है; इस box के लिए include list छोटी है और लिख रखने लायक़ है।
ऊपर की हर बात generation के बारे में थी, जो वह हिस्सा है जिसे एक CPU धीरे करता है। Retrieval ज़्यादातर उपयोगी systems का दूसरा आधा हिस्सा है और यह पूरी तस्वीर पलट देता है — यही वजह है कि इस पेज पर सबसे सस्ता टियर भी कुछ सचमुच काम की चीज़ कर सकता है, भले ही आप उस पर कभी एक भी टोकन generate न करें।
एक embedding मॉडल text के एक टुकड़े को एक vector में बदल देता है। यह gigabyte में नहीं बल्कि सैकड़ों megabyte में मापा जाता है, यह हर chunk पर ठीक एक forward pass करता है, और memory bandwidth से बंधा कोई token-by-token loop नहीं होता। जिस box पर एक 8B मॉडल तीन शब्द प्रति सेकंड लिखता है, उसी box पर एक embedding मॉडल किसी document library को उस रफ़्तार से process करेगा जो file copying जैसी महसूस होती है।
इसका स्वरूप। अपने documents को कुछ सौ शब्दों वाले chunks में बाँट लें। हर chunk को एक बार embed करें और उसका vector store कर लें। सवाल के वक़्त, सवाल को embed करें, सबसे पास वाले मुट्ठी-भर chunks ढूँढ़ें, और उन्हें सवाल के साथ किसी मॉडल को दे दें। storage के लिए कुछ भी exotic नहीं चाहिए: एक ही VPS पर दसियों हज़ार chunks के लिए एक vector extension वाला SQLite database काफ़ी है, और pgvector के साथ PostgreSQL इससे भी काफ़ी आगे तक संभाल लेता है। एक dedicated vector database बाद में चाहने के लिए ठीक चीज़ है, पर पहले ही दिन एक फ़ालतू dependency है।
यह रफ़्तार से भी ज़्यादा क्यों मायने रखता है। देखिए हर आधा हिस्सा किसे छूता है। generation step एक सवाल और कुछ paragraph देखता है। embedding step <em>आपके पास मौजूद हर document</em> देखता है — पूरा archive, हर contract, हर note, हर message, जो मॉडल से एक बार में एक chunk करके गुज़ारा जाता है। अगर यह step किसी hosted endpoint पर चलता है, तो index होने के लिए आपका पूरा corpus किसी तीसरे पक्ष को भेजा जा चुका है। अगर यह आपकी अपनी machine पर चलता है, तो उसमें से कुछ भी कहीं नहीं गया।
यह उन सबके लिए एक सचमुच अच्छा hybrid बनाता है जो frontier quality नहीं छोड़ना चाहते: locally index करें, locally retrieve करें, और जब जवाब बेहतरीन होना ज़रूरी हो तभी सिर्फ़ सवाल और तीन retrieved chunks किसी hosted मॉडल को भेजें। corpus घर पर ही रहता है; उसका बस एक पतला हिस्सा बाहर जाता है, और वह भी सिर्फ़ ज़रूरत पड़ने पर।
इस site पर दो पड़ोसी इस pattern को ठोस बना देते हैं। एक self-hosted SearXNG retrieval वाली परत को एक corpus की बजाय खुले web के लिए एक private front-end दे देता है; एक self-hosted document store उसे corpus दे देता है। ये दोनों, मॉडल के साथ मिलकर, ऐसे टियर्स पर फ़िट हो जाते हैं जिनकी महीने की क़ीमत एक अकेली hosted seat से भी कम है।
लोग मॉडल की privacy के बारे में ऐसे सोचते हैं जैसे risk output में हो। ऐसा नहीं है। output तो सामान्य text है; हज़ार और लोगों को भी कुछ मिलता-जुलता ही मिला होगा। जो चीज़ असल में सब कुछ खोल देती है वह है input — और एक साल के inputs किसी संस्था की एक हैरान करने वाली मुकम्मल तस्वीर बन जाते हैं।
सोचिए कि एक request log में असल में क्या होता है। वह contract जो आपने summarise कराने के लिए paste किया था। वह customer email जिसे classify करने को कहा, जिसमें customer भी मौजूद है। medical letter, salary का आँकड़ा, वह resignation जो आप draft कर रहे थे, किसी ऐसे repository का code जो public नहीं है। फिर उसके आसपास का metadata: कौन-से सवाल, किस क्रम में, किस समय, किस address से, कितने महीनों में। कोई भी दस्तावेज़ पर यह लिखकर sign नहीं करता कि “यह हमारी strategy है” — लेकिन सवालों का क्रम ही वह दस्तावेज़ है, जो आपके द्वारा, एक बार में एक call, ईमानदारी से बनाया गया है।
पहली परत — endpoint क्या रखता है। गंभीर providers गंभीर policies छापते हैं, और अच्छे providers सचमुच business API traffic पर train नहीं करते। पर यह retain न करने जैसा वादा नहीं है। Requests आमतौर पर abuse monitoring के लिए कुछ समय तक store होती हैं, तय शर्तों के तहत staff तक पहुँच में रहती हैं, और legal process के तहत produce की जा सकती हैं — यही एक बड़े platform को चलाने का सही तरीक़ा है, और यही उस text के लिए बिलकुल ग़लत जगह है जिसे आप किसी अजनबी को email नहीं करेंगे। आपकी अपनी machine पर चलने वाले मॉडल के पास ऐसा कोई log नहीं होता, जब तक आप ख़ुद एक न बनाएँ।
दूसरी परत — वह पहचान जिससे log जुड़ा होता है। सिर्फ़ retention exposure का आधा हिस्सा है। दूसरा आधा वह key है जिससे यह जुड़ता है: एक account, एक company का नाम, एक billing address, एक card। यही जोड़ है जो “किसी ने competitor ख़रीदने के बारे में पूछा” को बदलकर “उस मंगलवार को इस company ने पूछा” बना देता है। equation से मॉडल हटाने से retention हट जाता है; machine से पहचान हटाने से वह जोड़ हट जाता है। बिना email address या identity document के, किसी Nordic jurisdiction में खोला गया, Monero में settle किया गया एक VPS, उसी क़दम का दूसरा आधा हिस्सा है।
तीसरी परत — वे logs जो आप ख़ुद लिखते हैं। Self-hosting risk को मिटाता नहीं, बस उसकी जगह बदल देता है, और यह साफ़-साफ़ देखने लायक़ है कि वह कहाँ जाकर टिकता है। आपका application शायद अपने ही prompts log करता होगा। आपका reverse proxy हर request line log करता है। दो महीने पहले किसी debugging session ने journal में verbose output छोड़ दिया था। मॉडल ख़ुद calls के बीच कुछ नहीं रखता, लेकिन उसके आसपास की मशीनरी सब कुछ रख सकती है — इसलिए जान-बूझकर तय करें कि क्या लिखा जाए, उस पर retention set करें, और उस log को उसी standard पर रखें जिसे आप किसी और से मानने को तैयार नहीं थे।
इनमें से कुछ भी एक local मॉडल को अपने-आप privacy की गारंटी नहीं बनाता। यह इसे बस वह एक architecture बनाता है जहाँ गारंटी देना आपके हाथ में है: text उसी hardware पर रहता है जो आपने rent किया, उसी jurisdiction के तहत जो आपने चुना, उसी टोकन के पीछे जो आपने ख़ुद जारी किया, और यह किसी और के आगे जवाबदेह नहीं है।
मॉडल और उसका context cache मिलकर RAM से ज़्यादा हो गए और kernel हर टोकन पर weights को page करने लगा। memory में फ़िट हों या एक साइज़ छोटा मॉडल लें — इसके बीच का कोई setting नहीं है।
किसी client को काम कराने के लिए OLLAMA_HOST को 0.0.0.0 पर set कर दिया गया था। API में बिलकुल भी authentication नहीं है, और 11434 scan होता है। Loopback और साथ में एक ऐसा proxy जो टोकन चेक करे।
एक interactive assistant के लिए 32B मॉडल चुना गया। आकार को इंटरैक्शन के मुताबिक़ रखें: interactive के लिए छोटा मॉडल, quality के लिए asynchronous तरीक़ा।
बढ़ती हुई conversation cache को भी बढ़ाती है, और हर turn पर पूरी history फिर से पढ़ी जाती है। context को cap करें, और हमेशा जोड़ते जाने के बजाय एक नई शुरू करें।
मॉडल डिज़ाइन के हिसाब से आख़िरी call के बाद भी resident रहता है। OLLAMA_KEEP_ALIVE को box के हिसाब से set करें, और किसी और चीज़ को दोष देने से पहले ollama ps पढ़ें।
पाँच-पाँच gigabyte के चार candidates, कोई भी हटाया नहीं गया। ollama rm को comparison का हिस्सा बनाएँ, और जब disk अलर्ट बजें तो मॉडल directory ज़रूर चेक करें।
दस सवाल जो तय करते हैं कि आपके सोचे हुए काम के लिए CPU-only मॉडल सही tool है या नहीं।
हाँ, रफ़्तार को लेकर एक ईमानदार caveat के साथ। एक quantised मॉडल आम server CPUs पर बिलकुल ठीक चलता है — weights RAM में बैठे रहते हैं, गणित पूरी तरह पहुँच में है, और इस पूरी प्रक्रिया में कहीं भी graphics card की ज़रूरत नहीं। एक GPU जो चीज़ ख़रीदता है वह है memory bandwidth, और bandwidth ही generation की रफ़्तार तय करती है। तो एक CPU-only box, मॉडल के हिसाब से, सही और पूरा जवाब कुछ शब्दों से लेकर कुछ दर्जन शब्द प्रति सेकंड के बीच कहीं देगा। यह किसी chat window के लिए धीमा है और उस काम के लिए बिलकुल ठीक है जिसे ज़्यादातर लोग असल में automate करते हैं: किसी message को classify करना, किसी document से structured JSON निकालना, किसी page को summarise करना, search के लिए text embed करना, किसी paragraph को rewrite करना। सवाल कभी “क्या यह हो सकता है” नहीं होता — सवाल यह होता है “किस रफ़्तार पर, और क्या वह रफ़्तार इस काम के लिए मायने रखती है”।
किसी के भी benchmark पर भरोसा करने के बजाय — हमारे भी नहीं — ख़ुद गणित करें। एक dense मॉडल एक टोकन बनाने के लिए अपने हर weight को memory से पढ़ता है, इसलिए ceiling लगभग memory bandwidth को मॉडल के आकार से भाग देने पर मिलती है। क़रीब 2 GB में quantised एक 3B मॉडल, effective 20 GB/s वाली machine पर, लगभग 10 टोकन प्रति सेकंड की ceiling रखता है; 4.4 GB पर एक 7B लगभग 4.5 पर; 20 GB पर एक 32B 1 से कम पर। असली नंबर ceiling से नीचे ही रहते हैं — मान लीजिए 50 से 70 प्रतिशत — और host, पड़ोसियों और thread count के हिसाब से बदलते हैं। Prompt processing बिलकुल अलग मामला है: यह compute-bound है, कई गुना तेज़ चलता है, और यही वजह है कि किसी लंबे document को summarise करना आरामदायक है जबकि किसी बड़े मॉडल से chat करना नहीं।
Q4_K_M पर एक 8B-class instruct मॉडल, जो क़रीब 4.5 से 5 GB में आता है और operating system तथा context cache के लिए जगह छोड़ता है। यह आकार अभी का sweet spot है: instructions को भरोसे से follow करने, माँगने पर valid JSON बनाने, summarise, classify और rewrite करने के लिए काफ़ी अच्छा; responsive बने रहने के लिए काफ़ी छोटा। इससे नीचे, एक 3B मॉडल classification, tagging और routing के लिए सचमुच उपयोगी है और लगभग दोगुना तेज़। इससे ऊपर, एक 14B multi-step reasoning में काफ़ी बेहतर है और लगभग आधी रफ़्तार का, जो batch काम के लिए सही सौदा है और किसी भी interactive काम के लिए ख़राब। 8B से शुरू करें, मापें, फिर जिस दिशा में measurement इशारा करे उस दिशा में बढ़ें।
quantised file का आकार, साथ में context cache, साथ में system के लिए जगह — और कुल मिलाकर यह फ़िट होना ही चाहिए, क्योंकि यहाँ फ़ेल होने का तरीक़ा धीमापन नहीं बल्कि collapse है। जब मॉडल फ़िट नहीं होता, तो kernel मॉडल के weights को disk पर swap करने लगता है और जो generation चार सेकंड में होना चाहिए वह चार मिनट लेता है जबकि load average दहाइयों में चढ़ जाता है। Q4_K_M पर एक काम-चलाऊ नियम के तौर पर: एक 3B मॉडल क़रीब 2 GB का है, एक 8B क़रीब 5 GB का, एक 14B क़रीब 9 GB का, एक 32B क़रीब 20 GB का, एक 70B क़रीब 40 GB का। Debian और उसकी services के लिए दो gigabyte और जोड़ें, और आप जितना लंबा context allow करते हैं उसके हिसाब से key-value cache के लिए एक से चार gigabyte और। फिर उस टियर को ख़रीदें जो जवाब से एक पायदान ऊपर हो, ठीक उतने का मेल खाने वाला नहीं।
Ollama दरअसल llama.cpp ही है, जिसके चारों ओर एक model registry, एक REST API और एक systemd service लिपटी हुई है। जब तक कोई ख़ास वजह न हो, Ollama ही इस्तेमाल करें: एक install command, GGUF files ढूँढ़ने के बजाय ollama pull, एक OpenAI-compatible endpoint, और thread count व memory के लिए समझदार defaults। llama.cpp की तरफ़ सीधे तब जाएँ जब आपको कोई ऐसा flag चाहिए जो Ollama expose नहीं करता, जब आपको reproducibility के लिए कोई exact build pin करनी हो, या जब आप हमेशा के लिए एक ही configuration के साथ एक मॉडल चला रहे हों और किसी daemon से कुछ भी manage नहीं करवाना चाहते। दोनों एक ही weights को एक ही रफ़्तार से चलाते हैं; फ़र्क़ पूरी तरह operations में है।
नहीं, और इसके उलट मान लेना आपकी पूरी दोपहर बर्बाद कर देगा। किसी API के पीछे बैठा एक frontier मॉडल किसी भी virtual machine पर फ़िट होने वाली चीज़ से बड़ा होता है और hard reasoning, लंबे context और code में बेहतर होगा। एक छोटा local मॉडल असल में जिस चीज़ में मुक़ाबला कर पाता है वह है असली काम का विशाल बीचोंबीच हिस्सा: यह तय करना कि कोई email छह categories में से किसमें आता है, किसी invoice से पाँच fields निकालना, किसी support thread को summarise करना, किसी description को rewrite करना, किसी document को tag करना, यह judge करना कि दो records एक ही व्यक्ति के हैं या नहीं। इस तरह के काम में एक 8B और एक frontier मॉडल के बीच फ़र्क़ छोटा है, cost का फ़र्क़ पूरा है, और privacy का फ़र्क़ बिलकुल absolute है। सही रवैया “API को replace करो” नहीं बल्कि “उस नब्बे प्रतिशत को भेजना बंद करो जिसे कभी बाहर जाने की ज़रूरत ही नहीं थी” है।
नहीं — बिल्कुल भी नहीं, और यह इस गाइड का सबसे अहम operational तथ्य है। न कोई password है, न कोई टोकन, न कोई user मॉडल। जो कोई भी port 11434 पर TCP connection खोल सकता है वह text generate कर सकता है, आपके मॉडल की सूची देख सकता है, नए pull कर सकता है और मौजूदा मिटा सकता है। यह port लगातार scan होता है, और असुरक्षित instances अजनबियों को free compute के रूप में मिल जाते हैं और इस्तेमाल हो जाते हैं — जो पहले एक अजीब load average के रूप में दिखता है और बाद में bandwidth के bill के रूप में। Ollama को 127.0.0.1 तक ही bound रखें, उसके आगे एक reverse proxy लगाएँ, वहीं TLS terminate करें, और proxy पर bearer टोकन या client certificate अनिवार्य करें। अगर box के बाहर किसी को मॉडल की ज़रूरत नहीं, तो उसे बिलकुल भी expose न करें।
हाँ, और आमतौर पर इसमें बस एक field बदलना होता है। Ollama /v1 पर एक OpenAI-compatible API देता है, तो कोई भी client जो आपको base URL set करने देता है — OpenAI के SDKs, LangChain, n8n का OpenAI node, ज़्यादातर agent frameworks — https://your-host/v1 पर point करके और key की जगह कोई भी non-empty string भेजकर इससे बात करने लगेगा। n8n में एक dedicated Ollama node भी आता है। practice में जो pattern अच्छे से काम करता है वह एक hybrid है: बड़े, उबाऊ, high-volume calls को local मॉडल पर भेजें और hosted API को उन थोड़े-से steps के लिए बचाकर रखें जिन्हें सचमुच frontier reasoning चाहिए, साथ में एक fallback भी अगर local वाला valid JSON बनाने से मना कर दे।
यह इस पूरे पेज की सबसे best-value चीज़ है। Embedding मॉडल बहुत छोटे होते हैं — gigabyte नहीं बल्कि दसियों से सैकड़ों megabyte — और वे हर chunk पर एक forward pass चलाते हैं, कोई token-by-token generation नहीं, इसलिए एक CPU इन्हें ख़ुशी-ख़ुशी चबा जाता है। मतलब यह कि किसी RAG system का पूरा retrieval वाला आधा हिस्सा — अपने documents को index करना, query को embed करना, सबसे पास वाले chunks ढूँढ़ना — सबसे सस्ते टियर पर भी आराम से चलता है, और यही वह आधा हिस्सा भी है जो आपके पास मौजूद हर document को छूता है। भले ही आप generation वाले step को किसी hosted API पर रखने का फ़ैसला करें, embedding वाले step को अपनी ही machine पर ले जाना आपके corpus को किसी और की मशीन से दूर रखता है।
तीन वजहें, अहमियत के बढ़ते क्रम में। Cost की एक shape होती है: एक API तब तक सस्ता है जब तक वह नहीं है, और एक महीने में पचास हज़ार messages classify करने वाले workflow का bill बढ़ता जाता है जबकि $7.90 वाला VPS नहीं। Availability: कोई rate limit नहीं, जिस मॉडल के इर्द-गिर्द आपने सब बनाया उसकी कोई deprecation नहीं, किसी और के status page पर कोई outage नहीं। और वह वजह जो सबसे ज़्यादा तय करती है — आपके prompts ही वह सबसे ज़्यादा खोलने वाला text है जो आप बनाते हैं। जवाब नहीं, सवाल। आपने क्या पूछा, किसके बारे में, किस दिन, किस क्रम में। एक hosted endpoint यह सब देखता है, एक billing पहचान से जुड़ा हुआ। बिना identity document के rent की गई किसी machine पर चलने वाला, किसी Nordic jurisdiction में, Monero में paid मॉडल, वही text देखता है और किसी को कुछ नहीं बताता।
Garrison (4 vCPU, 8 GB, 240 GB NVMe, $7.90/mo) context cache और system के लिए जगह के साथ एक 8B मॉडल चलाता है — यही वह टियर है जिससे ज़्यादातर लोगों को शुरुआत करनी चाहिए। Ravelin 14B और लंबे contexts के लिए मेमोरी दोगुनी कर देता है। signup पर कोई email नहीं, कोई identity document नहीं, और कोई per-token bill नहीं।
अंतिम review · 2026-08-24 · स्रोत · Ollama documentation और API reference, llama.cpp documentation, Caddy reverse-proxy documentation, इस्तेमाल किए गए quantised builds के लिए published model cards · आवृत्ति · वार्षिक
This guide is one spoke of a larger series. The pillar walks the three privacy layers end to end — the sibling spokes below dive into the specifics.
Three independent layers — signup, payment, network — explained, legal context included, common mistakes flagged.
Deploy your own MCP server on a no-KYC VPS — TLS, streamable HTTP, OAuth.
Host an MCP server with no ID — the privacy stack, crypto-paid.
एजेंट को अपने लैपटॉप से हटाएं — आकार तय करना, systemd, secrets, खर्च की सीमाएँ।
Docker Compose, PostgreSQL, काम करते webhooks — automation जो आपका अपना है।