Привет!

Нужен LLM? Если для себя лично можно как-то извернуться и купить подписку на ChatGPT, Claude или Gemini, то для бизнеса это не так-то просто. И я сейчас говорю не про зарубежные карточки, а про разделение доступа и локальное хранение чувствительных данных компании.

Передо мной встала задача обеспечить моим клиентам локальную LLM, в которую можно закидывать любые документы и получать по ним ответы. Как водится, бюджета на это не выделили. Нужна демоверсия в боевом режиме для нескольких сотрудников, чтобы оценить профит.

Я подготовил эту инструкцию для сисадминов, которые по ней смогут настроить рабочую версию RAG-системы на базе открытого ПО для небольшой компании. Сразу скажу, что для себя лично вполне можно обойтись без серверной версии AnythingLLM, она нужна только для реализации многопользовательского режима. Десктопный AnythingLLM даст вам и вашим домашним доступ одной галочкой.

Я принял решение купить обычный VPS, а в качестве вычислительного ядра использовать свою домашнюю 4060ti на 16 ГБ. На моём домашнем сервере уже развёрнута Ollama с целым набором моделей. Его связь с миром обеспечивает MikroTik 4011 с гигабитным каналом и белым динамическим IP.

Дальше нам остаётся только правильно развернуть AnythingLLM на VPS и подключить его к вычислительному ядру. Об этом и пойдёт речь ниже.

  1. Установка пакетов на VPS (Ubuntu)

  2. Установка AnythingLLM через Docker Compose

  3. Настройка IPsec (swanctl) на VPS

  4. Настройка MikroTik

  5. Настройка Ollama на домашнем ПК

  6. Настройка клиента L2TP и PPP на VPS

  7. Настройка порядка запуска демонов при старте Ubuntu

  8. Настройка UFW на VPS

  9. Безопасность веб-интерфейса AnythingLLM (Nginx + SSL)

  10. Скрипт-сторож (Watchdog) для динамического IP

Пропустим этап первоначальной настройки VPS, об этом я писал в этой статье.

1. Установка пакетов на VPS (Ubuntu)

Устанавливаем службы VPN и необходимые плагины шифрования:

# Установка зависимостей туннеля
sudo apt update
sudo apt install -y strongswan-swanctl xl2tpd libstrongswan-standard-plugins libstrongswan-extra-plugins

# Установка Docker через официальный скрипт
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

2. Установка AnythingLLM через Docker Compose

Создаем рабочую директорию и конфигурационный файл:

mkdir -p /var/lib/anythingllm/storage
mkdir -p ~/anythingllm
cd ~/anythingllm
nano docker-compose.yml

Копируем туда следующий YAML-конфиг:

services:
  anythingllm:
    image: mintplexlabs/anythingllm
    container_name: anythingllm
    ports:
      - "127.0.0.1:3001:3001"
    environment:
      - STORAGE_DIR=/app/server/storage
    restart: unless-stopped
    volumes:
      - /var/lib/anythingllm/storage:/app/server/storage
      - /var/lib/anythingllm/.env:/app/server/.env

Обратите внимание на строчку "127.0.0.1:3001:3001" — так мы изолируем контейнер от внешнего мира. Зачем? Правильно! Мы будем использовать Nginx и Certbot для SSL-сертификата нашей веб-морды.

Осталось только запустить контейнер. Находясь в папке ~/anythingllm, выполняем:

docker compose up -d

3. Настройка IPsec (swanctl) на VPS

AnythingLLM будет отправлять Ollama документы для анализа. Чтобы они проходили по защищённой трубе, поднимем туннель L2TP/IPsec по классике. Боялся, что всё это заблокировано, но нет: VPS в РФ, и всё работает стабильно.

Чтобы не платить провайдеру за статический IP, используем функцию DDNS MikroTik. Главное, чтобы IP был белым, а не находился за NAT.

Создаём файл конфигурации /etc/swanctl/conf.d/l2tp.conf.

connections {
    myvpn {
        version = 1
        local_addrs = %defaultroute
        remote_addrs = ДДНС_ДОМЕН_МИКРОТИКА
        
        proposals = aes128-sha1-modp2048, aes256-sha256-modp2048
        
        local {
            auth = psk
        }
        remote {
            auth = psk
        }
        
        children {
            l2tp {
                mode = transport
                esp_proposals = aes128-sha1, aes256-sha256
                local_ts = dynamic[udp/1701]
                remote_ts = dynamic[udp/1701]
                start_action = start
                dpd_action = clear
            }
        }
    }
}

secrets {
    ike-mikrotik {
        secret = "IPSEC_SECRET"
    }
}

4. Настройка MikroTik

Сначала настроим дефолтные профили IPsec для полной совместимости со StrongSwan (IKEv1, modp2048).

В Winbox:

  1. Открываем IP -> IPsec, переходим на вкладку Profiles, открываем профиль default. Устанавливаем Hash Algorithm: sha1, sha256, Encryption Algorithm: aes-128, aes-256, DH Group: modp2048.

  2. Переходим на вкладку Proposals, открываем default. Выставляем Auth. Algorithms: sha1, sha256, Enc. Algorithms: aes-128 cbc, aes-256 cbc.

Через CLI:

/ip ipsec profile set [ find default=yes ] dh-group=modp2048 enc-algorithm=aes-128,aes-256 hash-algorithm=sha1,sha256
/ip ipsec proposal set [ find default=yes ] auth-algorithms=sha1,sha256 enc-algorithms=aes-128-cbc,aes-256-cbc

Теперь включаем L2TP-сервер с требованием обязательного IPsec.

В Winbox:

  • Переходим в раздел PPP, на вкладке Interface нажимаем кнопку L2TP Server. В открывшемся окне ставим галочку Enabled, в выпадающем списке Use IPsec выбираем required, а в поле IPsec Secret вписываем ваш секретный ключ. Default Profile оставляем default-encryption.

Через CLI:

/interface l2tp-server server set enabled=yes use-ipsec=required ipsec-secret="IPSEC_SECRET" default-profile=default-encryption

Создаём учётную запись пользователя для туннеля и жёстко фиксируем IP-адреса внутри него.

В Winbox:

  • В разделе PPP переходим на вкладку Secrets и нажимаем на «плюс». Заполняем поля: Name = ЛОГИН_L2TP, Password = ПАРОЛЬ_L2TP, Service = l2tp. В полях адресов строго прописываем: Local Address = 10.10.10.1, Remote Address = 10.10.10.2.

Через CLI:

/ppp secret add name="ЛОГИН_L2TP" password="ПАРОЛЬ_L2TP" service=l2tp local-address=10.10.10.1 remote-address=10.10.10.2

Я не хочу, чтобы с арендованного сервера был доступ в мою домашнюю локальную сеть, поэтому никакие маршруты на сервере мы не прописываем. На MikroTik в цепочке forward для безопасности стоит общее правило drop на все входящие из туннеля сессии.

Нам нужен только единственный порт 11434 на компьютере с Ollama. Настроим Destination NAT для безопасного проброса порта Ollama строго для IP-адреса VPS.

В Winbox:

  • Переходим в IP -> Firewall, вкладка NAT. Добавляем новое правило:

  • Вкладка General: Chain = dstnat, Src. Address = 10.10.10.2, Dst. Address = 10.10.10.1, Protocol = 6 (tcp), Dst. Port = 11434.

  • Вкладка Action: Action = dst-nat, To Addresses = IP_ДОМАШНЕГО_ПК.

Через CLI:

/ip firewall nat add chain=dstnat src-address=10.10.10.2 dst-address=10.10.10.1 dst-port=11434 protocol=tcp action=dst-nat to-addresses=IP_ДОМАШНЕГО_ПК comment="Forward Ollama from VPS"

5. Настройка Ollama на домашнем ПК

Скачать и установить Ollama совсем не сложно. На официальном сайте прямо на главной странице дана команда для PowerShell:

irm https://ollama.com/install.ps1 | iex

После установки скачиваем необходимые модели. Для генерации текста отлично подойдёт, например, qwen2.5:9b (или выше, в зависимости от вашей памяти), а для обработки входящих документов и построения эмбеддингов — nomic-embed-text:

ollama run qwen2.5:9b
ollama run nomic-embed-text

Важный нюанс: по умолчанию Ollama слушает только localhost. Нам нужно разрешить ей принимать внешние подключения по сети. Для этого в Windows создаём системную переменную окружения OLLAMA_HOST = 0.0.0.0 и перезапускаем службу Ollama. Также не забудьте в брандмауэре Windows разрешить входящие TCP-подключения на порт 11434.

6. Настройка клиента L2TP и PPP на VPS

Редактируем файл /etc/xl2tpd/xl2tpd.conf, указывая DDNS-домен роутера и автоматический дозвон:

[lac myvpn]
lns = ДДНС_ДОМЕН_МИКРОТИКА
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.client
length bit = yes
autodial = yes

Создаём файл опций авторизации /etc/ppp/options.l2tpd.client. Не ставьте таймаут, чтобы сессия не отваливалась по бездействию, а вот опцию persist нужно указать обязательно — она заставит систему держать туннель постоянно.

ipcp-accept-local
ipcp-accept-remote
refuse-eap
require-mschap-v2
noccp
noauth
noipdefault
novj
novjccomp
mtu 1410
mru 1410
persist
maxfail 0
name "ЛОГИН_L2TP"
password "ПАРОЛЬ_L2TP"

Пояснения по опциям конфигурации:

  • ipcp-accept-local и ipcp-accept-remote: Разрешают нашей Ubuntu принять те IP-адреса внутри туннеля, которые ей диктует MikroTik.

  • refuse-eap: Запрещает использовать небезопасный тип авторизации EAP.

  • require-mschap-v2: Жёсткое требование использовать для передачи пароля только протокол MS-CHAPv2.

  • noccp: Отключает протокол сжатия CCP. Трафик и так сжимается и шифруется на уровне IPsec.

  • noauth: Указывает, что сервер Ubuntu сам не требует авторизации от MikroTik.

  • noipdefault: Запрещает демону pppd использовать основной IP-адрес сервера для туннеля. Мы ждём адрес строго от роутера.

  • novj и novjccomp: Отключают алгоритм сжатия заголовков Ван Якобсона. В современных сетях он часто ломает маршрутизацию.

  • mtu 1410 и mru 1410: Уменьшают максимальный размер пакета (MTU/MRU), так как инкапсуляция в IPsec и L2TP забирает часть полезного размера пакета под свои заголовки.

  • persist: Заставляет демон автоматически переподключаться при любом случайном обрыве связи.

  • maxfail 0: Снимает лимит на количество неудачных попыток подключения. Сервер будет стучаться до MikroTik бесконечно, даже если домашний интернет упал на всю ночь.

7. Настройка порядка запуска демонов при старте Ubuntu

Пока тестировал схему, столкнулся с проблемой потери ppp интерфейса. В логах MikroTik видел refuse на подключение без активного IPsec. Это происходило потому, что L2TP пытался пробиться раньше, чем демоны IPsec успевали установить защищённое соединение.

Чтобы избежать этой гонки служб, добавим принудительную зависимость и задержку запуска L2TP.

Выполняем команду sudo systemctl edit xl2tpd.service и в открывшемся буфере вставляем:

[Unit]
After=strongswan-swanctl.service
Requires=strongswan-swanctl.service

[Service]
ExecStartPre=/bin/sleep 5

Применяем изменения в systemd:

sudo systemctl daemon-reload

8. Настройка UFW на VPS

Разрешаем в файрволе необходимые порты для управления сервером и работы веб-интерфейса, после чего активируем его:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Перезапускаем службы сети и туннелей, чтобы все правила применились в чистом виде:

sudo systemctl restart strongswan-swanctl xl2tpd

9. Безопасность веб-интерфейса AnythingLLM (Nginx + SSL)

Поскольку в docker-compose.yml мы изолировали контейнер, указав локальный хост 127.0.0.1:3001, пришло время настроить Nginx в качестве обратного прокси для доступа извне.

Устанавливаем веб-сервер и Certbot:

sudo apt install -y nginx certbot python3-certbot-nginx

Создаём конфигурационный файл виртуального хоста /etc/nginx/sites-available/anythingllm:

server {
    listen 80;
    server_name ТВОЙ_ДОМЕН_VPS;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Для долгих генераций ответов ИИ увеличим таймауты
        proxy_read_timeout 300;
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
    }
}

Активируем сайт, проверяем конфигурацию и получаем автоматический SSL-сертификат от Let’s Encrypt:

sudo ln -s /etc/nginx/sites-available/anythingllm /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d ТВОЙ_ДОМЕН_VPS

Если всё прошло удачно, переходим в браузере по адресу вашего домена VPS. Подключение защищено, никаких предупреждений безопасности. При первичной настройке в веб-интерфейсе AnythingLLM выбираем многопользовательский режим (Multi-user) и создаём аккаунт администратора.

В настройках AnythingLLM переходим в конфигурацию ИИ и указываем Ollama Base URL как http://10.10.10.1:11434. Наш сервер тут же подтянет список моделей с домашнего ПК. В поле моделей выберите qwen2.5:9b. Не забываем настроить и модель эмбеддингов в соседней вкладке — выбираем Embedding Preference -> Ollama, адрес тот же, модель nomic-embed-text. Также на этапе продакшена можно поиграться с размером чанка (Chunk size) и количеством одновременно обрабатываемых батчей.

10. Скрипт-сторож (Watchdog) для динамического IP

Так как домашний провайдер выдает динамический IP, MikroTik обновляет свою запись DDNS. Однако запущенный демон xl2tpd на стороне VPS не умеет самостоятельно переопределять изменившийся IP-адрес закешированного домена. Напишем простой скрипт автоматического перезапуска туннеля.

Создаём файл /usr/local/bin/vpn-watchdog.sh:

#!/bin/bash
TARGET="10.10.10.1"
LOGFILE="/var/log/vpn-watchdog.log"

if ! ping -c 10 -W 5 $TARGET > /dev/null 2>&1; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - Связь с $TARGET потеряна. Перезапуск туннеля..." >> $LOGFILE
    systemctl restart strongswan-swanctl xl2tpd
fi

По этой логике он будет выполнять 10 пингов с таймаутом 5 секунд, если все 10 провалятся, сервис будет перезапущен. Это убережёт нас от случайных сбоев интернета. Скрипт сработает, только если связь стабильно потеряна. Делаем его исполняемым:

sudo chmod +x /usr/local/bin/vpn-watchdog.sh

Добавляем задание в планировщик Cron для проверки каждые 5 минут. Создаем файл /etc/cron.d/vpn-watchdog:

*/5 * * * * root /usr/local/bin/vpn-watchdog.sh

Что мы получили в итоге?

Рабочее демо RAG-системы для заказчика всего за один вечер. Если клиенту понравится, мы оставляем ему этот настроенный VPS, и сотрудники безопасно работают через браузер — именно так, как они привыкли при использовании публичных LLM.

При этом архитектура полностью готова к масштабированию:

  1. Ресурсы VPS (диск под базу данных, оперативную память под веб-сервер) можно увеличивать на лету у хостера.

  2. Для огромного объема загружаемых документов всегда можно подключить внешнее S3-хранилище.

  3. Если клиент созреет купить собственное железо в офис или арендовать выделенный сервер с GPU, мы просто перенаправим AnythingLLM на новый IP-адрес хоста. Ollama здесь не является эксклюзивным решением.

  4. Вся обученная база данных и история переписок (embedded_db) остаются в целости на нашем VPS под полным контролем компании.

Комментарии (4)


  1. powerman
    06.06.2026 09:18

    qwen2.5:9b

    Жестоко. На этой карточке можно на приличной скорости использовать Qwen3.6-35B-A3B.


    1. vadimspriggan Автор
      06.06.2026 09:18

      Я использовал ранее qwen2.5:14b, но здесь привёл пример менее требовательный. Не у всех есть 16ГБ VRAM.


      1. powerman
        06.06.2026 09:18

        Там дело не столько в VRAM, сколько в правильном инструменте и технологии. У меня она выдаёт 34 t/s на 3060 Ti 8 GB - на Вашей карте должно быть заметно лучше, вполне возможно что даже Qwen-3.6-27B потянет.


        1. vadimspriggan Автор
          06.06.2026 09:18

          Спасибо за наводку. Я пока не смотрел в сторону этих больших моделей. Попробую!