Руководство по сборке локального AI-стека. Часть 1
Локальный стек для работы с большими языковыми моделями (LLM) и генерации изображений, который:
Работает полностью офлайн — ни одного запроса в облака, ни одной внешней зависимости во время работы.
Использует только CPU — без видеокарт, без CUDA, без драйверов. Всё считается на процессоре, с
mmapдля экономии RAM.Запускается на Debian 12 x86_64 (целевая система), но не привязан к конкретному железу — на другой машине с тем же дистрибутивом развернётся из той же папки.
Доступен из локальной сети — с аутентификацией, чтобы домашние или коллеги в офисе могли пользоваться, но без правки конфигов каждый раз.
Переживает перезагрузки и обновления — модели и пакеты лежат в папке проекта, а не размазаны по системе.
Из чего состоит стек
Три независимых компонента, каждый со своим портом и своей ролью:
Компонент | Что делает | Порт | Доступ |
|---|---|---|---|
llama.cpp ( | Инференс LLM: чат, саммари, перевод, код |
| только |
Open WebUI | Веб-интерфейс с логином, историей чатов, настройкой моделей |
|
|
stable-diffusion.cpp ( | Генерация изображений |
|
|
Почему именно так:
llama-serverслушает только localhost — снаружи к нему не подключиться напрямую. Это безопасность: даже если кто-то в LAN узнает порт10000, он не достучится.Open WebUI — единственная «дверь» с аутентификацией. Он ходит к
llama-serverпо127.0.0.1:10000, а пользователи ходят к нему поLAN_IP:8080.sd-server— отдельный сервис, не связанный с чатом. У него свой UI и свой порт. Если картинки не нужны — его можно не запускать.
Что понадобится
Железо:
CPU (любой x86_64, чем больше ядер — тем быстрее; 4+ ядра комфортно).
RAM: минимум 8 ГБ для моделей до 10B (с
mmapи лимитом), 16+ ГБ — если хочется запускать модели 20B+ или несколько сервисов одновременно.Диск: 60–80 ГБ свободного места (модели +
venv+offline_packages). SSD/NVMe настоятельно рекомендуется для скорости, но и на HDD работает (медленно).Сеть: для первичной сборки нужен интернет, для работы — нет.
Софт:
Debian 12 (bookworm) x86_64.
Python 3.11 (идёт в комплекте).
git,cmake,build-essential,python3-venv,python3-pip.Интернет только на этапе сборки — потом всё офлайн.
Общий план работ
Руководство разбито на пять шагов. Каждый шаг — самостоятельный, можно остановиться и проверить результат, прежде чем идти дальше.
Шаг 1. Запуск llama.cpp на тестовой модели.
Собираем
llama.cppиз исходников (один раз).Качаем компактную модель (
Qwen3.5-2B-Q4_K_M).Запускаем
llama-serverсmmapи лимитом памяти.Проверяем, что чат работает, и понимаем, как устроены ключевые флаги (
--load-mode,--no-repack,--cache-type-k/v,--reasoning).Учимся правильно раскладывать модели: обычные
.gguf— в кореньmodels/, мультимодальные (сmmproj) — в отдельные подпапки.
Шаг 2. Наполнение моделями.
Скачиваем набор моделей под разные задачи: универсальный чат, кодинг, ролевое общение, русский язык, vision (OCR).
Раскладываем по папкам с учётом
mmproj.Делаем HTML-шпаргалку
web/models.html— статическую страницу с описанием моделей, их сильных/слабых сторон и рекомендаций «какая модель для какой задачи». Она открывается в браузере локально, без сервера.
Шаг 3. Запуск сервера генерации изображений (stable-diffusion.cpp).
Собираем
stable-diffusion.cppиз исходников.Разбираемся, что для изображений нужен не один файл, а три: диффузионная модель (
.ggufили.safetensors), VAE (декодер в пиксели) и текстовый энкодер (LLM, который понимает промпт).Раскладываем по папкам: модели — в
models/media/, VAE — вmodels/media/vae/<модель>/, LLM — вmodels/(общие с текстовым стеком).Запускаем
sd-serverна порту8888с веб-UI (web/index.html).
Шаг 4. Добавление Open WebUI поверх llama.cpp.
Ставим Open WebUI в тот же
venv, что и всё остальное (общая папка).Настраиваем его через
start_webui.py: отключаем Ollama, отключаем телеметрию, включаем веб-поиск (DuckDuckGo, если есть сеть), подключаем кllama-serverчерез127.0.0.1:10000.Секреты (API-ключ llama и сессионный ключ WebUI) храним в
.secrets(chmod 600), генерируем один раз черезinit_secrets.sh.Запускаем через оркестратор
run_webui.sh: он поднимаетllama-serverв фоне, ждёт готовности, потом запускает WebUI, и корректно останавливает оба по Ctrl+C.Первый пользователь, зарегистрировавшийся в WebUI, становится админом; регистрация после этого закрывается.
Шаг 5. Офлайн-развёртывание и перенос.
Собираем
offline_packages/— все Python-wheels, нужные дляvenv(включая CPU-версию PyTorch).Фиксируем версии в
requirements.lock.Пишем
README.mdс инструкцией «как развернуть с нуля на другой машине».Опционально: упаковка в LXC (обсудили, но решили не делать — слишком много возни ради того, что
venvи так решает).
Что в итоге получится
После прохождения всех шагов у вас будет:
Рабочий чат с LLM на
http://<LAN_IP>:8080— с логином, историей, настройкой параметров моделей.Родной UI
llama.cppнаhttp://127.0.0.1:8080(если запускатьrun_llama_mmap.shотдельно) — для отладки и сравнения.Генератор картинок на
http://<LAN_IP>:8888— с промптом, размером и шагами.Шпаргалка
web/models.html— какая модель для какой задачи.Папка
offline_packages/— для развёртывания на другой машине без интернета.Полное понимание, как это всё устроено, и возможность добавлять новые модели, менять лимиты памяти, переключать режимы (router / single, reasoning on/off).
Что важно понять до начала
Всё на CPU — это иногда медленно. 3–15 минут на ответ большой модели, 5–10 минут на картинку.
mmapи лимиты памяти делают процесс предсказуемым, но не быстрым.mmap— ключевая технология. Модель не загружается в RAM целиком; ядро подгружает страницы по требованию и вытесняет неиспользуемые. Это позволяет запускать 20-гиговую модель на 10 ГБ RAM — медленно, но работает.Open WebUI — это «поверх»
llama.cpp, а не замена. Родной UIllama.cppостаётся доступен (на localhost), а WebUI добавляет аутентификацию и управление моделями.Офлайн — это не «нет интернета вообще». На этапе сборки интернет нужен (скачать исходники, модели, пакеты). После сборки — не нужен.
offline_packages/решает проблему переноса на машину без сети.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.