SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-28

Como hospedar seu próprio mecanismo de busca com Hister

Aprenda a instalar o Hister em um VPS com binário ou Docker, configurar TLS e login e usar o endpoint MCP para pesquisar páginas e arquivos pessoais.

O que é o Hister e o que ele não é

O Hister é um mecanismo de pesquisa pessoal que você hospeda por conta própria. Ele indexa o texto completo das páginas que você visitou e dos arquivos que mantém, e permite pesquisar essa coleção a partir de uma interface web, de um cliente de terminal, de uma API HTTP ou de um assistente de IA (inteligência artificial). O Hister responde a uma pergunta: onde eu li isso.

A maioria dos leitores conhece esta ideia através do SearXNG, mas as duas ferramentas não são iguais. Se o nome que conhece é o Searx mais antigo, esse projeto não recebe commits de código desde 2023 e o SearXNG dá-lhe continuidade, por isso uma nova instância que configurar hoje será SearXNG de qualquer forma. O SearXNG é um proxy de metapesquisa. A sua consulta chega até ele, que consulta outros motores em seu nome e devolve os respetivos resultados sem o rastreamento. O índice pertence a esses motores. O Hister cria o seu próprio índice a partir do conteúdo que lhe fornece: páginas capturadas por uma extensão do navegador, histórico do navegador importado, URLs rastreados e ficheiros nos diretórios que indicar. Uma instância self-hosted do SearXNG dá-lhe acesso privado à Web pública. O Hister permite pesquisar o seu próprio histórico de leitura. As funções são diferentes, por isso é normal executar ambos no mesmo servidor. Nesse caso, convém saber quanto das suas pesquisas o SearXNG realmente oculta, porque substitui o seu IP pelo IP do servidor junto dos motores, em vez de ocultar as próprias consultas.

O Hister é software livre sob a AGPLv3 (GNU Affero General Public License, versão 3) ou posterior. Ele não utiliza telemetria nem precisa de um serviço de nuvem. Este guia fixa a versão v0.17.0, que era a release atual em 2026-07-28. Consulte a página de releases para verificar a tag atual antes de copiar qualquer coisa e fixe a tag encontrada.

Por que hospedar o Hister num VPS

Um índice só é útil quando está completo, e só está completo se o servidor estiver em execução enquanto você lê. Um laptop fica suspenso durante metade do dia. As páginas que você abre no telefone nesse período nunca chegam até ele, e uma importação noturna nunca começa. Um VPS (servidor virtual privado) permanece ativo, para que todos os dispositivos que você possui enviem conteúdo para o mesmo índice e o crawler continue a trabalhar enquanto você dorme.

O segundo motivo é a separação. Definir user_handling: true na seção app dá a cada conta as suas próprias credenciais e a sua própria coleção de documentos numa única instância. Assim, um servidor pode atender uma família ou uma pequena equipe sem que ninguém pesquise o conteúdo de leitura de outra pessoa.

O terceiro motivo é a infraestrutura. O VPS já tem um nome de host público e um certificado, que são necessários para que a extensão do navegador consiga alcançar o servidor a partir de uma rede que não controla. O mesmo par é usado noutras partes do servidor, porque o openGym regista a sua primeira passkey no nome de host que estiver ativo nesse momento, o que significa que o nome e o certificado têm de estar definidos antes de a primeira conta ser criada.

Opção de instalação um: o binário da release

Hister disponibiliza um binário por plataforma. Faça o download juntamente com o ficheiro de checksums e valide-o antes da instalação.

cd /tmp
curl -LO https://github.com/asciimoo/hister/releases/download/v0.17.0/hister_0.17.0_linux_amd64
curl -LO https://github.com/asciimoo/hister/releases/download/v0.17.0/hister_0.17.0_checksums.txt
sha256sum --ignore-missing -c hister_0.17.0_checksums.txt

Um resultado correto é a única linha hister_0.17.0_linux_amd64: OK. Uma linha FAILED significa que o download está danificado ou foi alterado. Faça o download novamente em vez de o instalar.

Instale o binário. Em seguida, crie uma conta de sistema e os diretórios que ele utilizará.

sudo install -m 755 /tmp/hister_0.17.0_linux_amd64 /usr/local/bin/hister
sudo useradd --system --home-dir /var/lib/hister --shell /usr/sbin/nologin hister
sudo install -d -o hister -g hister -m 750 /var/lib/hister
sudo install -d -m 755 /etc/hister
sudo hister create-config /etc/hister/config.yml

create-config grava um ficheiro de configuração predefinido e também confirma que o binário é executado nesta máquina. Um download para a arquitetura errada falha neste ponto, com cannot execute binary file: Exec format error.

Edite apenas as definições relevantes. O restante do ficheiro gerado pode permanecer como está.

app:
  directory: /var/lib/hister
  access_token: 'paste-a-long-random-string-here'
server:
  address: 127.0.0.1:4433
  base_url: https://hister.example.com

Gere o token com openssl rand -hex 32. O ficheiro passa a conter uma credencial. Restrinja as permissões antes de iniciar o serviço.

sudo chown root:hister /etc/hister/config.yml
sudo chmod 640 /etc/hister/config.yml

Execute-o com systemd

Escreva /etc/systemd/system/hister.service:

[Unit]
Description=Hister personal search engine
After=network-online.target
Wants=network-online.target

[Service]
User=hister
Group=hister
Environment=HISTER_CONFIG=/etc/hister/config.yml
ExecStart=/usr/local/bin/hister listen
Restart=on-failure
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/hister

[Install]
WantedBy=multi-user.target

HISTER_CONFIG é a variável de ambiente documentada para o caminho da configuração, portanto a unidade não depende do diretório inicial da conta hister. ProtectSystem=strict torna todo o sistema de ficheiros apenas de leitura para este serviço, razão pela qual ReadWritePaths tem de indicar o diretório de dados. ProtectHome=yes oculta /home do serviço, portanto um diretório monitorizado dentro de /home pareceria vazio para o indexador. Remova essa linha se precisar de indexar ficheiros nesse local.

sudo systemctl daemon-reload
sudo systemctl enable --now hister
systemctl status hister --no-pager
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:4433/

Qualquer código de estado HTTP apresentado pelo último comando significa que o processo está a escutar. curl: (7) Failed to connect significa que não está, e journalctl -u hister -n 50 --no-pager indicará o motivo.

Caminho de instalação dois: Docker Compose

A imagem é publicada no registo de contentores do GitHub, com uma tag por versão.

services:
  hister:
    image: ghcr.io/asciimoo/hister:v0.17.0
    container_name: hister
    user: '1000:1000'
    restart: unless-stopped
    environment:
      - HISTER__SERVER__ADDRESS=0.0.0.0:4433
      - HISTER__SERVER__BASE_URL=https://hister.example.com
      - HISTER__APP__ACCESS_TOKEN=${HISTER_ACCESS_TOKEN}
    volumes:
      - ./data:/hister/data
    ports:
      - 127.0.0.1:4433:4433

Cada chave de configuração tem uma substituição de ambiente no formato HISTER__<SECTION>__<KEY>, com dois underscores como separador. Por isso, uma implementação em contentor não precisa de montar um ficheiro de configuração. Mantenha HISTER_ACCESS_TOKEN num ficheiro .env junto ao ficheiro Compose. Se preferir editar um ficheiro, docker run --rm ghcr.io/asciimoo/hister:v0.17.0 create-config > config.yml apresenta os valores predefinidos.

As duas linhas acima são fáceis de configurar incorretamente, e vale a pena compreender ambas.

O endereço dentro do contentor tem de ser 0.0.0.0:4433. Um contentor tem o seu próprio namespace de rede. Por isso, um processo associado a 127.0.0.1 nesse contentor só pode ser acedido a partir do próprio contentor, e não há nenhum serviço para o qual a porta publicada possa encaminhar o tráfego.

A porta publicada deve ser escrita como 127.0.0.1:4433:4433, e não como 4433:4433. O Docker publica portas através da inserção das suas próprias regras netfilter. Essas regras são avaliadas antes das regras do ufw. Por isso, um 4433:4433 simples continua acessível a partir da Internet, mesmo num sistema em que ufw status indique que a porta está fechada. Associar o lado do anfitrião a 127.0.0.1 faz com que o reverse proxy seja a única forma de acesso. O mesmo problema aplica-se a todos os contentores no servidor, e Docker Compose num VPS aborda o restante.

A imagem predefinida é executada como UID 1000 e GID 1000. Por isso, ./data tem de ser gravável por essa conta. Caso contrário, o contentor termina durante o arranque com um erro de permissões. sudo chown -R 1000:1000 ./data corrige o problema. Se esses números não forem familiares, leia primeiro com que UID e GID um contentor escreve ficheiros.

Por que expor um índice de pesquisa pessoal é a pior opção

Por padrão, o Hister escuta em 127.0.0.1:4433, e esse padrão é intencional. Pense no que o índice contém depois de um mês de uso: páginas internas da wiki, faturas, tickets de suporte que abriu enquanto tinha sessão iniciada, páginas de reposição de palavra-passe e o texto integral de tudo o que leu. A documentação do projeto afirma isso diretamente: "O Hister transmite todo o seu histórico de navegação, incluindo o conteúdo das páginas, de e para o servidor."

Uma base de dados de palavras-passe divulgada ainda tem de ser quebrada. Um índice pessoal divulgado está em texto simples e já permite pesquisas, por isso exige mais cuidado do que a pequena aplicação self-hosted com que se parece.

Isto conduz a duas conclusões. O Hister não exige autenticação por padrão, por isso um reverse proxy, por si só, publica uma cópia pesquisável do que leu para qualquer pessoa que descubra o hostname. O endpoint MCP também é servido por padrão em /mcp e, sem um token, qualquer cliente que consiga aceder-lhe pode executar uma pesquisa no índice.

Configure a autenticação antes de o serviço sair do localhost pela primeira vez. Um único utilizador só precisa de app.access_token, um segredo partilhado enviado pela extensão do browser, pelo cliente de terminal e por qualquer cliente MCP. Para várias pessoas, defina user_handling: true e crie as contas:

sudo -u hister hister create-user alice --admin --config /etc/hister/config.yml

O comando pede uma palavra-passe com pelo menos 8 caracteres. Cada conta recebe os seus próprios documentos e um token de API pessoal, que o proprietário pode regenerar na página de perfil ou com a flag --regen-token em hister update-user. Gerar um novo token invalida imediatamente o anterior, por isso é necessário atualizar depois todos os dispositivos usados por essa conta.

Não altere app.public sem uma razão específica. O modo público permite pesquisas sem autenticação, pré-visualizações, disponibilização de ficheiros e pesquisas MCP, mas continua a bloquear operações de escrita, acesso ao histórico e operações administrativas.

Proxy reverso, TLS e firewall

O Hister não serve HTTPS diretamente, por isso termine o TLS (transport layer security) à frente dele. O Caddy é o caminho mais curto, porque solicita e renova certificados automaticamente através do ACME (automatic certificate management environment).

hister.example.com {
    reverse_proxy 127.0.0.1:4433
}

Recarregue-o com sudo systemctl reload caddy. Duas condições têm de ser cumpridas antes de um certificado poder ser emitido: o registo A de hister.example.com tem de apontar para este servidor, e a porta 80 tem de estar aberta, porque o desafio HTTP-01 é respondido nessa porta. Quando uma delas não é cumprida, o browser apresenta um erro de TLS em vez da página, e o log do Caddy repete a falha do desafio.

Depois, feche todas as outras portas.

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

A porta 4433 foi omitida dessa lista de propósito. Um hostname público não é a única forma de acesso, e um serviço onion apontado para a mesma porta de loopback permite aceder ao seu índice a partir dos seus próprios dispositivos sem um registo DNS ou qualquer porta de entrada aberta.

server.base_url tem de corresponder ao endereço que escreve no browser, incluindo o esquema. Quando não corresponde, a interface é carregada com texto sem estilos e imagens em falta, porque o servidor cria os links dos recursos a partir de base_url e o browser tenta depois obtê-los de uma origem que não responde. Esse mesmo URL é configurado na extensão do browser.

Preenchendo o índice

A extensão do navegador é o principal coletor. Instale-a a partir do Mozilla Add-ons ou da Chrome Web Store, abra a página de opções, defina o URL do servidor como https://hister.example.com e cole o token de acesso. Depois, ela captura o título, o texto completo, o HTML e o favicon de cada página que visitar e envia esses dados para o servidor. A extração ocorre no lado do cliente, dentro do navegador. A extensão não contacta terceiros, e o único pedido externo que faz é para obter o favicon da página.

A extração no lado do cliente é o que torna possível um índice privado. A extensão vê uma página exatamente como a vê, depois do login e da renderização. Assim, uma página de wiki interna ou um artigo pago é indexado corretamente, sem que o servidor precise das credenciais. Isto também significa que tudo o que consultar pode ser incluído no índice. Por isso, as regras de exclusão devem ser configuradas antes de adicionar mais conteúdo.

As regras de exclusão ficam em rules.json numa instalação para um único utilizador, ou por utilizador na base de dados. O separador Rules na interface web é a forma mais simples de as editar. São expressões regulares Go aplicadas ao URL completo:

^https://mail\.example\.com
^https://bank\.example\.com
.*?utm_source=

Um padrão como ^mail.example.com nunca corresponde, porque a cadeia testada começa com https://. Um $ no fim também falha em qualquer URL que contenha uma cadeia de consulta, porque os parâmetros da consulta são mantidos durante a correspondência.

O histórico existente é importado através da leitura da própria base de dados do navegador. Por isso, esse comando deve ser executado na máquina que contém o perfil do navegador: o seu portátil, não o VPS. Instale aí o mesmo binário e indique o servidor:

export HISTER_TOKEN='your-access-token'
hister import browser firefox -u https://hister.example.com -t "$HISTER_TOKEN"

A importação é executada como uma tarefa retomável chamada browser-import-YYYY-MM-DD. Pode interrompê-la e reiniciá-la mais tarde. Os serviços de marcadores são importados da mesma forma, incluindo Linkwarden, Karakeep, Wallabag, Linkding, Readeck e Shaarli. Uma nova importação obtém apenas o que é mais recente do que a importação anterior.

Os ficheiros no servidor são indexados ao indicar diretórios na configuração:

indexer:
  directories:
    - path: '/var/lib/hister/documents'
      label: 'documents'
      filetypes: ['pdf', 'docx', 'md', 'txt']

Ficheiros PDF, DOCX, Markdown, Org mode e ficheiros de texto UTF-8 válidos são lidos como texto completo. Fotografias e vídeos não fazem parte dessa lista. Por isso, uma biblioteca de imagens precisa de um servidor que indexe rostos, locais e datas, e PhotoPrism e Immich são as duas opções normalmente comparadas para esse trabalho. Uma única página é adicionada com hister index https://example.com. Transformar sites inteiros em texto limpo para outras ferramentas é uma tarefa separada, feita por rastreadores autoalojados que convertem páginas em texto limpo.

A pesquisa é baseada em campos, por isso vale a pena ler a linguagem de consulta durante dez minutos:

"connection reset" domain:github.com added:<30d
title:(wireguard|nftables) -tutorial sort:-visits

Indique o seu próprio índice a um agente de programação através do MCP

MCP (model context protocol) é a interface que um assistente utiliza para chamar ferramentas num servidor. O Hister disponibiliza-a em POST /mcp, na mesma URL base, através do transporte HTTP com streaming, e expõe search, get_preview e get_history. A autenticação utiliza o mesmo token bearer que o restante da API. Se a chamada de ferramentas for uma novidade, escrever o seu próprio ciclo de agente pequeno é a forma mais rápida de perceber o que um endpoint como este realmente disponibiliza a um assistente.

{
  "mcpServers": {
    "hister": {
      "url": "https://hister.example.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_ACCESS_TOKEN"
      }
    }
  }
}

Um cabeçalho X-Access-Token funciona como alternativa a Authorization.

O valor está naquilo que o agente pesquisa. A pesquisa aberta na Web devolve os resultados que têm melhor classificação atualmente. Para software em evolução rápida, esses resultados são frequentemente documentação de uma versão que não está a utilizar. O seu próprio índice devolve a página que já leu e decidiu guardar. get_preview disponibiliza a cópia armazenada, por isso a resposta continua disponível mesmo que a página original fique offline. Dê ao agente ambas as fontes se também quiser resultados públicos: uma skill de pesquisa no navegador baseada no SearXNG adiciona a Web aberta como uma ferramenta separada. Quando executar mais do que um destes endpoints, vale a pena ler alojar servidores MCP num VPS, porque todos partilham este problema de exposição.

Disco, cópias de segurança e manutenção

A documentação considera cerca de 100 KB por página indexada, incluindo a pré-visualização comprimida, portanto cem mil páginas correspondem aproximadamente a 10 GB. Não existe um sistema de quotas. Duas definições são frequentemente confundidas: indexer.max_file_size_mb (1 MiB por predefinição) limita um único ficheiro monitorizado, enquanto server.max_batch_body_size (40 MiB por predefinição) limita um pedido à API.

O diretório definido por app.directory contém index.db, com os ficheiros de índice por idioma, db.sqlite3, para contas e tarefas, data/html/, para pré-visualizações, e rules.json. Uma cópia de segurança consiste em parar o serviço e copiar todo esse diretório e o ficheiro de configuração. hister export backup.json exporta documentos como JSON para migração; não é uma cópia de segurança do servidor.

É útil conhecer dois comandos de manutenção. hister reindex recria os índices de pesquisa, operação necessária depois de alterar as definições do indexador. Se o consumo de memória aumentar durante uma importação grande, defina detect_languages: false na secção indexer e recrie o índice. hister cleanup remove ficheiros órfãos de pré-visualizações e favicons deixados por eliminações.

A eliminação é feita através de uma consulta, por isso execute primeiro em modo de simulação:

hister delete 'domain:example.com' --dry --verbose

Uma página eliminada volta a aparecer se um coletor continuar a submetê-la. Adicione a regra de exclusão antes de a eliminar.

A AGPLv3 só é relevante se alterar o código. Executar uma cópia sem modificações para uso próprio não implica qualquer obrigação. Se modificar o Hister e permitir que outras pessoas utilizem a sua versão através de uma rede, a licença exige que lhes disponibilize o código-fonte modificado.

Modos de falha e mensagens apresentadas

O servidor não inicia. A porta 4433 já está ocupada ou o ficheiro de configuração contém um erro de sintaxe YAML. sudo ss -lntp | grep 4433 mostra o processo que ocupa a porta e journalctl -u hister -n 50 --no-pager apresenta o erro de análise.

A interface carrega, mas parece danificada. Texto desordenado e imagens em falta indicam que server.base_url não corresponde ao URL na barra de endereços. Uma barra final também conta como divergência.

A extensão não estabelece ligação. O URL do servidor configurado na extensão tem de ser igual a base_url. O servidor tem de estar em execução e atualizado. Uma firewall entre os dois pode bloquear a ligação sem apresentar uma mensagem na página. O Firefox não coloca os logs das extensões na consola normal. Abra about:debugging#/runtime/this-firefox e inspecione a extensão Hister.

O contentor termina durante o arranque. Um erro de permissões em ./data indica que o diretório pertence a um UID diferente de 1000. Esse é o UID da conta dentro da imagem predefinida.

403 Forbidden numa rota administrativa. POST /api/reindex e POST /api/cleanup estão disponíveis apenas para administradores quando a gestão de utilizadores está ativa. Por isso, uma conta normal é recusada nessas rotas.

O consumo de memória aumenta durante uma importação. A deteção de idioma sobre um histórico grande é a causa habitual. Defina detect_languages: false e execute hister reindex depois.

FAQ

Em que é que o Hister é diferente do SearXNG?

O SearXNG é um proxy de metapesquisa: encaminha a sua consulta para motores públicos e devolve os resultados sem os elementos de rastreamento, pelo que o índice pertence a esses motores. O Hister mantém o seu próprio índice de texto integral das páginas que visitou e dos ficheiros que guarda, por isso responde a "onde é que li isto", enquanto o SearXNG responde a "o que diz a Web". Resolvem problemas diferentes e muitas pessoas executam ambos no mesmo servidor.

É seguro colocar todo o meu histórico de navegação num VPS?

Só depois de tratar da exposição. O Hister associa-se a 127.0.0.1:4433 e, por predefinição, não requer autenticação. Defina app.access_token ou user_handling: true, coloque um reverse proxy com TLS à frente do serviço e mantenha a porta 4433 fechada na firewall. Um índice de texto integral do que leu está em texto simples, pelo que qualquer pessoa que consiga aceder à porta pode ler tudo sem ter de quebrar nenhuma proteção criptográfica.

Preciso da extensão do navegador ou posso simplesmente importar o meu histórico?

A importação é um preenchimento inicial único. Lê a base de dados do histórico do próprio navegador, por isso é executada no computador que contém o perfil do navegador, e não no servidor. A extensão mantém o índice atualizado a partir desse momento e captura páginas protegidas por autenticação porque extrai o conteúdo no navegador depois de a página ser renderizada. Uma configuração comum consiste numa importação seguida da utilização da extensão.

Um agente de programação pode pesquisar o meu índice do Hister?

Sim. O Hister é um servidor MCP (model context protocol) em POST /mcp no seu URL base e expõe search, get_preview e get_history. Aponte o cliente para https://your-host/mcp com um cabeçalho Authorization: Bearer que contenha o seu token de acesso. O agente pesquisa então a documentação que leu efetivamente, na versão que leu, em vez de pesquisar o que hoje obtém uma classificação mais elevada num motor de pesquisa público.