اجرای llama-server روی VPS با systemd
آموزش گامبهگام اجرای llama-server با استفاده از تگهای ثابت، اتصال به API سازگار با OpenAI و تنظیم محدودیت حافظه در systemd برای جلوگیری از کرش کردن مدلهای GGUF روی VPS.
آنچه میسازید
اجرای سرور llama.cpp روی یک VPS به معنای استفاده از یک فایل اجرایی واحد، یعنی llama-server، است که یک فایل مدل GGUF را بارگذاری کرده و به درخواستهای HTTP در قالب یک API سازگار با OpenAI پاسخ میدهد. کافی است هر کلاینت OpenAI را به http://127.0.0.1:8080/v1 متصل کنید تا کار کند. نصب این برنامه، نیمهٔ آسان کار است.
بخش باقیمانده، عملیات نگهداری است: تعیین نسخه (pin)، محدود کردن پورت به localhost، نوشتن یک unit برای systemd و تصمیمگیری دربارهٔ رفتار سیستم هنگام اتمام حافظه (RAM). این راهنما به همین موارد میپردازد. اگر هنوز بین دو گزینهٔ اصلی تصمیم نگرفتهاید، ابتدا تفاوتها و اولویتهای Ollama و llama.cpp را مطالعه کنید، زیرا این راهنما دقیقاً همان جزئیات اجرایی است که در آن مقایسه نادیده گرفته شده است.
یک تگ انتشار انتخاب کرده و آن را یادداشت کنید
پروژه llama.cpp تقریباً برای هر merge یک تگ انتشار در نظر میگیرد، بنابراین این تگها در واقع شمارههای ساخت (build numbers) هستند. در تاریخ 18 اوت 2026، تگ b10488 جدیدترین نسخه است. هیچ شاخه پایداری با عمر طولانی وجود ندارد، به این معنی که نسخه "latest" دائماً در حال تغییر است و نسخهای که تست کردهاید، تنها نسخهای است که میتوانید از آن پشتیبانی کنید. یک تگ را انتخاب کنید، آن را ثبت کنید و از همان رشته در زمان clone کردن، در نام فایل اجرایی و در یادداشتهای خود استفاده کنید.
هر تگ همچنین شامل آرشیوهای از پیش ساختهشده است. برای یک VPS با معماری x86 و فقط CPU، این فایل llama-b10488-bin-ubuntu-x64.tar.gz است و اگر از یک VPS با معماری ARM به جای x86 استفاده میکنید، آرشیو arm64 در کنار آن قرار دارد.
curl -LO https://github.com/ggml-org/llama.cpp/releases/download/b10488/llama-b10488-bin-ubuntu-x64.tar.gz
tar tf llama-b10488-bin-ubuntu-x64.tar.gz | headپیش از استخراج آرشیو، محتویات آن را لیست کنید تا بدانید فایلها در چه مسیری قرار میگیرند. این فایلهای اجرایی با کتابخانه C مربوط به ایمیجی که آنها را ساخته است لینک شدهاند؛ بنابراین در توزیعهای قدیمیتر، هنگام اجرا با خطایی مواجه میشوید که به یک نسخه GLIBC_ اشاره دارد که نصب نشده است. کامپایل از سورس روی یک VPS کوچک تنها چند دقیقه زمان میبرد و این دسته از مشکلات را بهطور کامل برطرف میکند، بنابراین مسیر پیشنهادی در ادامه آمده است.
ساخت llama-server از یک تگ ثابت (pinned)
sudo apt update
sudo apt install -y build-essential cmake git libssl-dev
git clone --depth 1 --branch b10488 https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF
cmake --build build --config Release -t llama-server -j 2دستور --branch b10488 روی یک --depth 1، دقیقاً همان تگ را checkout میکند و هیچ چیز دیگری را تغییر نمیدهد؛ بنابراین در حین کار، نسخهٔ build دچار تغییر ناخواسته نمیشود.
libssl-dev اهمیت دارد زیرا گزینهٔ LLAMA_OPENSSL بهصورت پیشفرض فعال است و همین گزینه است که به باینری اجازه میدهد بعداً مدلها را از طریق HTTPS دانلود کند. بدون این هدرها، مرحلهٔ configure با شکست مواجه میشود.
-DBUILD_SHARED_LIBS=OFF به شما یک باینری یکپارچه و مستقل میدهد. در حالت پیشفرض، build کتابخانههای اشتراکی را در کنار فایل اجرایی قرار میدهد؛ بنابراین اگر فقط فایل اجرایی را به /usr/local/bin کپی کنید، با خطای error while loading shared libraries: libllama.so مواجه خواهید شد.
-t llama-server فقط هدف server را build میکند. در حالت پیشفرض، build سایر ابزارها و تستها را نیز کامپایل میکند که در یک VPS با دو هسته، چندین دقیقه زمان اضافی صرف فایلهایی میشود که هرگز از آنها استفاده نخواهید کرد.
-j 2 عمدی است. هر job کامپایل موازی، فضای کاری (working set) مخصوص خود را اشغال میکند؛ بنابراین -j $(nproc) در یک پلن کوچک با c++: fatal error: Killed signal terminated program cc1plus به پایان میرسد که همان مکانیزم OOM killer هسته است که کامپایلر را متوقف میکند. تعداد jobها را کاهش دهید یا برای عملیات build، فضای swap اضافه کنید.
یک فلگ که ممکن است بخواهید تغییر دهید: GGML_NATIVE بهصورت پیشفرض روشن است، بنابراین کامپایلر دقیقاً CPU همان ماشینی را هدف قرار میدهد که build روی آن انجام میشود. این همان چیزی است که هنگام build روی ماشینی که قرار است برنامه را اجرا کند، به آن نیاز دارید. اگر یک بار build میکنید و باینری را به میزبان دیگری کپی میکنید، -DGGML_NATIVE=OFF را اضافه کنید؛ زیرا باینری که از دستوراتی استفاده میکند که CPU مقصد فاقد آنهاست، در اولین inference با خطای Illegal instruction (core dumped) متوقف میشود.
آن را با نامی نصب کنید که شامل شماره تگ باشد.
./build/bin/llama-server --version
sudo install -m 755 build/bin/llama-server /usr/local/bin/llama-server-b10488
sudo ln -sfn /usr/local/bin/llama-server-b10488 /usr/local/bin/llama-server--version شماره build و commit را چاپ میکند. این مقدار باید با تگی که checkout کردهاید مطابقت داشته باشد. اگر مطابقت ندارد، شما چیز دیگری را build کردهاید. نگه داشتن شماره در نام فایل و اشاره دادن یک symlink به آن، به این معنی است که ارتقا فقط با یک ln -sfn و یک restart انجام میشود و بازگشت به نسخه قبلی (rollback) نیز با همان دستور و شماره نسخه قدیمی امکانپذیر است.
دریافت مدل GGUF و بررسی اولیه دیسک
فرمت GGUF یک فایل واحد است که توسط llama.cpp بارگذاری میشود. این فایل شامل وزنها، توکنایزر و متادیتا است، بنابراین نیاز به نصب هیچ مورد دیگری نیست. پسوند نام فایل نشاندهنده کوانتایزیشن (quantisation) است که دقت ذخیرهسازی وزنها را تعیین میکند: Q4_K_M یک ترکیب 4-بیتی، Q8_0 نسخه 8-بیتی و f16 فایل بدون کوانتایزیشن با دقت نیمممیز شناور (half-precision) است.
پیش از دانلود هر فایلی، یک حساب کاربری سرویس و یک دایرکتوری برای مدل ایجاد کنید.
sudo useradd --system --home /srv/llama --create-home --shell /usr/sbin/nologin llama
sudo install -d -o llama -g llama /srv/models
df -h /srvسرور میتواند مدل را مستقیماً با استفاده از -hf دریافت کند که سریعترین راه برای اطمینان از صحت عملکرد build شماست.
sudo -u llama env LLAMA_CACHE=/srv/models /usr/local/bin/llama-server \
-hf ggml-org/gemma-3-1b-it-GGUF:Q4_K_M --host 127.0.0.1 --port 8080دستور LLAMA_CACHE دایرکتوری دانلود را تعیین میکند. بدون آن، فایل در مسیر ~/.cache/llama.cpp تحت حساب کاربری که دستور را اجرا کرده ذخیره میشود؛ این مکان برای سرویسی که قصد دارید دایرکتوری خانگیاش را غیرقابلخواندن کنید، مناسب نیست. پس از آن ls -lh /srv/models را اجرا کنید، زیرا نام فایل کششده از نام مخزن (repository) مشتق میشود و نه از نام اصلی فایل.
برای یک سرویس، فایل را در مسیری که انتخاب کردهاید دانلود کنید تا فایل unit شما یک مقصد ثابت برای ارجاع داشته باشد.
sudo -u llama curl -L --output-dir /srv/models -O \
https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.ggufدیسک اولین محدودیتی است که کاربران با آن مواجه میشوند. اینها اندازههای فایل منتشرشده برای دو مدل هستند که در تاریخ 18 آگوست 2026 بررسی شدهاند.
The data behind this chart
[
{
"label": "gemma-3-1b-it Q4_K_M",
"size_gb": 0.81
},
{
"label": "gemma-3-1b-it Q8_0",
"size_gb": 1.07
},
{
"label": "gemma-3-1b-it f16",
"size_gb": 2.01
},
{
"label": "gpt-oss-20b MXFP4",
"size_gb": 12.11
}
]فایل 4-بیتی برای مدل 1B برابر با 0.81 گیگابایت است. همان مدل بدون کوانتایزیشن 2.01 گیگابایت است، بنابراین انتخاب فرمت، عدد را بیش از دو برابر تغییر میدهد. یک مدل 20B با فرمت MXFP4 برابر با 12.11 گیگابایت است که در بسیاری از پلنهای پایه در دیسک جا نمیشود و پس از آن نیز باید در حافظه بارگذاری شود. اگر به خانواده خاصی از مدلها نظر دارید، تمرین مشابه برای تخمین اندازه مدلهای GLM نشان میدهد که چگونه مدلهای اصلی بهسرعت از محدوده قیمتی یک VPS خارج میشوند، در حالی که نسخههای کوچکتر بهراحتی در آن جای میگیرند.
پیش از هر دانلود، df -h را بررسی کنید. پر شدن فایلسیستم ریشه در حین یک انتقال 12 گیگابایتی، باعث اختلال در تمام فرآیندهایی میشود که نیاز به نوشتن دارند، از جمله journal.
یکبار آن را بهصورت دستی اجرا کنید و بررسی نمایید
sudo -u llama /usr/local/bin/llama-server \
--model /srv/models/gemma-3-1b-it-Q4_K_M.gguf \
--host 127.0.0.1 --port 8080 \
--ctx-size 4096 --parallel 1 --threads 2 --no-webuiدر یک نشست (session) دوم، از سرور بپرسید که آیا آماده است یا خیر.
curl -s http://127.0.0.1:8080/healthهنگامی که فایل در حال بارگذاری است، خطای HTTP 503 و بدنه زیر را دریافت میکنید:
{"error":{"code":503,"message":"Loading model","type":"unavailable_error"}}وقتی سرور آماده باشد، بدنه پاسخ {"status": "ok" } خواهد بود. سپس یک درخواست واقعی ارسال کنید.
curl -s http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"local","messages":[{"role":"user","content":"Say hello in five words."}]}'یک شیء JSON با آرایه choices نشاندهنده عملکرد صحیح سرور است. فیلد model به این دلیل وجود دارد که کلاینتهای OpenAI همیشه آن را ارسال میکنند. این سرور تنها یک مدل بارگذاریشده دارد، بنابراین از این مقدار برای انتخاب چیزی استفاده نمیشود.
رابط برنامهنویسی سازگار با OpenAI و سایر موارد موجود روی این پورت
POST /v1/chat/completions، POST /v1/completions و POST /v1/embeddings مسیرهای سازگار با OpenAI هستند و GET /v1/models مدل بارگذاریشده را گزارش میدهد. GET /health همان بررسی آمادگی است که در بالا ذکر شد، GET /props تنظیمات فعلی سرور را برمیگرداند و GET /metrics در صورتی که برنامه را با --metrics اجرا کنید، شمارندههای Prometheus را در دسترس قرار میدهد.
هر SDK مربوط به OpenAI به محض اینکه base URL را روی http://127.0.0.1:8080/v1 تنظیم کنید و یک رشته غیرخالی به عنوان API key ارسال کنید، کار میکند. تا زمانی که خودتان --api-key را تنظیم نکنید، هیچ بررسی روی آن کلید انجام نمیشود.
ادعای هیچکس درباره نرخ توان عملیاتی (throughput) را به عنوان عددی برای برنامهریزی خود در نظر نگیرید. سرعت استنتاج CPU به تعداد هستهها، پهنای باند حافظه و همسایگانی که میزبان را با آنها به اشتراک میگذارید بستگی دارد؛ بنابراین تعداد توکن در ثانیه را روی سیستم خودتان اندازهگیری کنید و آن نتیجه را به عنوان حقیقت بپذیرید. زمان سرقتشده توسط یک همسایه پرمصرف (noisy neighbour) در اینجا به صورت سرعت تولیدی ظاهر میشود که ساعت به ساعت تغییر میکند.
سرویس را روی 127.0.0.1 نگه دارید و یک پروکسی در مقابل آن قرار دهید
--host بهصورت پیشفرض روی 127.0.0.1 تنظیم شده است، بنابراین تا زمانی که آن را تغییر ندهید، سرور از خارج غیرقابلدسترسی است. آن را به همان حالت رها کنید. در llama-server هیچ مدل کاربری، محدودیت نرخ (rate limit) یا لاگ حسابرسی (audit log) مفیدی وجود ندارد و تنها کنترل داخلی آن --api-key است که فقط یک رشته متنی را مقایسه میکند. باز گذاشتن پورت استنتاج (inference port) به معنای در اختیار قرار دادن توان پردازشی رایگان برای هر کسی است که آن را پیدا کند؛ اشتباه مشابهی که در مورد Ollama رخ میدهد، پیامدهای یکسانی دارد: ایمنسازی API مدلهای self-hosted در اینجا نیز دقیقاً صدق میکند.
پایاندهی TLS (امنیت لایه انتقال) را در nginx انجام دهید و درخواستها را به پورت loopback پروکسی کنید.
server {
listen 443 ssl;
server_name llm.example.com;
location /v1/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 600s;
}
}proxy_buffering off برای استریم کردن ضروری است. با فعال بودن بافرینگ، nginx رویدادهای ارسالی از سمت سرور (SSE) را تا پایان پاسخ نگه میدارد، در نتیجه کلاینت در سکوت منتظر میماند و سپس کل پاسخ را یکجا دریافت میکند. proxy_read_timeout 600s برای تولیدات طولانی لازم است، زیرا مقدار پیشفرض 60 ثانیه باعث میشود پاسخهای کند به 504 Gateway Time-out تبدیل شوند. گواهی را با استفاده از Certbot و Let's Encrypt در nginx دریافت کنید.
واحد systemd
دستور /etc/systemd/system/llama-server.service را بنویسید.
[Unit]
Description=llama.cpp server
After=network-online.target
Wants=network-online.target
[Service]
User=llama
Group=llama
Environment=LLAMA_ARG_MODEL=/srv/models/gemma-3-1b-it-Q4_K_M.gguf
Environment=LLAMA_ARG_HOST=127.0.0.1
Environment=LLAMA_ARG_PORT=8080
Environment=LLAMA_ARG_CTX_SIZE=4096
Environment=LLAMA_ARG_N_PARALLEL=1
Environment=LLAMA_ARG_THREADS=2
ExecStart=/usr/local/bin/llama-server --no-webui
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
MemoryHigh=3G
MemoryMax=3500M
OOMPolicy=stop
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
[Install]
WantedBy=multi-user.targetتنظیمات در خطوط Environment= قرار دارند، زیرا llama-server برای اکثر پرچمها (flags) متغیرهای LLAMA_ARG_* را میخواند و آرگومان خط فرمان، متغیر منطبق را بازنویسی میکند. این کار باعث میشود یک مکان واحد برای تغییر اندازه context داشته باشید و ExecStart را به اندازه کافی کوتاه نگه میدارد تا در یک نگاه خوانده شود.
گزینه ProtectSystem=strict کل سیستم فایل را برای این واحد فقطخواندنی (read-only) میکند، که مشکلی ایجاد نمیکند زیرا سرور فقط مدل را میخواند. اگر میخواهید خود سرویس با استفاده از -hf مدلها را دانلود کند، ReadWritePaths=/srv/models را اضافه کنید. گزینه ProtectHome=yes مسیرهای /home و /root را مخفی میکند و این دومین دلیل برای نگهداری مدلها در /srv است: با فعال بودن ProtectHome، مسیر پیشفرض ~/.cache/llama.cpp اصلاً برای پردازش قابل مشاهده نیست.
sudo systemctl daemon-reload
sudo systemctl enable --now llama-server
systemctl status llama-server
curl -s http://127.0.0.1:8080/health
journalctl -u llama-server -n 50 --no-pagerبخش enable --now همان چیزی است که افراد از آن صرفنظر میکنند. بدون enable، سرور پس از reboot بعدی از دسترس خارج میشود. اگر میخواهید کارهای زمانبندیشدهای پیرامون این سرویس انجام دهید، مانند بررسی شبانه برای انتشار نسخه جدید، یک سرویس systemd به همراه تایمر مکانیزم مناسب برای این کار است.
پیش از وقوع OOM، برای آن تصمیمگیری کنید
میزان مصرف حافظه از دو بخش تشکیل شده است که تحت محدودیت، رفتارهای متفاوتی دارند. فایل مدل بهصورت پیشفرض memory-mapped است، بنابراین صفحات آن file-backed هستند: هسته سیستمعامل میتواند آنها را حذف کرده و دوباره از دیسک بخواند. حافظه پنهان KV که وضعیت هر توکن برای هر گفتگوی فعال است، حافظه anonymous محسوب میشود. این حافظه قابل حذف نیست و به همین دلیل باعث کشتهشدن (kill) پروسه میشود.
به همین دلیل است که دو محدودیت در unit، وظایف متفاوتی دارند. MemoryHigh=3G یک محدودیت نرم (soft limit) است: بالاتر از آن، هسته سیستمعامل cgroup را تحت فشار بازپسگیری (reclaim pressure) قرار میدهد، بنابراین صفحات مدل که map شدهاند تخلیه شده و در توکن بعدی از دیسک خوانده میشوند. سرویس به کار خود ادامه میدهد اما کندتر میشود. MemoryMax=3500M یک محدودیت سخت (hard limit) است: بالاتر از آن، پروسه کشته میشود و ژورنال سیستم بهوضوح این موضوع را گزارش میکند.
llama-server.service: A process of this unit has been killed by the OOM killer.مقدار --ctx-size را خودتان تنظیم کنید. مقدار پیشفرض 0 است که به معنای کانتکستی است که مدل با آن آموزش دیده است؛ در مدلهای مدرن با کانتکست طولانی، این مقدار در زمان شروع، حافظه پنهان KV بسیار بزرگی را تخصیص میدهد. در نتیجه، سرویس پیش از پاسخدهی به حتی یک درخواست، متوقف میشود. --parallel همین هزینه را چند برابر میکند، زیرا هر اسلات وضعیت گفتگوی خاص خود را نگه میدارد؛ بنابراین تا زمانی که از نیاز خود به همروندی (concurrency) مطمئن نشدهاید، آن را روی 1 بگذارید.
با Restart=on-failure، سرویسی که کشته شده است دوباره بالا میآید. اگر سرویس در هر بار شروع مجدد کشته شود، systemd تسلیم شده و systemctl status عبارت start request repeated too quickly را چاپ میکند. این رفتار درستی است: یک حلقه راهاندازی مجدد که هر پنج ثانیه یک فایل 12 گیگابایتی را میخواند، از قطعی سرویس مخربتر است. محدودیت یا اندازه کانتکست را اصلاح کنید و سپس وضعیت را با sudo systemctl reset-failed llama-server پاک کنید.
در حین اجرای درخواست، عدد واقعی را با systemctl show llama-server -p MemoryCurrent مشاهده کنید. محدود کردن حافظه و CPU پروسه با systemd این دستورالعملها را با جزئیات بیشتری پوشش میدهد.
برای این حجم کاری از swap اجتناب کنید. مدل swap-out شده، هر توکن را به خواندن تصادفی از دیسک تبدیل میکند. Memory mapping فایل مدل، همین اثر را با آسیب کمتر ایجاد میکند، زیرا هسته سیستمعامل صفحاتی را که نیاز دارد مستقیماً از فایل میخواند.
چه زمانی Ollama انتخاب بهتری است
این یک دوراهی است. زمانی که به یک پردازش واحد با فلگهای مشخص، بیلد ثابت و فایلی که خودتان انتخاب کردهاید نیاز دارید و میخواهید هیچ تغییری در زیرساخت رخ ندهد (چون هیچ چیز دیگری در حال اجرا نیست)، llama-server را انتخاب کنید.
زمانی که به مدیریت مدل نیاز دارید، Ollama را انتخاب کنید: دانلود مدلها با نام، نگهداری چندین مدل روی دیسک، تخلیه مدلهای غیرفعال از حافظه و ارتقای مدلها با یک دستور واحد بهجای بازسازی (rebuild). اینها کارهای واقعی هستند که در غیر این صورت باید خودتان برایشان اسکریپت بنویسید. اجرای Ollama روی یک VPS همین کار را با رویکردی متفاوت انجام میدهد. هر دو سرویس یک API سازگار با OpenAI ارائه میدهند، بنابراین کد کلاینت شما در هر دو جهت بهراحتی قابل سوئیچ است.
ارتقای یک build ثابتشده (pinned)
مقدار bNNNNN را با تگی که قصد انتقال به آن را دارید، جایگزین کنید.
cd llama.cpp
git fetch --tags
git checkout bNNNNN
cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF
cmake --build build --config Release -t llama-server -j 2
sudo install -m 755 build/bin/llama-server /usr/local/bin/llama-server-bNNNNN
sudo ln -sfn /usr/local/bin/llama-server-bNNNNN /usr/local/bin/llama-server
sudo systemctl restart llama-serverفایل باینری قدیمی روی دیسک باقی میماند، بنابراین بازگشت به نسخه قبل (rollback) تنها با یک دستور ln -sfn به llama-server-b10488 و یک بار راهاندازی مجدد (restart) انجام میشود. پیش از انجام ارتقا، یادداشتهای انتشار (release notes) را مطالعه کنید. فایلهای GGUF دارای نسخهبندی هستند و فایلهای قدیمی همچنان بارگذاری میشوند، اما برخی flagها تغییر نام مییابند: استفاده از --mlock و --no-mmap منسوخ شده و جای خود را به --load-mode دادهاند؛ در نتیجه، اگر یک unit file حاوی flag حذفشده باشد، سرویس هنگام شروع با خطای unrecognised argument متوقف میشود.
حالتهای شکست و پیامهایی که مشاهده خواهید کرد
error while loading shared libraries: libllama.so پس از کپی کردن فایل باینری به مکانی دیگر. بیلد پیشفرض، کتابخانههای اشتراکی را در کنار آن تولید میکند. با استفاده از -DBUILD_SHARED_LIBS=OFF مجدداً بیلد کنید یا کل دایرکتوری build/bin را کپی نمایید.
Illegal instruction (core dumped) در زمان راهاندازی یا اولین درخواست. فایل باینری با فعال بودن GGML_NATIVE برای پردازندهای متفاوت از پردازنده فعلی کامپایل شده است. روی همین ماشین مجدداً بیلد کنید یا با استفاده از -DGGML_NATIVE=OFF پیکربندی نمایید.
c++: fatal error: Killed signal terminated program cc1plus در حین بیلد. کامپایلر به دلیل مصرف بیش از حد حافظه توسط سیستم متوقف شده است. مقدار -j را کاهش دهید یا برای مدت بیلد، swap اضافه کرده و سپس آن را حذف کنید.
curl: (7) Failed to connect ... Connection refused از لپتاپ شما. این رفتار صحیح است: سرور روی آدرس loopback در VPS گوش میدهد. روی خود VPS تست کنید یا یک تونل با ssh -L 8080:127.0.0.1:8080 user@your-vps ایجاد کرده و از http://127.0.0.1:8080 به صورت محلی استفاده کنید.
خطای HTTP 503 همراه با "message":"Loading model" در چند ثانیه یا دقیقه اول پس از راهاندازی مجدد. خواندن یک فایل چند گیگابایتی زمانبر است و systemd واحد (unit) را از لحظه شروع پردازش به عنوان فعال گزارش میکند، در حالی که مدل هنوز در حافظه بارگذاری نشده است.
درخواستها معلق میمانند و سپس 504 Gateway Time-out برمیگردانند. پروکسی پیش از اتمام کار مدل، درخواست را رها کرده است. مقدار proxy_read_timeout را افزایش دهید و proxy_buffering را خاموش کنید تا توکنها به محض تولید به کلاینت برسند.
واحد (unit) دچار نوسان شده و سپس با start request repeated too quickly متوقف میشود. عاملی در هر بار شروع، آن را متوقف میکند. فایل journalctl -u llama-server را برای یافتن خط مربوط به OOM killer بررسی کنید، سپس مقدار --ctx-size را کاهش دهید، --parallel را کمتر کنید یا MemoryMax را افزایش دهید.
FAQ
آیا باید سرور llama.cpp را روی VPS اجرا کنم یا Ollama را؟
زمانی که میخواهید یک نسخه (build) دقیق را ثابت نگه دارید، پرچمهای (flags) خاصی را ارسال کنید و یک مدل را در یک فایل واحد داشته باشید که هیچچیز بدون اطلاع شما آن را بهروزرسانی نکند، از llama-server استفاده کنید. زمانی که مدیریت مدل و ارتقای تکدستوری مدنظر شماست، Ollama را اجرا کنید؛ زیرا فراخوانی مدلها با نام، نگهداری چندین مدل روی دیسک و تخلیه مدلهای بلااستفاده از حافظه، کارهایی هستند که در غیر این صورت باید خودتان برای آنها اسکریپت بنویسید. هر دو ابزار یک API سازگار با OpenAI ارائه میدهند، بنابراین اگر بعداً تصمیم به تغییر بگیرید، نیازی به تغییر کد کلاینت نخواهید داشت.
کدام نسخه llama.cpp را باید ثابت (pin) کنم؟
هر تگی که واقعاً آن را ساخته و تست کردهاید. llama.cpp تقریباً هر merge را تگگذاری میکند و نامها همان شمارههای build هستند، مانند b10488 که در تاریخ 18 آگوست 2026 جدیدترین نسخه بود. شاخه پایدار (stable) جداگانهای وجود ندارد، بنابراین نسخه "فعلی" روزانه چندین بار تغییر میکند. با استفاده از --branch <tag> مخزن را کلون کنید، فایل باینری را با نامی که شامل آن تگ باشد نصب کنید و یک symlink به آن اشاره دهید تا ارتقا و بازگشت به نسخه قبل (rollback) تنها با یک دستور انجام شود.
سرور llama-server به چه مقدار RAM نیاز دارد؟
از حجم فایل GGUF شروع کنید، سپس حافظه کش KV را به آن اضافه کنید که با --ctx-size و تعداد اسلاتهای --parallel افزایش مییابد. ارقام منتشرشده جایگزین اندازهگیری در تنظیمات شخصی شما نیستند، زیرا مقدار کل به مدل، کوانتیزاسیون (quantisation) و متنی (context) که مجاز میدانید بستگی دارد. در حین پردازش یک درخواست، systemctl show llama-server -p MemoryCurrent را اجرا کنید و از عددی که مشاهده میکنید استفاده کنید.
چرا مسیر /health خطای 503 با پیام "Loading model" برمیگرداند؟
پردازش شروع شده اما فایل مدل هنوز در حافظه بارگذاری نشده است، بنابراین سرور پاسخ {"error":{"code":503,"message":"Loading model","type":"unavailable_error"}} را میدهد. این وضعیت پس از هر بار راهاندازی مجدد طبیعی است و تا زمانی که خواندن فایل طول بکشد، ادامه مییابد. این موضوع تنها زمانی به مشکل تبدیل میشود که کلاینت یا پروکسی، آن خطای 503 اولیه را به عنوان یک شکست قطعی تلقی کند. تا زمانی که پاسخ {"status": "ok" } دریافت نشده است، مسیر /health را به صورت دورهای بررسی (poll) کنید.
آیا میتوانم llama-server را مستقیماً در معرض اینترنت قرار دهم؟
آن را روی 0.0.0.0 بایند نکنید و پورت را باز نگذارید. این سرویس فاقد حساب کاربری، محدودیت نرخ (rate limiting) و لاگ درخواستی است که ارزش بررسی داشته باشد، و تنها بررسی داخلی آن --api-key است که یک رشته متنی ساده را مقایسه میکند. آن را روی بایند پیشفرض 127.0.0.1 نگه دارید، nginx را با TLS در مقابل آن قرار دهید و همچنین --api-key را تنظیم کنید تا یک اشتباه در پیکربندی پروکسی، مدل را برای همه در دسترس قرار ندهد.