SSD Nodes Learn 8GB de RAM — $66/ano
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-02

Como hospedar seu próprio SearXNG com Docker Compose

Execute o SearXNG no seu VPS com Docker Compose, settings.yml, limiter e nginx com TLS. Exponha uma API JSON privada para scripts sem chave ou cobrança por consulta.

O que você está criando

Hospedar o SearXNG por conta própria fornece um mecanismo de pesquisa privado executado no seu próprio servidor. O SearXNG é um mecanismo de metapesquisa: ele recebe sua consulta, consulta outros mecanismos, como Google, Bing, DuckDuckGo e Wikipedia, e combina os resultados em uma única página. Nenhum perfil é criado e nenhum cookie de rastreamento é definido, porque a única máquina que armazena sua consulta é a sua.

A pilha é pequena. Dois contêineres, um arquivo de configurações e um proxy reverso. A decisão principal é definir se a instância será privada, ou seja, acessível apenas por você e pelos seus próprios scripts, ou pública, ou seja, acessível a qualquer pessoa na internet. Essa escolha altera as configurações de segurança. Portanto, faça essa definição antes de inserir qualquer informação. A opção padrão é privada.

Há outro motivo para executar uma instância. Uma instância do SearXNG fornece uma interface JSON. Assim, qualquer script ou agente de IA que você desenvolver terá uma API de pesquisa sob seu controle, sem chave, cobrança por consulta ou mensagens sobre limites de cota.

Instalar o SearXNG com Docker Compose

O projeto publica uma imagem de contêiner e um arquivo Compose. Baixe ambos para um servidor Ubuntu 24.04 novo que já tenha o Docker Engine e o plugin Compose. Se o Docker for novidade para você, comece por Noções básicas do Docker Compose em um VPS e depois volte.

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

O arquivo Compose define dois serviços. core é o próprio SearXNG, e valkey é um armazenamento de dados em memória usado para limitação de taxa e para estado temporário. Ele monta ./core-config/ em /etc/searxng/ dentro do contêiner, portanto tudo o que você configurar ficará nesse único diretório no host.

Agora edite .env. Todas as linhas do exemplo fornecido estão comentadas. Por isso, o contêiner inicia na porta 8080 em todos os endereços. Remova o comentário e defina estes três valores.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 é a configuração mais importante. Ela faz a porta publicada ser 127.0.0.1:8080:8080 em vez de [::]:8080:8080, portanto o contêiner responde somente no endereço de loopback e a internet não pode acessá-lo diretamente. Se você ignorar isso, o contêiner ficará exposto assim que iniciar, porque uma porta publicada pelo Docker é inserida antes das regras do firewall. Leia esta armadilha em detalhes: portas publicadas pelo Docker ignoram o ufw.

SEARXNG_VERSION=latest é suficiente enquanto você estiver aprendendo. Em um servidor importante, fixe a tag. Em julho de 2026, as tags de release são baseadas em datas e têm um formato como 2026.3.25-541c6c3cb, portanto uma implantação com tag fixa será atualizada quando você decidir, e não quando o registro for alterado sem sua intervenção.

settings.yml: as partes importantes

Crie core-config/settings.yml antes da primeira inicialização. use_default_settings: true instrui o SearXNG a carregar os padrões fornecidos com o software e aplicar apenas as chaves que você escreveu. Assim, o arquivo permanece curto e continua funcionando após atualizações que adicionem novas opções.

Gere o segredo primeiro, porque o valor será inserido diretamente no arquivo.

openssl rand -hex 32
use_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
    - json

secret_key assina os dados de sessão e de token. O padrão fornecido é a string literal ultrasecretkey. Mantê-la significa que qualquer pessoa que conheça esse padrão pode forjar esses tokens. Substitua-a uma vez e não a altere depois: mudá-la invalida todas as preferências salvas.

base_url deve ser o endereço HTTPS público, com a barra final. É esse endereço que o SearXNG grava nos links que renderiza. Se ele continuar apontando para localhost, o link "próxima página" em um navegador remoto apontará para a própria máquina do leitor e falhará.

formats define quais tipos de saída o endpoint web produzirá. json não está na lista padrão. Por isso, uma solicitação JSON retorna 403 até que você o adicione. image_proxy: true encaminha as miniaturas dos resultados pelo seu servidor. Assim, os sites que hospedam essas imagens não veem os endereços dos seus visitantes.

O valkey.url usa o nome de host valkey porque esse é o nome do serviço no arquivo Compose. O Compose coloca os dois containers na mesma rede, onde os nomes dos serviços são resolvidos. Aponte-o para localhost e o limitador falhará, porque, dentro do container core, localhost é o próprio container.

O segredo fica em um arquivo simples. Portanto, proteja o diretório que o contém, e não o arquivo isoladamente. chmod 750 /opt/searxng impede o acesso de outros usuários do host. Não restrinja core-config/settings.yml para o modo 600: o container é executado com seu próprio usuário sem privilégios, e um arquivo que ele não consegue ler impede completamente a inicialização do SearXNG.

Inicie a stack e verifique-a.

cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/

docker compose ps deve mostrar os dois containers no estado running. O curl deve responder com HTTP/1.1 200 OK. Se não houver resposta, leia docker compose logs core, pois um erro de YAML em settings.yml aparecerá ali como um erro de análise que informa a linha.

Coloque-o atrás do nginx com TLS

O contêiner escuta apenas no loopback. O nginx permite o acesso a ele e também adiciona a segurança da camada de transporte (TLS). Escreva /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 exibe syntax is ok e test is successful antes de você recarregar. O Certbot reescreve o mesmo arquivo para escutar na porta 443 com um certificado e adiciona um redirecionamento da porta 80. O registro DNS de search.example.com já deve apontar para este servidor, porque a autoridade certificadora comprova a propriedade buscando um arquivo por HTTP. O passo a passo completo, incluindo a renovação, está em o guia do Certbot e nginx para Ubuntu 24.04.

Os dois cabeçalhos de encaminhamento não são decorativos. Sem X-Forwarded-For e X-Real-IP, toda solicitação que chega ao SearXNG carrega o endereço do proxy. Assim, o limitador de taxa vê um único cliente gerando todo o tráfego e não consegue distinguir os visitantes.

Por que scripts e agentes querem uma API de pesquisa JSON

Com json em formats, o mesmo endpoint que renderiza a página retorna dados estruturados.

curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
  | jq -r '.results[0:5][] | .url'

Você recebe um objeto com um array results, em que cada entrada contém url, title, content e o mecanismo que forneceu o resultado, junto com answers, infoboxes e suggestions. Isso é suficiente para alimentar um resumidor, um verificador de links ou um ciclo de pesquisa.

Isso é importante para qualquer coisa orientada a agentes. Um modelo de linguagem tem uma data de corte no treinamento, portanto precisa de pesquisa em tempo real para responder a perguntas sobre o presente. Além disso, as APIs comerciais de pesquisa cobram por consulta e impõem limites rigorosos de taxa. Uma instância local custa um container em um servidor que você já paga, e as consultas nunca saem dele. Se você está conectando ferramentas a um modelo, o mesmo raciocínio se aplica a executar servidores MCP em um VPS, em que uma ferramenta de pesquisa geralmente é a primeira que as pessoas adicionam.

Há duas regras para usar a API. Mantenha a instância privada. Vincule o lado da API ao endereço de loopback ou a uma rede privada e permita que apenas seus próprios hosts a acessem. Em seguida, faça as consultas com moderação. O SearXNG encaminha sua solicitação para mecanismos de pesquisa reais, portanto um script que execute cem consultas por segundo estará pedindo ao Google para bloquear seu servidor.

O limitador e o que muda em uma instância pública

O limitador é a defesa contra bots do SearXNG. Ele monitora cabeçalhos de requisição, endereços e taxas de requisições, e descarta o tráfego que parece automatizado. Ele precisa do Valkey para armazenar esse estado. Por isso, o arquivo Compose o inclui.

Em uma instância privada, mantenha limiter: false. Seus próprios scripts são tráfego automatizado por definição. Portanto, o limitador bloquearia exatamente as chamadas JSON para as quais você criou a instância. O controle de acesso fica a cargo do proxy reverso: um par allow e deny na configuração location do nginx, autenticação HTTP básica ou um firewall que aceite conexões apenas dos seus outros servidores.

Se você publicar a instância para outras pessoas, ative as duas opções.

server:
  limiter: true
  public_instance: true

O controle mais detalhado fica em core-config/limiter.toml, que o contêiner lê em /etc/searxng/limiter.toml. Escreva apenas as chaves que deseja alterar. Atrás de um proxy, declare o proxy. Caso contrário, o limitador tratará o endereço do nginx como o endereço do único cliente abusivo.

[botdetection]
trusted_proxies = [
  '127.0.0.0/8',
  '::1',
]

[botdetection.ip_limit]
link_token = true

link_token = true faz o SearXNG emitir um token que somente uma sessão real do navegador obterá. Isso bloqueia a maioria dos scrapers simples. Espere que uma instância pública atraia esses scrapers em poucos dias. Espere também erros dos mecanismos, porque quanto mais tráfego você encaminhar, mais cedo os mecanismos upstream começarão a retornar CAPTCHAs para o endereço do seu servidor. Uma instância pública do SearXNG exige trabalho contínuo. Uma instância privada não exige, e por isso ela aparece na maioria das listas curtas de coisas que vale a pena hospedar por conta própria em 2026.

Por que as pesquisas não retornam resultados

Abra /stats na sua instância. Ele lista cada mecanismo com sua taxa de erro e tempo de resposta. Esse é o primeiro lugar a verificar quando os resultados parecem insuficientes.

Um mecanismo que exibe erros como "Access denied" ou "CAPTCHA" bloqueou o endereço do seu servidor. Isso é comum em endereços de faixas de data centers, porque os mecanismos de pesquisa presumem que eles pertencem a scrapers. O SearXNG então suspende o mecanismo com falha por um período, em vez de tentar novamente. Assim, um mecanismo bloqueado deixa de participar dos resultados sem chamar atenção. Desative-o em settings.yml ou aceite a perda. Os mecanismos restantes continuam respondendo.

Se todos os mecanismos falharem ao mesmo tempo, o container não tem resolução de nomes de saída funcional ou não tem uma rota para a internet. Teste isso de dentro do container.

docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo ok

FAQ

O SearXNG torna minhas pesquisas anônimas?

Ele oculta sua identidade dos mecanismos consultados, porque eles veem seu servidor fazendo a solicitação, e não o seu navegador. Ele não oculta a consulta do seu servidor nem oculta seu servidor desses mecanismos. Em uma instância com um único usuário, todo o tráfego desse endereço é seu, então o próprio endereço se torna o identificador. O tráfego entre seu navegador e sua instância é protegido pelo certificado TLS.

Por que uma solicitação JSON retorna 403 Forbidden?

Há duas causas, e ambas estão relacionadas à configuração. Ou json está ausente da lista formats em search: dentro de settings.yml, que é o estado padrão, ou o limitador está ativado e classificou seu script como um bot. Adicione o formato primeiro, reinicie com docker compose restart core e tente novamente. Se ainda falhar, defina limiter: false e controle o acesso no proxy reverso.

Preciso do contêiner Valkey se mantiver o limitador desativado?

Mantenha-o em execução. O SearXNG funciona sem ele, mas o limitador não poderá ser ativado posteriormente sem esse contêiner, que também armazena outros estados de curta duração. O contêiner é pequeno e armazena apenas dados em cache, portanto removê-lo economiza muito pouco e elimina essa opção.

Como atualizo o SearXNG?

Execute docker compose pull e depois docker compose up -d em /opt/searxng. O Compose recria qualquer contêiner cuja imagem tenha sido alterada e deixa o diretório core-config/ intacto, portanto settings.yml é preservado. Como use_default_settings: true mescla suas chaves sobre os padrões fornecidos, as opções adicionadas upstream chegam com valores adequados, em vez de corromper o arquivo.

Várias pessoas podem compartilhar uma única instância?

Sim. Esse é o caso em que você ativa o limitador e define public_instance: true. As preferências são armazenadas no próprio navegador de cada visitante, portanto não há contas para gerenciar. Monitore /stats por uma semana depois de disponibilizar a instância, porque os mecanismos upstream começam a rejeitar seu servidor muito antes de você perceber a ausência de resultados.

#searxng#search#privacy#self-hosting#docker