MAATRIX / Блог / Как установить и настроить Perplexica на VPS

Как установить и настроить Perplexica на VPS

Как установить и настроить Perplexica на VPS

MAATRIX

Perplexica — открытый аналог Perplexity: ИИ-поиск, который отвечает не по памяти модели, а по свежей выдаче из интернета и подписывает каждый абзац ссылкой на источник. Разворачивается он одной командой docker compose up, а настройка спотыкается о два условия: без SearXNG с включённым JSON поиск не работает вообще, а без двух моделей — для ответа и отдельно для embedding-поиска по найденным страницам — работает наполовину. Ниже — установка Perplexica на VPS по шагам: Docker Compose, разбор config.toml по провайдерам, подключение SearXNG и расчёт памяти, чтобы стек не упал по OOM в первую неделю.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Perplexica и что нужно подготовить до установки

Perplexica (ItzCrazyKns/Perplexica, MIT) — свой конвейер, а не обёртка над чужим поиском: SearXNG собирает результаты с десятка источников, приложение разбирает страницы по кускам, считает embedding куска и запроса, сортирует по косинусной близости (SIMILARITY_MEASURE) и лучшие куски с вопросом отправляет модели — та отвечает со сносками на URL.

Отсюда — что нужно подготовить заранее.

  • SearXNG с json в search.formats. Не опционально: другого источника результатов нет, обращения к Google Custom Search или Bing API не предусмотрено.
  • Две модели, а не одна. Chat-модель формирует ответ, embedding-модель ранжирует найденные фрагменты. Часть провайдеров даёт и то, и другое одним ключом, часть — только чат; подробно в третьей секции.
  • Docker Engine с плагином compose. Путь — git clone и сборка образа локально, готового пакета под apt нет.
  • VPS на Ubuntu 24.04 или Debian 12, порт 3000 на время проверки и, если нужен домен, DNS-запись на сервер.

Установка Perplexica через Docker Compose: команды по шагам

Официальный путь — сборка образа из исходников, а не готовый тег из чужого реестра: так вы получаете код, что лежит в репозитории на момент клонирования.

sudo apt update && sudo apt install -y git
git clone https://github.com/ItzCrazyKns/Perplexica.git
cd Perplexica
cp sample.config.toml config.toml

config.toml — из шаблона, пустые ключи и адрес SearXNG для запуска вне Docker; разбор в следующей секции. Сначала — сам стек: docker-compose.yaml репозитория, два сервиса:

services:
  searxng:
    image: docker.io/searxng/searxng:latest
    container_name: perplexica-searxng
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - ./searxng:/etc/searxng:rw
    restart: unless-stopped
    networks: [perplexica-network]

  app:
    build:
      context: .
      dockerfile: app.dockerfile
    container_name: perplexica
    ports:
      - "3000:3000"
    volumes:
      - backend-dbstore:/home/perplexica/data
      - uploads:/home/perplexica/uploads
      - ./config.toml:/home/perplexica/config.toml
    depends_on: [searxng]
    restart: unless-stopped
    networks: [perplexica-network]

networks:
  perplexica-network:
volumes:
  backend-dbstore:
  uploads:

app собирается из app.dockerfile дольше, чем скачивается SearXNG: на слабом VPS сборка займёт пару минут — не обрыв сети.

docker compose up -d --build
docker compose ps

Оба контейнера должны быть в статусе running. Если perplexica-searxngExited (1), откройте лог: скорее всего не заменена заглушка secret_key, как и у отдельного SearXNG. Подробно — в статье как установить и настроить SearXNG на VPS; коротко — openssl rand -hex 32 в ./searxng/settings.yml вместо ultrasecretkey и docker compose up -d --force-recreate searxng.

Живость приложения — отдельно:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/
200

200 — Next.js поднялся и отдаёт страницу; поиск это ещё не проверяет, до моделей и SearXNG доходим в следующих двух секциях.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть SearXNG

config.toml по секциям: провайдеры моделей и адрес SearXNG

config.toml — TOML-файл из трёх частей: общие параметры, провайдеры моделей и адрес SearXNG.

[GENERAL]
SIMILARITY_MEASURE = "cosine"
KEEP_ALIVE = "5m"

[API_ENDPOINTS]
SEARXNG = "http://searxng:8080"

SIMILARITY_MEASURE — метрика сравнения кусков страниц с embedding-ом запроса; трогать dot почти никогда не нужно, cosine — устоявшийся выбор. KEEP_ALIVE — параметр для Ollama: сколько держать модель прогретой после последнего запроса, для облачных провайдеров он ни на что не влияет. SEARXNG в [API_ENDPOINTS]не http://localhost:8080, как можно ожидать из шаблона: внутри контейнера app localhost — сам контейнер, а SearXNG виден только по имени из docker-сети.

Дальше — провайдеры, у каждого свой блок [MODELS.ИМЯ]; не каждый отдаёт embedding-и — это определяет список моделей в настройках:

ПровайдерКлюч в config.tomlChat-модельEmbedding-модель
OpenAIAPI_KEYдада
GeminiAPI_KEYдада
AnthropicAPI_KEYданет
GroqAPI_KEYданет
OllamaAPI_URLдада
Custom (OpenAI-совместимый)API_KEY, API_URL, MODEL_NAMEдазависит от эндпоинта

Частая ошибка: вписать только [MODELS.ANTHROPIC] и ждать, что заработает всё — у Anthropic нет API для embedding-ов (в отличие от OpenAI и Gemini): чат-модель появится, embedding-провайдера в списке не будет. Проще для старта — один провайдер на обе роли:

[MODELS.OPENAI]
API_KEY = "sk-proj-..."

Модели выбираются уже в веб-интерфейсе после запуска (пятая секция), TOML только раздаёт ключи и адреса.

Локальный вариант через Ollama требует адреса, а не ключа:

[MODELS.OLLAMA]
API_URL = "http://host.docker.internal:11434"

Линуксовая ловушка: host.docker.internal резолвится в Docker Desktop из коробки, а на обычном VPS на Linux — только если попросить явно:

  app:
    extra_hosts:
      - "host.docker.internal:host-gateway"

Без этой строки обращение к Ollama падает с ошибкой резолвинга в логе app: TypeError: fetch failed ... cause: Error: getaddrinfo ENOTFOUND host.docker.internal. После правки — docker compose up -d --force-recreate app.

Подключаем SearXNG: свой контейнер или уже поднятый инстанс

У связки Perplexica + SearXNG два рабочих сценария, и путать их — источник самой частой поломки при установке.

Сценарий А — SearXNG из docker-compose.yaml Perplexica. Поднят во второй секции: контейнер perplexica-searxng живёт в одной сети с app, виден по имени searxng. Каталог ./searxng в /etc/searxng Perplexica создаёт сам при первом запуске, JSON там обычно уже разрешён. Проверить можно из контейнера app, где нет ни curl, ни wget (образ собран на Node), но есть встроенный fetch:

docker compose exec app node -e "fetch('http://searxng:8080/search?q=test&format=json').then(r=>console.log(r.status))"
200

Если вместо 200 пришёл 403 или соединение оборвалось — смотрим docker compose logs searxng, не упал ли сам контейнер, а не правим Perplexica.

Сценарий Б — уже существующий SearXNG. Так бывает, если SearXNG один на несколько сервисов, а второй экземпляр поднимать не хочется. Тогда в [API_ENDPOINTS] — не searxng, а фактический адрес инстанса, и на его стороне придётся руками проверить то, что в сценарии А настроено само: json в search.formats и, при включённом лимитере, адрес контейнера Perplexica в pass_ip внутри limiter.toml. Подсеть, из которой стучится Perplexica, узнаётся командой

docker network inspect perplexica_perplexica-network --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'

и добавляется в pass_ip внешнего SearXNG — иначе Perplexica для лимитера выглядит атакой и получает Too Many Requests. Механика лимитера, x_for и link_token — в статье SearXNG на сервере: частые ошибки и решения, здесь не повторяем.

Симптом одинаков в обоих сценариях: интерфейс открывается, режим без поиска отвечает, а на обычном запросе — красный тост без подробностей, они только в docker compose logs app. Остальные типовые поломки Perplexica вне SearXNG — в статье Perplexica на сервере: частые ошибки и решения.

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

Открываем http://IP_СЕРВЕРА:3000 (или домен, если уже настроен прокси из шестой секции). Пустой чат и шестерёнка настроек в левом нижнем углу — с неё начинается работа, не с поля ввода.

В настройках две пары «провайдер + модель»: Chat model provider и Embedding model provider. Нужны обе — с одним ключом Anthropic повторится случай из третьей секции: чат-провайдер появится, embedding-провайдера не будет. Практичный минимум для теста — один ключ OpenAI на обе роли: gpt-4o-mini для чата, text-embedding-3-small для embedding-ов.

Тестовый запрос — в режиме All (веб-поиск по умолчанию). Рабочий ответ: текст со сносками [1], [2] и список источников с реальными URL под ним. Если сносок нет, а текст общий «из головы модели» — поиск не отработал: либо SearXNG (предыдущая секция), либо embedding-провайдер не задан, а чат-модель всё равно отвечает без опоры на страницы.

Кроме All есть пять режимов: Writing Assistant — чат без SearXNG, для черновиков; Academic Search — научные источники; YouTube Search и Reddit Search — свои категории; Wolfram Alpha Search — вычисления отдельным движком. Рядом — переключатель Copilot: модель сначала расширяет запрос в несколько поисковых и только потом идёт в SearXNG. Результаты полнее, но это лишний вызов модели до ответа — больше токенов и времени, включать стоит осознанно.

История переписки хранится не в браузере, а в SQLite-базе на сервере, в volume backend-dbstore — переживает перезапуск контейнера и docker compose down без флага -v.

Публикация наружу: домен, TLS и автозапуск

Порт 3000 без прокси годится для проверки, не для постоянной работы: ни TLS, ни таймаута на долгую генерацию у голого Next.js-сервера нет. Минимальный конфиг Nginx:

server {
    listen 443 ssl;
    http2 on;
    server_name search-ai.example.com;

    ssl_certificate     /etc/letsencrypt/live/search-ai.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/search-ai.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "upgrade";
        proxy_buffering off;
        proxy_read_timeout 600s;
    }
}

Upgrade/Connection и отключённая буферизация нужны для потокового ответа — токены идут в браузер по мере готовности, а не куском после таймаута. proxy_read_timeout 600s — запас на Copilot из прошлой секции, где один ответ — несколько обращений к модели.

Сертификат — certbot --nginx -d search-ai.example.com. Фаервол закрывает прямой доступ к обоим внутренним портам:

ufw allow 22/tcp
ufw allow 80,443/tcp
ufw deny 3000/tcp
ufw deny 8080/tcp
ufw enable

unless-stopped поднимает оба контейнера после перезагрузки сам, если включён Docker — systemctl enable docker разово.

Обновление — git pull && docker compose up -d --build. Честно: config.toml время от времени получает новые секции провайдеров, старый файл о них не узнает — не ошибка, а рост проекта; после крупных обновлений сверяйтесь с sample.config.toml. Перед обновлением — бэкап volume с базой, он бэкапится отдельно от кода:

docker run --rm \
  -v perplexica_backend-dbstore:/data \
  -v "$PWD":/backup alpine \
  tar czf /backup/perplexica-db-$(date +%F).tar.gz -C /data .

Какой сервер под Perplexica брать в MAATRIX

Perplexica — это два процесса на одной машине: Node-сервер приложения и SearXNG-контейнер под ним, считать ресурсы нужно на сумму, а не по большему из двух.

Честный минимум: 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. Хватает на облачных провайдерах (OpenAI, Anthropic, Gemini, Groq) без локального инференса. Минимума для одиночного SearXNG (1–2 ГБ) здесь не хватит: рядом Node-процесс Perplexica со своими всплесками памяти при стриминге. Уместить всё в 2 ГБ — верный способ познакомиться с OOM-killer в первую нагруженную сессию.

Комфортный вариант: 4 vCPU, 8 ГБ RAM, 60–80 ГБ NVMe. Нужен, если чат и embedding — не облачный API, а Ollama. Считать по весам: модель 7B в Q4 — около 4,5 ГБ, которые Ollama держит в памяти целиком, плюс растущий KV-кеш, плюс SearXNG и сам Perplexica. Меньше 8 ГБ закладывать не стоит — не тот случай, где помогает «как-нибудь поместится». Расчёт под разные сценарии — в статье сколько RAM нужно для SearXNG и Perplexica.

Конкретный конфликт, о котором стоит знать заранее. Заказали SearXNG из каталога MAATRIX (слушает 127.0.0.1:8080) и следом развернули Perplexica по инструкции из второй секции как есть — оба compose-файла займут один порт хоста, docker compose up упадёт: Error response from daemon: driver failed programming external connectivity on endpoint perplexica-searxng-1: Bind for 127.0.0.1:8080 failed: port is already allocated. Решение: уберите сервис searxng из docker-compose.yaml Perplexica, а в config.toml укажите вместо http://searxng:8080 адрес http://127.0.0.1:8080 — на одном сервере это тот же хост, а не имя из чужой docker-сети.

Локация — Лондон (UK). Причина двойная: британским адресам поисковики отвечают штатнее, чем спорным подсетям, а до Google, DuckDuckGo и Brave в Европе — минимальный пинг. С другой стороны — облачные модели: OpenAI, Anthropic и Gemini обслуживают британский адрес без региональных отказов, тогда как российский IP на части из них упирается в 403 unsupported_country_region_territory. Для российской команды пинг до Лондона заметно меньше, чем до США, а на поиске с параллельными обращениями к движкам разница ощутимее, чем на одиночном API-вызове.

Сам Perplexica пока не входит в каталог одного клика — его разворачиваете сами, как выше. SearXNG в каталоге apps.maatrix.io есть, ставится автоматически при заказе, работает на Ubuntu и Debian; адрес панели и доступы — в личном кабинете, в разделе «Доступ». Оплата — картой российского банка, по СБП, криптовалютой или токеном MAAT: заграничная карта не нужна, хотя сервер в Лондоне.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть SearXNG

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Обязателен ли SearXNG, или можно подключить другой поисковый API?

Только SearXNG — интеграции с Google Custom Search, Bing и SerpAPI нет. Если SearXNG недоступен, откажут все режимы с поиском, но Writing Assistant ответит — он вообще не обращается к поисковику.

Можно уйти от облачных ключей и работать на Ollama?

Да, для чата и для embedding-ов — секция [MODELS.OLLAMA] с API_URL вместо ключа. Условия: host.docker.internal на Linux нужен через extra_hosts (иначе ENOTFOUND), а памяти — по весам модели, не по облачному минимуму: CPU без GPU заметно медленнее API, и если это критично, разумный компромисс — Ollama только под embedding-и, чат оставить на облаке.

Пропадёт ли история чатов при обновлении контейнера?

Нет, если не удалять volume backend-dbstoredocker compose down без -v его не трогает, а up -d --build пересоздаёт только код. Перед крупным обновлением стоит сделать tar volume отдельно — способ в шестой секции.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.