Как установить SearXNG на VPS с Docker Compose
Разверните частный SearXNG на VPS: settings.yml, limiter, nginx с TLS и JSON API для скриптов без ключей, оплаты за запросы и лимитов внешних сервисов.
Что вы создаете
Собственный экземпляр SearXNG предоставляет частную поисковую систему, работающую на вашем сервере. SearXNG — это метапоисковая система: она принимает ваш запрос, обращается к другим системам, например Google, Bing, DuckDuckGo и Wikipedia, а затем объединяет полученные результаты на одной странице. Профиль не создается, а cookie для отслеживания не устанавливается, потому что единственная машина, которая хранит ваш запрос, — это ваша машина.
Стек небольшой. Два контейнера, один файл настроек и один обратный прокси. Главное решение — будет ли экземпляр частным, то есть доступным только вам и вашим собственным скриптам, или публичным, то есть доступным для запросов из интернета. Этот выбор меняет параметры безопасности, поэтому сделайте его до начала настройки. По умолчанию следует выбрать частный экземпляр.
Есть и вторая причина запустить собственный экземпляр. SearXNG поддерживает JSON, поэтому любой написанный вами скрипт или AI-агент получает принадлежащий вам API поиска без ключа, оплаты за каждый запрос и уведомлений об исчерпании квоты.
Установка SearXNG с помощью Docker Compose
Проект публикует образ контейнера и файл Compose. Загрузите оба файла на чистый сервер Ubuntu 24.04, на котором уже установлены Docker Engine и плагин Compose. Если Docker вам незнаком, сначала ознакомьтесь с материалом Основы Docker Compose на VPS, а затем вернитесь к этому руководству.
sudo install -d -o "$USER" -g "$USER" -m 750 /opt/searxng
cd /opt/searxng
mkdir -p core-config
curl -fsSL \
-O https://raw.githubusercontent.com/searxng/searxng/master/container/docker-compose.yml \
-O https://raw.githubusercontent.com/searxng/searxng/master/container/.env.example
cp -i .env.example .envФайл Compose определяет два сервиса. core — это сам SearXNG, а valkey — хранилище данных в памяти, используемое для ограничения частоты запросов и хранения краткоживущего состояния. Файл монтирует ./core-config/ в /etc/searxng/ внутри контейнера, поэтому все настройки хранятся в одном каталоге на хосте.
Теперь отредактируйте .env. Все строки в поставляемом примере закомментированы. Поэтому контейнер запускается на порту 8080 на всех адресах. Раскомментируйте и задайте следующие три параметра.
SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080SEARXNG_HOST=127.0.0.1 — самый важный параметр. Он задаёт опубликованный порт 127.0.0.1:8080:8080 вместо [::]:8080:8080. Поэтому контейнер отвечает только на loopback-адресе, и интернет не может обращаться к нему напрямую. Если пропустить этот параметр, контейнер будет открыт сразу после запуска, поскольку опубликованный порт Docker добавляется до правил брандмауэра. Подробное описание этой особенности приведено здесь: опубликованные порты Docker обходят ufw.
SEARXNG_VERSION=latest подходит для обучения. На важном сервере зафиксируйте тег. По состоянию на July 2026 теги выпусков основаны на датах и выглядят как 2026.3.25-541c6c3cb. Поэтому обновление развертывания выполняется по вашему решению, а не после изменения реестра.
settings.yml: важные параметры
Создайте core-config/settings.yml до первого запуска. use_default_settings: true указывает SearXNG загрузить собственные поставляемые значения по умолчанию, а затем применить только указанные вами ключи. Поэтому файл остается коротким и сохраняет работоспособность после обновлений, добавляющих новые параметры.
Сначала сгенерируйте секрет, поскольку это значение будет напрямую записано в файл.
openssl rand -hex 32use_default_settings: true
general:
instance_name: "search.example.com"
server:
base_url: "https://search.example.com/"
secret_key: "paste-the-openssl-output-here"
limiter: false
public_instance: false
image_proxy: true
valkey:
url: valkey://valkey:6379/0
search:
safe_search: 0
autocomplete: "duckduckgo"
formats:
- html
- jsonsecret_key подписывает данные сеансов и токенов. Поставляемое значение по умолчанию — буквальная строка ultrasecretkey. Если оставить ее, любой, кому известно это значение, сможет подделать такие токены. Замените его один раз и больше не меняйте: последующая замена удалит все сохраненные настройки.
base_url должен содержать общедоступный адрес HTTPS с завершающей косой чертой. Этот адрес SearXNG записывает в создаваемые ссылки. Если оставить значение localhost, ссылка «следующая страница» в удаленном браузере будет указывать на компьютер самого пользователя и завершится ошибкой.
formats определяет типы результатов, которые будет возвращать веб-конечная точка. json отсутствует в списке по умолчанию, поэтому запрос JSON возвращает 403, пока вы не добавите этот тип. image_proxy: true направляет миниатюры результатов через ваш сервер, поэтому сайты, на которых размещены эти изображения, не видят адреса ваших посетителей.
В valkey.url используется имя хоста valkey, поскольку это имя сервиса в файле Compose. Compose помещает оба контейнера в одну сеть, где имена сервисов разрешаются. Если указать localhost, ограничитель запросов завершится ошибкой, поскольку внутри контейнера core localhost обозначает этот контейнер.
Секрет хранится в обычном файле, поэтому защищайте каталог, в котором он находится, а не сам файл. chmod 750 /opt/searxng не позволяет другим пользователям хоста получить к нему доступ. Не устанавливайте для core-config/settings.yml режим 600: контейнер запускается от имени собственного непривилегированного пользователя, и файл, который он не может прочитать, полностью блокирует запуск SearXNG.
Запустите стек и проверьте его состояние.
cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/docker compose ps должен показать оба контейнера в состоянии running. curl должен вернуть ответ HTTP/1.1 200 OK. Если ответа нет, просмотрите docker compose logs core: ошибка YAML в settings.yml отображается там как ошибка разбора с указанием строки.
Разместите за nginx с TLS
Контейнер принимает соединения только через loopback, поэтому именно nginx делает сервис доступным. Он также добавляет защиту транспортного уровня (TLS). Запишите /etc/nginx/sites-available/searxng.
server {
listen 80;
server_name search.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}sudo ln -s /etc/nginx/sites-available/searxng /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d search.example.comКоманда nginx -t выводит syntax is ok и test is successful перед перезагрузкой. Certbot изменяет тот же файл, чтобы принимать соединения на 443 с сертификатом, и добавляет перенаправление с порта 80. DNS-запись для search.example.com уже должна указывать на этот сервер, поскольку центр сертификации подтверждает право владения, загружая файл по HTTP. Полное руководство, включая продление сертификата, приведено в руководстве по Certbot и nginx для Ubuntu 24.04.
Два заголовка для передачи данных не являются декоративными. Без X-Forwarded-For и X-Real-IP каждый запрос, поступающий в SearXNG, содержит адрес прокси. Поэтому ограничитель частоты запросов видит одного клиента, создающего весь трафик, и не может различать посетителей.
Почему скриптам и агентам нужен API поиска JSON
С json в formats та же конечная точка, которая отображает страницу, возвращает структурированные данные.
curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
| jq -r '.results[0:5][] | .url'Вы получаете объект с массивом results. Каждый элемент содержит url, title, content и поисковую систему, которая предоставила результат, а также answers, infoboxes и suggestions. Этого достаточно, чтобы передать данные в средство создания сводок, проверку ссылок или цикл исследования.
Это важно для любых систем с агентами. У языковой модели есть дата отсечения обучающих данных, поэтому для ответов на вопросы о текущих событиях ей нужен актуальный поиск. Коммерческие API поиска взимают плату за каждый запрос и используют жёсткие ограничения частоты. Локальный экземпляр занимает один контейнер на сервере, за который вы уже платите, а запросы не покидают его. Если вы подключаете инструменты к модели, та же логика применима к запуску MCP-серверов на VPS, где инструмент поиска обычно добавляют первым.
При использовании API соблюдайте два правила. Держите экземпляр закрытым. Привяжите API к адресу loopback или к частной сети и разрешите доступ только своим хостам. Затем отправляйте запросы с умеренной частотой. SearXNG пересылает ваш запрос настоящим поисковым системам, поэтому скрипт, выполняющий сто запросов в секунду, фактически просит Google заблокировать ваш сервер.
Лимитер и изменения для общедоступного экземпляра
Лимитер — это защита SearXNG от ботов. Он отслеживает заголовки запросов, адреса и частоту запросов, а затем отбрасывает трафик, похожий на автоматизированный. Для хранения этого состояния ему нужен Valkey, поэтому Valkey включён в Compose-файл.
Для частного экземпляра оставьте limiter: false. Ваши собственные скрипты по определению создают автоматизированный трафик, поэтому лимитер будет блокировать именно те вызовы JSON, для которых вы создали экземпляр. Контроль доступа должен выполнять обратный прокси: пара allow и deny в конфигурации nginx location, HTTP-аутентификация Basic или firewall, который разрешает доступ только с ваших других серверов.
Если вы публикуете экземпляр для других пользователей, включите оба параметра.
server:
limiter: true
public_instance: trueБолее точная настройка находится в core-config/limiter.toml, который контейнер читает из /etc/searxng/limiter.toml. Указывайте только ключи, которые хотите изменить. При работе через прокси необходимо объявить прокси, иначе лимитер будет считать адрес nginx одним клиентом, создающим вредоносный трафик.
[botdetection]
trusted_proxies = [
'127.0.0.0/8',
'::1',
]
[botdetection.ip_limit]
link_token = truelink_token = true заставляет SearXNG выдавать токен, который получает только настоящая сессия браузера. Это останавливает большинство простых скрейперов. Ожидайте, что через несколько дней общедоступный экземпляр начнут сканировать. Также ожидайте ошибок поисковых движков: чем больше трафика вы перенаправляете, тем раньше upstream-движки начнут возвращать CAPTCHA для адреса вашего сервера. Общедоступный экземпляр SearXNG требует постоянного обслуживания. Частный экземпляр этого не требует, поэтому он входит в большинство коротких списков сервисов, которые стоит разместить самостоятельно в 2026 году.
Почему поиск не возвращает результаты
Откройте /stats в вашем экземпляре. Здесь перечислены все поисковые системы с указанием частоты ошибок и времени ответа. С этого раздела следует начинать проверку, если результатов мало.
Поисковая система со статусом "Access denied" или ошибками "CAPTCHA" заблокировала адрес вашего сервера. Это часто происходит с адресами из диапазонов центров обработки данных, поскольку поисковые системы считают, что они принадлежат средствам автоматического сбора данных. После этого SearXNG временно отключает неисправную поисковую систему, а не повторяет запросы. Поэтому одна заблокированная система незаметно перестаёт участвовать в формировании результатов. Отключите её в settings.yml или примите потерю этой системы. Остальные поисковые системы продолжат отвечать.
Если все поисковые системы одновременно завершаются с ошибкой, в контейнере не работает разрешение имён для исходящих подключений или отсутствует маршрут в интернет. Проверьте это изнутри контейнера.
docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo okFAQ
Делает ли SearXNG мои поисковые запросы анонимными?
Он скрывает вашу личность от поисковых систем, к которым обращается, поскольку они видят запрос от вашего сервера, а не от браузера. При этом запрос остается видимым для вашего сервера, а ваш сервер — для поисковых систем. В экземпляре для одного пользователя весь трафик с этого адреса принадлежит вам, поэтому сам адрес становится идентификатором. Трафик между браузером и вашим экземпляром защищен сертификатом TLS.
Почему запрос JSON возвращает 403 Forbidden?
Причина связана с конфигурацией. Либо json отсутствует в списке formats в разделе search: файла settings.yml, что является состоянием по умолчанию, либо ограничитель включен и классифицировал ваш скрипт как бота. Сначала добавьте формат и перезапустите сервис с помощью docker compose restart core, затем повторите запрос. Если ошибка сохраняется, задайте limiter: false и контролируйте доступ на обратном прокси.
Нужен ли контейнер Valkey, если ограничитель отключен?
Оставьте его запущенным. SearXNG работает без него, но без этого контейнера ограничитель нельзя будет включить позже. Кроме того, контейнер хранит другие краткоживущие данные состояния. Контейнер небольшой и хранит только кэшированные данные, поэтому его удаление почти ничего не экономит и лишает вас этой возможности.
Как обновить SearXNG?
Выполните docker compose pull, затем docker compose up -d в /opt/searxng. Compose пересоздает контейнеры, для которых изменился образ, и оставляет каталог core-config/ без изменений, поэтому settings.yml сохраняется. Поскольку use_default_settings: true объединяет ваши ключи со значениями по умолчанию из выпуска, добавленные upstream параметры получают корректные значения вместо того, чтобы нарушать работу файла.
Могут ли несколько пользователей совместно использовать один экземпляр?
Да. В этом случае включите ограничитель и задайте public_instance: true. Настройки хранятся в браузере каждого посетителя, поэтому учетными записями управлять не нужно. В течение недели отслеживайте /stats после открытия доступа, поскольку поисковые системы upstream начинают отклонять запросы к вашему серверу задолго до того, как вы заметите отсутствие результатов.