SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-08-21

اجرای سرور llama.cpp روی VPS با systemd

آموزش گام‌به‌گام اجرای llama-server با استفاده از تگ‌های ثابت، اتصال به API سازگار با OpenAI و تنظیم محدودیت حافظه در systemd برای جلوگیری از خطای OOM در سرورهای لینوکس.

آنچه می‌سازید

اجرای سرور llama.cpp روی یک VPS به معنای استفاده از یک فایل باینری واحد، llama-server، است که یک فایل مدل GGUF را بارگذاری کرده و به درخواست‌های HTTP در قالب یک API سازگار با OpenAI پاسخ می‌دهد. کافی است هر کلاینت OpenAI را به http://127.0.0.1:8080/v1 متصل کنید تا کار کند. نصب این برنامه بخش سادهٔ کار است.

باقی کار مربوط به عملیات نگهداری است: تعیین نسخه (pin)، محدود کردن پورت به localhost، نوشتن یک unit برای systemd و تصمیم‌گیری در مورد رفتار سیستم هنگام اتمام حافظه (OOM). این راهنما به همین موارد می‌پردازد. اگر هنوز بین دو گزینهٔ اصلی تصمیم نگرفته‌اید، ابتدا تفاوت‌ها و اولویت‌های Ollama و llama.cpp را مطالعه کنید، زیرا این راهنما دقیقاً همان جزئیات اجرایی است که در آن مقایسه نادیده گرفته شده است.

یک تگ release انتخاب و یادداشت کنید

پروژه llama.cpp تقریباً برای هر merge یک تگ release ثبت می‌کند، بنابراین این تگ‌ها در واقع شماره‌های build هستند. تا تاریخ 18 آگوست 2026، تگ b10488 جدیدترین نسخه است. هیچ شاخه stable با عمر طولانی وجود ندارد؛ این یعنی "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 از یک تگ مشخص

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 کامپایل موازی، فضای حافظهٔ کاری خود را اشغال می‌کند؛ بنابراین -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 و یک راه‌اندازی مجدد انجام می‌شود و بازگشت به نسخهٔ قبل (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 August 2026 بررسی شده‌اند.

ChartGGUF file size on disk, published figures, 18 August 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 گیگابایت است که در بسیاری از پلن‌های پایه در دیسک جا نمی‌شود و پس از آن نیز باید در حافظه بارگذاری شود.

پیش از هر دانلود، df -h را بررسی کنید. پر شدن فایل‌سیستم root در حین انتقال یک فایل 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 همان بررسی آمادگی (readiness check) در بالا است، GET /props تنظیمات فعلی سرور را برمی‌گرداند و GET /metrics در صورتی که با --metrics شروع کنید، شمارنده‌های Prometheus را در دسترس قرار می‌دهد.

هر SDK مربوط به OpenAI به محض اینکه base URL را روی http://127.0.0.1:8080/v1 تنظیم کنید و یک رشته غیرخالی به عنوان API key ارسال کنید، کار می‌کند. تا زمانی که خودتان --api-key را تنظیم نکنید، هیچ بررسی روی آن کلید انجام نمی‌شود.

ادعای هیچ‌کس درباره نرخ توان عملیاتی (throughput) را به عنوان عددی برای برنامه‌ریزی خود در نظر نگیرید. سرعت استنتاج (inference) روی CPU به تعداد هسته‌ها، پهنای باند حافظه و همسایگانی که میزبان را با آن‌ها به اشتراک می‌گذارید بستگی دارد، بنابراین تعداد توکن در ثانیه را روی سیستم خودتان اندازه‌گیری کنید و آن نتیجه را به عنوان حقیقت بپذیرید. زمان سرقت‌شده توسط یک همسایه پرمصرف (noisy neighbour) در اینجا به صورت سرعت تولیدی ظاهر می‌شود که ساعت به ساعت تغییر می‌کند.

سرویس را روی 127.0.0.1 نگه دارید و یک پروکسی در مقابل آن قرار دهید

--host به‌صورت پیش‌فرض روی 127.0.0.1 تنظیم شده است، بنابراین تا زمانی که آن را تغییر ندهید، سرور از خارج غیرقابل‌دسترسی است. آن را به همان حالت رها کنید. در llama-server هیچ مدل کاربری، محدودیت نرخ (rate limit) یا لاگ حسابرسی مفیدی وجود ندارد و تنها کنترل داخلی آن --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 برای استریم کردن ضروری است. اگر buffering فعال باشد، nginx رویدادهای ارسالی از سمت سرور (SSE) را تا پایان پاسخ نگه می‌دارد؛ در نتیجه کلاینت در سکوت منتظر می‌ماند و سپس کل پاسخ را یک‌جا دریافت می‌کند. proxy_read_timeout 600s برای تولیدات طولانی (long generations) لازم است، زیرا مقدار پیش‌فرض 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 برای اکثر فلگ‌ها متغیرهای 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) قرار می‌دهد، بنابراین صفحات مدل نگاشت‌شده حذف شده و در توکن بعدی از دیسک خوانده می‌شوند. سرویس به کار خود ادامه می‌دهد اما کندتر می‌شود. MemoryMax=3500M یک محدودیت سخت (hard limit) است: بالاتر از آن، پروسه کشته می‌شود و journal به‌وضوح این موضوع را گزارش می‌کند.

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 را چاپ می‌کند. این رفتار درستی است: حلقه راه‌اندازی مجدد (restart loop) که هر 5 ثانیه یک فایل 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 دقیق را ثابت نگه دارید، flagهای مشخصی را پاس دهید و یک مدل را در یک فایل واحد داشته باشید که هیچ‌چیز بدون اطلاع شما آن را به‌روزرسانی نکند، از llama-server استفاده کنید. زمانی که مدیریت مدل و ارتقا با یک دستور برایتان اولویت دارد، Ollama را اجرا کنید؛ زیرا فراخوانی مدل‌ها با نام، نگهداری چندین مدل روی دیسک و خارج کردن مدل‌های غیرفعال از حافظه، کارهایی هستند که در غیر این صورت باید خودتان برایشان اسکریپت بنویسید. هر دو ابزار یک API سازگار با OpenAI ارائه می‌دهند، بنابراین اگر بعداً تصمیم به تغییر بگیرید، نیازی به تغییر کد کلاینت نخواهید داشت.

به کدام نسخه از llama.cpp باید متعهد (pin) باشم؟

به هر تگی که واقعاً آن را build و تست کرده‌اید. llama.cpp تقریباً هر merge را تگ‌گذاری می‌کند و نام‌ها شماره‌های build هستند، مانند b10488 که جدیدترین نسخه در تاریخ 18 August 2026 بود. شاخه stable جداگانه‌ای وجود ندارد، بنابراین نسخه "current" روزانه چندین بار تغییر می‌کند. با استفاده از --branch <tag> کلون کنید، باینری را با نام فایلی که شامل آن تگ باشد نصب کنید و یک symlink به آن اشاره دهید تا ارتقا و بازگشت به نسخه قبل (rollback) هر کدام تنها با یک دستور انجام شود.

سرور llama-server به چه مقدار RAM نیاز دارد؟

از اندازه فایل GGUF شروع کنید، سپس KV cache را به آن اضافه کنید که با --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 اولیه را به عنوان یک خطای قطعی در نظر بگیرد. تا زمانی که /health مقدار {"status": "ok" } را برنگردانده است، به polling ادامه دهید.

آیا می‌توانم llama-server را مستقیماً در معرض اینترنت قرار دهم؟

آن را به 0.0.0.0 متصل (bind) نکنید و پورت را باز نگذارید. این برنامه فاقد سیستم حساب کاربری، rate limiting و لاگ درخواستی است که ارزش بررسی داشته باشد، و تنها بررسی داخلی آن --api-key است که یک رشته متنی ساده را مقایسه می‌کند. اتصال پیش‌فرض 127.0.0.1 را حفظ کنید، nginx را با TLS در مقابل آن قرار دهید و --api-key را نیز تنظیم کنید تا یک اشتباه در پیکربندی پروکسی، مدل را برای همه در دسترس قرار ندهد.