LocalAI на CPU-сервері: LLM без відеокарти
TL;DR
LocalAI дає змогу запустити локальну мовну модель з OpenAI-сумісним API на VPS або dedicated-сервері без GPU. У цьому посібнику буде налаштовано захищений LocalAI на Ubuntu 24.04 LTS з Docker, CPU-бекендом llama.cpp, моделлю у форматі GGUF, HTTPS через Caddy, API-ключем і резервним копіюванням.
- Для першого робочого запуску достатньо 4 vCPU, 8 ГБ RAM і 40–60 ГБ SSD.
- Для комфортної роботи з моделями 7B–8B у квантизації Q4 краще використовувати 8 vCPU і 16–32 ГБ RAM.
- LocalAI надає інтерфейс, сумісний з OpenAI API:
/v1/chat/completions,/v1/modelsта інші endpoints. - На CPU важливіша швидкість одного ядра та обсяг RAM, ніж номінальна кількість слабких vCPU.
- Моделі GGUF можна зберігати локально: запити й документи не надсилаються до зовнішніх AI-сервісів.
- Для публічного доступу обов'язкові TLS, firewall, API-ключ і обмеження доступу за IP або reverse proxy.
Що ми налаштовуємо і навіщо
LocalAI — це self-hosted AI-сервіс, який запускає мовні моделі, моделі для генерації ембедингів, speech-to-text та частину інших завдань на власному сервері. Для LLM на CPU зазвичай застосовується бекенд llama.cpp і моделі у форматі GGUF. Вони квантизовані: займають менше пам'яті, ніж вихідні ваги у FP16 або BF16, і можуть працювати без NVIDIA GPU.
Практичний результат цього посібника — API-сервіс, доступний через HTTPS на власному домені. До нього зможуть підключатися застосунки, які вміють працювати з OpenAI API: внутрішній чат для команди, бот у Telegram або Mattermost, IDE-асистент, n8n, Dify, LibreChat, Open WebUI, власний SaaS або backend на Python, Node.js і Go.
На сервері працюватимуть чотири шари: Docker Compose керує контейнером, LocalAI надає API, GGUF-модель відповідає на запити, а Caddy приймає HTTPS-трафік і проксіює його всередину. Сам LocalAI не буде опублікований безпосередньо в інтернеті: порт 8080 залишиться доступним лише на localhost.
Коли LocalAI на CPU виправданий
- Потрібен автономний API для невеликої команди, бота або внутрішніх інструментів.
- Дані не можна або небажано надсилати до хмарних LLM-провайдерів.
- Навантаження помірне: від кількох десятків до сотень запитів на день.
- Допустима затримка відповіді в кілька секунд, а не потокова швидкість GPU-сервісу.
- Потрібен передбачуваний щомісячний бюджет без оплати за токени.
- Ви хочете експериментувати з моделями, системними промптами та параметрами inference.
Чого CPU-сервер не вирішує
CPU-інференс не замінює GPU для високої паралельності. На сервері з 8 сучасними vCPU модель 8B у Q4 зазвичай видає приблизно 4–12 токенів за секунду, але реальна цифра залежить від покоління CPU, частоти, AVX2/AVX-512, розміру контексту та навантаження сусідніх процесів. Для інтерактивного одного користувача цього часто достатньо. Для десятків одночасних діалогів — уже ні.
Не варто очікувати хорошого результату від великих моделей 30B, 70B і вище на звичайному VPS. Навіть якщо модель поміститься в пам'ять, час до першого токена та загальна затримка зроблять сервіс незручним. Для таких моделей потрібен сервер з великим обсягом RAM, потужними CPU або GPU-інфраструктура.
Хмарний API і self-hosted LocalAI
| Критерій | Хмарний managed API | LocalAI на власному сервері |
|---|---|---|
| Запуск | Практично миттєвий | Потрібні сервер, Docker, модель і захист API |
| Якість найбільших моделей | Зазвичай вища | Залежить від обраної локальної моделі |
| Конфіденційність | Дані надсилаються зовнішньому провайдеру | Дані залишаються у вашій інфраструктурі |
| Вартість | Оплата за токени або підписка | Фіксована вартість сервера та зберігання |
| Швидкість за великого навантаження | Висока, інфраструктура масштабується автоматично | Обмежена CPU, RAM і налаштуваннями черги |
| Контроль над моделлю | Обмежений доступними моделями | Повний контроль над моделлю, шаблонами та версіями |
Раціональна схема для невеликого продукту — використовувати LocalAI для завдань, де важливі приватність, низька вартість і передбачуваність: класифікація, вилучення даних, сумаризація внутрішніх текстів, RAG за документацією, допомога розробникам. Зовнішній хмарний API можна залишити як резерв для складних запитів або піків.
Яка VPS-конфігурація потрібна для цього завдання
Головний ресурс для LocalAI на CPU — оперативна пам'ять. Друга за значущістю характеристика — продуктивність процесорного ядра. Диск важливий для зберігання моделей: одна GGUF-модель 3B у Q4 зазвичай займає 2–3 ГБ, модель 8B у Q4 — близько 4,5–6 ГБ, а кілька варіантів моделей і резервні копії швидко заповнюють невеликий SSD.
| Сценарій | CPU | RAM | SSD/NVMe | Рекомендовані моделі |
|---|---|---|---|---|
| Тести, один користувач | 4 vCPU | 8 ГБ | 50 ГБ | 1B–4B, Q4 |
| Чат, бот, RAG для команди | 8 vCPU | 16 ГБ | 100 ГБ NVMe | 7B–8B, Q4_K_M |
| Кілька користувачів і моделей | 12–16 vCPU | 32–64 ГБ | 200 ГБ NVMe | 8B–14B, embeddings, reranker |
| Великі моделі на CPU | 16+ виділених ядер | 64–128 ГБ | 500 ГБ NVMe | 14B–32B з компромісом у швидкості |
Практична стартова конфігурація
Для першої production-інсталяції беріть 8 vCPU, 16 ГБ RAM, 100 ГБ NVMe і канал від 1 Гбіт/с. Такий сервер дасть змогу запустити одну основну модель рівня Llama 3.1/3.2 8B, Qwen2.5 7B або Mistral 7B у GGUF-квантизації Q4, залишити запас операційній системі та Caddy, а також зберігати кілька файлів моделей. Як один із нейтральних варіантів можна взяти VPS із зазначеними характеристиками.
Під час вибору тарифу уточнюйте, чи є vCPU гарантованими, яке покоління CPU використовується і чи має процесор AVX2. Для llama.cpp AVX2 помітно впливає на продуктивність. Іноді 8 швидких виділених ядер дають корисніший результат, ніж 16 перевантажених віртуальних ядер.
Оцінка пам'яті для GGUF
Не можна розраховувати RAM лише за розміром файлу GGUF. Крім ваг моделі, пам'ять потрібна для KV cache, буферів inference, контейнера, ядра Linux і файлового кешу. Безпечне практичне правило: для моделі 8B Q4 розміром 5 ГБ виділяйте сервер щонайменше з 12–16 ГБ RAM. Для 14B Q4 розміром 9–11 ГБ потрібно щонайменше 24–32 ГБ RAM.
Контекст також споживає пам'ять. Якщо ви збільшуєте context_size з 4096 до 16384 токенів, споживання RAM може зрости на кілька гігабайтів. Не задавайте максимальний контекст «про всяк випадок»: для звичайного чату та RAG у більшості випадків достатньо 4096–8192 токенів.
Коли потрібен dedicated, а не VPS
Dedicated-сервер потрібен, коли важливі стабільно висока швидкість генерації, гарантія відсутності noisy neighbors, 32–128 ГБ RAM, великі моделі або постійні паралельні запити. Це також правильний вибір, якщо LocalAI обслуговує комерційний продукт, де затримка безпосередньо впливає на конверсію.
VPS залишається хорошим варіантом для прототипу, внутрішнього сервісу, особистого асистента та малої команди. Починайте з VPS, вимірюйте реальну швидкість через API й переходьте на dedicated лише після появи підтвердженого вузького місця: нестачі RAM, CPU saturation або зростання черги запитів.
Як впливає локація сервера
Локація не прискорює обчислення токенів, але впливає на мережеву затримку до користувачів. Для чату бажано розміщувати сервер у регіоні, близькому до більшості клієнтів. Різниця в 50–100 мс особливо помітна за streaming-відповідей, хоча основна затримка на CPU все одно буде пов'язана з генерацією моделі.
Якщо LocalAI обробляє персональні дані, документи компанії або медичну інформацію, також враховуйте вимоги до юрисдикції, зберігання даних і транскордонної передачі. Розміщуйте резервні копії окремо від основного сервера, бажано в іншому дата-центрі.
Підготовка сервера
Нижче використовується Ubuntu Server 24.04 LTS. На момент налаштування це стабільна LTS-база з тривалим строком підтримки. Увійдіть на сервер під користувачем root лише для початкової підготовки, потім створіть окремого адміністратора та вимкніть вхід root через SSH.
Оновлення системи та базові пакети
Команда встановлює актуальні оновлення безпеки, інструменти діагностики, firewall і fail2ban.
apt update && apt full-upgrade -y
apt install -y ca-certificates curl gnupg jq nano vim \
ufw fail2ban unattended-upgrades \
htop iotop ncdu rsync
Перезавантажте сервер, якщо оновилося ядро. Це застосує новий kernel і виключить ситуацію, коли вразливе ядро продовжує працювати в пам'яті.
if [ -f /var/run/reboot-required ]; then reboot; fi
Створення адміністратора
Замініть deploy на власне ім'я користувача. Обліковий запис використовуватиметься для Docker Compose і подальшого обслуговування LocalAI.
adduser deploy
usermod -aG sudo deploy
Скопіюйте свій публічний SSH-ключ на сервер із локального комп'ютера. Виконуйте цю команду на своєму комп'ютері, а не на VPS.
ssh-copy-id deploy@SERVER_IP
Перевірте вхід в окремому терміналі. Не закривайте поточну root-сесію, доки не переконаєтеся, що авторизація за ключем працює.
ssh deploy@SERVER_IP
Захист SSH
Відкрийте конфігурацію SSH і забороніть root-вхід та парольну авторизацію. Перед цим переконайтеся, що користувач deploy має робочий ключ.
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 30
Перевірте синтаксис і перезапустіть SSH. Якщо команда sshd -t не виводить помилок, конфігурація коректна.
sudo sshd -t && sudo systemctl restart ssh
Firewall і fail2ban
Відкрийте лише SSH, HTTP і HTTPS. Порт LocalAI 8080 не відкривайте: після налаштування він слухатиме лише 127.0.0.1.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Увімкніть fail2ban. Ubuntu постачає готовий фільтр для OpenSSH; сервіс тимчасово блокуватиме IP після серії невдалих входів.
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
Перевірка ресурсів перед установленням
До завантаження моделі перевірте доступну RAM, розмір диска та характеристики процесора. Це допоможе заздалегідь вибрати відповідну квантизацію і кількість потоків.
free -h
df -h /
lscpu | egrep 'Model name|CPU\(s\)|Thread|AVX|Flags'
nproc
Якщо у виведенні lscpu немає AVX2, LocalAI все одно може працювати, але продуктивність на CPU може бути помітно нижчою. У такому разі розумніше використовувати компактну модель 3B–4B і не намагатися обслуговувати кілька одночасних чатів.
Встановлення ПЗ — покроково
У цій конфігурації використовуються Docker Engine 28+ і Docker Compose v2, Ubuntu 24.04 LTS, Caddy 2.8+ та актуальна стабільна гілка LocalAI 3.x. Для production не залишайте тег latest назавжди: після успішного тестування зафіксуйте конкретний тег або digest образу в compose.yaml.
Встановлення Docker Engine
Видаліть старі пакети Docker, якщо вони присутні. Це виключає конфлікт між пакетами Ubuntu та офіційним Docker Engine.
sudo apt remove -y docker.io docker-compose docker-compose-v2 \
docker-doc podman-docker containerd runc 2>/dev/null || true
Додайте офіційний ключ репозиторію Docker і підключіть репозиторій для Ubuntu 24.04.
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Встановіть Docker Engine, containerd і Compose plugin. Compose запускатиме LocalAI та виконуватиме healthcheck.
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
Дозвольте користувачу deploy керувати Docker без sudo. Після команди вийдіть із SSH-сесії та увійдіть знову, щоб група застосувалася.
sudo usermod -aG docker deploy
exit
Після повторного входу переконайтеся, що Docker працює. Контейнер hello-world має завершитися без помилок.
docker version
docker compose version
docker run --rm hello-world
Створення структури проєкту
Усі файли LocalAI будуть розташовані в /opt/localai. Каталог models зберігає GGUF-файли та YAML-конфігурації моделей, а data зберігає дані LocalAI між перезапусками.
sudo mkdir -p /opt/localai/{models,data,backups}
sudo chown -R deploy:deploy /opt/localai
cd /opt/localai
Завантаження першої моделі
Для першого запуску на CPU візьміть інструктивну модель Qwen2.5-3B-Instruct у квантизації Q4_K_M. Вона компактніша за моделі 7B–8B, нормально працює на 8 ГБ RAM і підходить для перевірки API. Перед використанням у production вивчіть ліцензію конкретної моделі та умови її поширення.
Наступна команда завантажує GGUF до каталогу моделей. URL вказано як приклад публічного репозиторію; перед завантаженням перевірте актуальну назву файлу та хеш на сторінці релізу моделі.
cd /opt/localai/models
curl -L --fail --retry 3 \
-o Qwen2.5-3B-Instruct-Q4_K_M.gguf \
"https://huggingface.co/bartowski/Qwen2.5-3B-Instruct-GGUF/resolve/main/Qwen2.5-3B-Instruct-Q4_K_M.gguf"
Перевірте, що файл справді завантажився та не має нульової довжини. Для моделі 3B Q4 очікуйте розмір близько 2–3 ГБ.
ls -lh /opt/localai/models
sha256sum /opt/localai/models/Qwen2.5-3B-Instruct-Q4_K_M.gguf
Створення секретів
Не зберігайте API-ключ у compose-файлі або вихідному коді застосунку. Згенеруйте довге значення та запишіть його у файл .env, доступний лише користувачу deploy.
cd /opt/localai
umask 077
printf 'LOCALAI_API_KEY=%s\n' "$(openssl rand -hex 32)" > .env
chmod 600 .env
cat .env
Збережіть цей ключ у менеджері секретів. Він знадобиться клієнтським застосункам у заголовку Authorization: Bearer.
Конфігурація LocalAI, моделей і HTTPS
Опис моделі
Створіть YAML-файл конфігурації. Параметр threads задає кількість CPU-потоків для inference. На сервері з 8 vCPU почніть із 6: залишиться ресурс для ОС, reverse proxy та обробки мережі. Значення context_size 4096 — безпечна початкова точка для CPU-сервера.
nano /opt/localai/models/qwen-cpu.yaml
name: qwen2.5-3b-cpu
backend: llama-cpp
parameters:
model: Qwen2.5-3B-Instruct-Q4_K_M.gguf
context_size: 4096
threads: 6
temperature: 0.7
top_p: 0.9
max_tokens: 512
template:
chat: |
{{if .System}}<|im_start|>system
{{.System}}<|im_end|>
{{end}}{{range .Messages}}<|im_start|>{{.Role}}
{{.Content}}<|im_end|>
{{end}}<|im_start|>assistant
{{.Assistant}}
Шаблон чату важливий: він перетворює повідомлення OpenAI API у формат, на якому навчалася модель Qwen. Якщо відповіді раптово містять службові токени, повторюють промпт або ігнорують ролі, спочатку перевірте саме chat template.
Docker Compose для CPU-інференсу
Створіть compose.yaml. Образ localai/localai:latest-aio-cpu призначений для CPU та містить потрібні компоненти для типового запуску. Після підтвердження робочої версії замініть latest-aio-cpu на конкретний version tag з офіційних release notes.
nano /opt/localai/compose.yaml
services:
localai:
image: localai/localai:latest-aio-cpu
container_name: localai
restart: unless-stopped
env_file:
- .env
environment:
- DEBUG=false
- MODELS_PATH=/models
- THREADS=6
- CONTEXT_SIZE=4096
volumes:
- ./models:/models
- ./data:/data
ports:
- "127.0.0.1:8080:8080"
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8080/readyz || curl -fsS http://localhost:8080/v1/models"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
deploy:
resources:
limits:
memory: 12G
Ліміт пам’яті у 12 ГБ підходить для сервера з 16 ГБ RAM та однією моделлю 3B. На VPS з 8 ГБ RAM встановіть memory: 6G і використовуйте компактнішу модель. На сервері з 32 ГБ RAM для моделі 8B можна підняти ліміт до 20–24 ГБ.
Запустіть контейнер у фоновому режимі та перегляньте журнали. Перше завантаження може зайняти більше часу, оскільки LocalAI ініціалізує backend і читає файл моделі з диска.
cd /opt/localai
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f --tail=100
Не публікуйте локальний порт 8080 через firewall. Перевірка нижче виконується безпосередньо на сервері та показує, що API бачить налаштовану модель.
curl -s http://127.0.0.1:8080/v1/models | jq .
Перевірка chat completion локально
Замініть значення ключа командою, яка читає його з .env. Параметр stream вимкнено для простої діагностики; після запуску застосунку його можна увімкнути для поступової видачі токенів.
cd /opt/localai
source .env
curl -sS http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${LOCALAI_API_KEY}" \
-d '{
"model": "qwen2.5-3b-cpu",
"messages": [
{
"role": "system",
"content": "Ты краткий технический помощник."
},
{
"role": "user",
"content": "Объясни в одном предложении, что такое reverse proxy."
}
],
"temperature": 0.2,
"max_tokens": 100,
"stream": false
}' | jq .
Якщо API відповідає JSON-об’єктом із choices, базове налаштування завершено. Якщо LocalAI повертає 401, перевірте ім’я змінної та підтримку API-ключа версією образу, що використовується. У деяких збірках LocalAI ключ задається окремою змінною середовища або автентифікацію зручніше реалізувати на рівні Caddy.
Налаштування Caddy і TLS
Для HTTPS потрібен домен, A-запис якого вказує на IP сервера. До запуску Caddy перевірте DNS: домен має повертати публічну IPv4-адресу VPS. Порти 80 і 443 мають бути доступні ззовні.
Встановіть Caddy з офіційного репозиторію. Він автоматично отримує та продовжує сертифікати Let’s Encrypt, якщо DNS і firewall налаштовані коректно.
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
Створіть додатковий пароль для basic authentication. Це другий бар’єр перед API: клієнту знадобляться і Basic Auth, і Bearer token. Хеш, який поверне команда, вставте в Caddyfile.
caddy hash-password --plaintext 'СЮДА_ДЛИННЫЙ_ОТДЕЛЬНЫЙ_ПАРОЛЬ'
Відкрийте конфігурацію Caddy. Замініть домен, ім’я користувача та хеш. За потреби замість basic auth можна обмежити доступ VPN-мережею WireGuard або IP-адресами офісу.
sudo nano /etc/caddy/Caddyfile
llm.example.com {
encode zstd gzip
@not_api not path /v1/ /readyz /healthz
respond @not_api "Not found" 404
basicauth {
apiadmin $2a$14$REPLACE_WITH_CADDY_PASSWORD_HASH
}
reverse_proxy 127.0.0.1:8080 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
transport http {
read_timeout 300s
write_timeout 300s
}
}
log {
output file /var/log/caddy/localai-access.log
format json
}
}
Перевірте файл перед застосуванням. Потім перезавантажте Caddy і переконайтеся, що сертифікат видано.
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -n 50 --no-pager
Зовнішня перевірка HTTPS API
Виконайте команду з робочого комп’ютера. Вона перевіряє TLS, basic authentication, Bearer token і доступність списку моделей через публічний домен.
curl -sS https://llm.example.com/v1/models \
-u 'apiadmin:ВАШ_ОТДЕЛЬНЫЙ_ПАРОЛЬ' \
-H 'Authorization: Bearer ВАШ_LOCALAI_API_KEY' | jq .
Для Python-клієнта використовуйте звичайний OpenAI SDK, указавши свій base_url. Пароль basic auth краще передавати через захищений reverse proxy або VPN; для API-застосунків зручніше залишити лише Bearer-автентифікацію та обмежити IP-адреси в Caddy.
from openai import OpenAI
client = OpenAI(
base_url="https://llm.example.com/v1",
api_key="ВАШ_LOCALAI_API_KEY",
)
response = client.chat.completions.create(
model="qwen2.5-3b-cpu",
messages=[
{"role": "user", "content": "Напиши короткое приветствие."}
],
temperature=0.4,
)
print(response.choices[0].message.content)
Контроль продуктивності
Під час тестового запиту в окремому SSH-вікні запустіть htop. Процеси inference мають використовувати приблизно ту кількість ядер, яку задано параметром threads. Якщо сервер починає використовувати swap, зменште контекст, виберіть меншу квантизацію або збільште RAM.
htop
free -h
docker stats localai
docker compose -f /opt/localai/compose.yaml logs --tail=100 localai
Резервні копії та обслуговування
LocalAI зазвичай не містить критичної бази даних, якщо використовується лише як inference API. Однак потрібно зберігати конфігурацію, файли моделей, змінні оточення, Caddyfile, дані клієнтських застосунків і, якщо вони з’являться, векторну базу RAG. Не вважайте Docker image резервною копією: образ можна завантажити знову, а конфіги та дані — ні.
Що включити до резервної копії
/opt/localai/compose.yaml— версія сервісу та налаштування контейнера./opt/localai/models/.yaml— параметри та chat templates моделей./opt/localai/.env— API-ключі; зберігати лише в зашифрованому backup./opt/localai/data— постійні дані LocalAI, якщо вони використовуються./etc/caddy/Caddyfile— reverse proxy та правила доступу.- Каталог моделей GGUF — залежно від ситуації: файли великі, але їх повторне завантаження може тривати довго.
- Дані RAG-стека: PostgreSQL, Qdrant, pgvector, Chroma або інший vector store.
Для конфігурації робіть щоденну копію. Моделі можна створювати в резервній копії щотижня або не копіювати взагалі, якщо ви зберігаєте перевірений список URL, версій і SHA256. Для production-сервісу розумніше мати хоча б одну віддалену копію GGUF: публічний репозиторій може змінити структуру, видалити файл або обмежити доступ.
Резервне копіювання через restic
Restic шифрує архів перед надсиланням до S3-сумісного сховища. Встановіть пакет і створіть окремий файл секретів. Не додавайте цей файл до Git і не надсилайте його в месенджери.
sudo apt install -y restic
sudo install -d -m 700 /root/.config/restic
sudo nano /root/.config/restic/localai.env
export RESTIC_REPOSITORY="s3:https://s3.example.net/localai-backups"
export RESTIC_PASSWORD="ДЛИННЫЙ_СЛУЧАЙНЫЙ_ПАРОЛЬ_РЕПОЗИТОРИЯ"
export AWS_ACCESS_KEY_ID="S3_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="S3_SECRET_KEY"
Обмежте доступ до файлу та ініціалізуйте віддалений репозиторій. Цю операцію виконують один раз.
sudo chmod 600 /root/.config/restic/localai.env
sudo bash -c 'source /root/.config/restic/localai.env && restic init'
Створіть скрипт. У прикладі моделі виключено зі щоденного бекапу; додайте каталог /opt/localai/models, якщо хочете копіювати також GGUF-файли. Скрипт також видаляє надто старі snapshots відповідно до політики зберігання.
sudo nano /usr/local/sbin/backup-localai.sh
#!/usr/bin/env bash
set -euo pipefail
source /root/.config/restic/localai.env
restic backup \
/opt/localai/compose.yaml \
/opt/localai/.env \
/opt/localai/data \
/opt/localai/models \
/etc/caddy/Caddyfile \
--exclude='.gguf' \
--tag localai
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--prune
Зробіть скрипт виконуваним, запустіть вручну та перевірте список snapshots. Перший backup підтвердить, що доступ до S3, шифрування та права налаштовані правильно.
sudo chmod 700 /usr/local/sbin/backup-localai.sh
sudo /usr/local/sbin/backup-localai.sh
sudo bash -c 'source /root/.config/restic/localai.env && restic snapshots'
Додайте щоденний запуск через cron о 03:30. Логи зберігаються в окремий файл, який корисно перевіряти хоча б раз на тиждень.
sudo crontab -e
30 3 /usr/local/sbin/backup-localai.sh >> /var/log/localai-backup.log 2>&1
Перевірка відновлення
Бекап без тесту відновлення — лише припущення. Раз на місяць відновлюйте snapshot до тимчасової директорії на іншому сервері або локальній машині, перевіряйте YAML-конфігурації та переконуйтеся, що .env присутній.
sudo mkdir -p /tmp/localai-restore
sudo bash -c 'source /root/.config/restic/localai.env && \
restic restore latest --target /tmp/localai-restore'
sudo find /tmp/localai-restore -maxdepth 4 -type f | sort
Безпечні оновлення
Не оновлюйте LocalAI, Docker, Caddy та модель одночасно. Інакше в разі помилки буде складно зрозуміти її причину. Для невеликого сервісу використовуйте maintenance window: попередьте користувачів, зробіть backup, оновіть один компонент, виконайте smoke test і лише потім рухайтеся далі.
Оновлення LocalAI виглядає так: спочатку збережіть поточний image digest, потім завантажте новий образ, перезапустіть контейнер і перевірте API. Якщо модель або API перестали працювати, поверніть попередній тег образу в compose.yaml і знову виконайте up -d.
cd /opt/localai
docker inspect localai --format='{{.Image}}'
docker compose pull
docker compose up -d
docker compose ps
curl -fsS http://127.0.0.1:8080/v1/models | jq .
Для rolling-оновлення без простою знадобляться щонайменше два backend-інстанси, балансувальник і достатній запас RAM. На одному CPU VPS частіше безпечніше заплановане коротке вікно обслуговування: завантаження однієї моделі вже споживає суттєву частину пам’яті.
Усунення несправностей і FAQ
Чому LocalAI не бачить модель у /v1/models?
Спочатку перевірте шлях монтування: каталог хоста /opt/localai/models має бути підключений до контейнера як /models. Потім перегляньте логи: docker compose logs --tail=200 localai. Поширена причина — неправильний YAML, невідповідність імені GGUF-файлу в параметрі model або неправильні права на каталог. Також переконайтеся, що файл конфігурації має розширення .yaml і розташований поруч із моделлю.
Чому відповідь генерується дуже повільно?
Перевірте навантаження через htop і docker stats localai. На CPU нормальною є швидкість у кілька токенів за секунду, особливо для моделей 7B–8B. Зменште context_size до 4096, встановіть threads приблизно на кількість доступних фізичних або віртуальних ядер мінус одне-два, використовуйте Q4_K_M замість Q5/Q6 та виберіть модель 3B–4B. Якщо CPU постійно завантажений на 100%, а користувачів стає більше, потрібен потужніший сервер або GPU.
Контейнер перезапускається, а в логах є out of memory. Що робити?
Це означає, що моделям, KV cache і системним процесам не вистачило RAM. Виконайте free -h і перевірте, чи використовувався swap. Зменште розмір контексту, кількість одночасно завантажених моделей і квантизацію. Наприклад, замініть 8B Q5 на 8B Q4 або 3B Q4. Не намагайтеся виправити проблему лише більшим swap: inference стане вкрай повільним. Для моделі 8B Q4 практичний мінімум — 16 ГБ RAM.
Чому HTTPS-сертифікат Caddy не випускається?
Перевірте A-запис домену командою dig +short llm.example.com: він має вказувати на IP сервера. Переконайтеся, що порти 80 і 443 відкриті в UFW і в панелі провайдера, якщо там є окремий firewall. Перегляньте sudo journalctl -u caddy -n 100. Поширені причини: DNS ще не оновився, домен проксіюється стороннім CDN із невідповідним режимом TLS або порт 80 зайнятий іншим вебсервером.
API повертає 401 Unauthorized. Де шукати помилку?
Розділіть перевірку на рівні. Спочатку виконайте запит до 127.0.0.1:8080 без Caddy. Потім перевірте Basic Auth через curl -u, а після цього — Bearer token. Переконайтеся, що значення в .env не містить зайвих пробілів, а контейнер було перезапущено після зміни файлу: docker compose up -d --force-recreate. Не передавайте ключ у URL і не зберігайте його в shell history.
Яка мінімальна конфігурація VPS підійде?
Для знайомства з LocalAI мінімально підійде VPS із 4 vCPU, 8 ГБ RAM і 50 ГБ SSD. На ньому слід запускати одну невелику модель 1B–4B у Q4-квантизації, контекст 2048–4096 та один активний діалог. Для моделі 7B–8B така конфігурація вже гранична: сервіс може працювати, але буде повільним або зіткнеться з нестачею пам’яті. Для стабільної роботи 8B обирайте 8 vCPU та 16 ГБ RAM.
Що вибрати — VPS чи dedicated для цього завдання?
VPS підходить для особистого асистента, прототипу, RAG за внутрішніми документами та команди з кількома користувачами. Dedicated варто обирати за постійного CPU-навантаження, вимоги до стабільного часу відповіді, використання моделей 14B і більше, 32–64 ГБ RAM або помітної паралельності. Практичний підхід — почати з VPS, зібрати метрики швидкості, пам’яті та черг, а потім мігрувати на виділений сервер лише за підтвердженої потреби.
Як додати другу модель без зупинки першої?
Скопіюйте другий GGUF-файл до /opt/localai/models, створіть для нього окремий YAML з унікальним name і перезапустіть контейнер. Враховуйте, що кілька одночасно завантажених моделей сумують споживання RAM. На сервері з 16 ГБ розумно тримати одну модель 8B або кілька компактних моделей. Якщо модель потрібна рідко, розгляньте окремий інстанс LocalAI або механізм вивантаження невикористовуваних моделей, якщо він підтримується вашою версією.
Чому модель відповідає незв’язно, повторює текст або ігнорує системний промпт?
Зазвичай проблема в несумісному chat template, а не в CPU. Кожна instruct-модель має свій формат ролей і спеціальних токенів. Перевірте офіційну model card і порівняйте рекомендований шаблон із YAML-файлом LocalAI. Також знизьте temperature до 0.2–0.5, переконайтеся, що вибрано саме instruct-версію моделі, і не змішуйте шаблон Qwen з Llama або Mistral. Для діагностики надішліть короткий запит без довгої історії.
Висновки та наступні кроки
Тепер на сервері працює LocalAI з CPU-інференсом, локальною GGUF-моделлю, OpenAI-сумісним API, HTTPS і базовим захистом. Такий стек підходить для приватних AI-інструментів і помірного навантаження без купівлі або оренди GPU.
- Виміряйте швидкість генерації, використання RAM і реальні затримки на типових запитах вашого завдання.
- Додайте RAG: embeddings-модель, vector store і контроль доступу до документів.
- Зі зростанням навантаження перейдіть на швидші CPU, dedicated-сервер, кілька інстансів за reverse proxy або GPU-інференс.
Перед впровадженням у production зафіксуйте версії Docker image і моделей, документуйте SHA256 GGUF-файлів, регулярно перевіряйте відновлення бекапів і не публікуйте API без автентифікації.