SSD Nodes Learn 🎉 VPS desde $5.50/mês
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-21

Hister: seu buscador pessoal com Docker ou binário

Instale o Hister em um VPS para pesquisar páginas e arquivos indexados. Veja instalação por binário e Docker, TLS, login e como usar o endpoint MCP.

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

O Hister é um motor de pesquisa pessoal que aloja no seu próprio servidor. Indexa o texto completo das páginas que consultou e dos ficheiros que mantém. Depois, permite pesquisar essa coleção através 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 é que li isto.

A maioria dos leitores conhece esta ideia através do SearXNG, mas as duas ferramentas não são iguais. O SearXNG é um proxy de metapesquisa. A consulta é enviada para o SearXNG, que consulta outros motores em seu nome e devolve os respetivos resultados sem o rastreio. 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 existentes nos diretórios que indicar. Uma instância SearXNG alojada no seu próprio servidor proporciona acesso privado à web pública. O Hister permite pesquisar aquilo que leu. As funções são diferentes, por isso é normal executar ambos no mesmo servidor.

O Hister é software livre ao abrigo da AGPLv3 (GNU Affero General Public License, versão 3) ou posterior. Não recolhe telemetria e não precisa de um serviço na cloud. Este guia fixa a versão v0.17.0, que era a versão atual em 2026-07-28. Consulte a página de releases para confirmar a tag atual antes de copiar qualquer conteúdo e fixe a tag aí indicada.

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 é iniciada. Um VPS (servidor privado virtual) permanece ativo, para que todos os seus dispositivos publiquem no mesmo índice e o crawler continue trabalhando 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 os conteúdos lidos por outra pessoa.

O terceiro motivo é a infraestrutura de conexão. O VPS já tem um nome de host público e um certificado, que é o que a extensão do navegador precisa para alcançar o servidor a partir de uma rede que você não controla.

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

O Hister disponibiliza um binário por plataforma. Faça o download juntamente com o ficheiro de checksums e valide-os 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 novamente o download em vez de o instalar.

Instale o binário. Depois, 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 escreve um ficheiro de configuração predefinido. 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 as poucas definições relevantes. O restante ficheiro gerado pode permanecer inalterado.

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 contém agora uma credencial. Restrinja as permissões antes de o serviço arrancar.

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. Assim, a unidade não depende do diretório inicial da conta hister. ProtectSystem=strict torna todo o sistema de ficheiros só de leitura para este serviço. Por isso, ReadWritePaths tem de indicar o diretório de dados. ProtectHome=yes oculta /home do serviço. Assim, 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.

Instalação, opção 2: Docker Compose

A imagem é publicada no GitHub Container Registry, com uma tag por release.

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>, usando dois sublinhados como separador. Por isso, uma implantação em contentor não precisa de um ficheiro de configuração montado. Mantenha HISTER_ACCESS_TOKEN num ficheiro .env junto do 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 anteriores 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 ligado a 127.0.0.1 nesse contentor só pode ser acedido a partir do próprio contentor, e a porta publicada não tem nenhum serviço para onde encaminhar o tráfego.

A porta publicada deve ser escrita como 127.0.0.1:4433:4433, não como 4433:4433. O Docker publica portas inserindo as suas próprias regras do 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 indica que a porta está fechada. Ligar o lado do anfitrião a 127.0.0.1 faz do reverse proxy 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 com 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 lhe forem familiares, leia primeiro com que UID e GID um contentor grava ficheiros.

Por que um índice de pesquisa pessoal é a pior coisa para expor

Por predefinição, o Hister escuta em 127.0.0.1:4433, e esse valor predefinido é intencional. Pense no que o índice contém após um mês de utilização: páginas internas da wiki, faturas, pedidos de suporte que abriu enquanto estava autenticado, páginas de reposição de palavras-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 decifrada. 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 à qual se assemelha.

Há duas consequências. O Hister não exige autenticação por predefiniçã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 predefinição em /mcp. Sem um token, qualquer cliente que consiga aceder-lhe pode executar uma pesquisa no índice.

Configure a autenticação antes de o serviço deixar o localhost pela primeira vez. Para um único utilizador, basta 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 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. O proprietário pode regenerá-lo a partir da página de perfil ou com a flag --regen-token em hister update-user. Gerar um novo token invalida imediatamente o anterior. Depois disso, é necessário atualizar todos os dispositivos utilizados 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. Continua, no entanto, 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 é a opção mais simples, porque solicita e renova os 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. É necessário cumprir duas condições antes de emitir um certificado: 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 destas condições não é cumprida, o navegador 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.

server.base_url tem de corresponder ao endereço que escreve no navegador, 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 navegador tenta depois solicitá-los a uma origem que não responde. Esse mesmo URL é introduzido na extensão do navegador.

Preenchimento do í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. A extensão captura o título, o texto completo, o HTML e o favicon de cada página que visita 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. O único pedido externo que faz é para obter o favicon da página.

A extração no lado do cliente permite criar um índice privado. A extensão vê a página exatamente como o utilizador a vê, depois do login e da renderização. Assim, uma página de uma wiki interna ou um artigo pago é indexado corretamente, e o servidor nunca precisa das credenciais. Isto também significa que tudo o que consulta 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. As regras 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 por https://. Um $ no fim também falha em qualquer URL que contenha uma query string, porque os parâmetros da query 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, ou seja, no seu portátil e não no VPS. Instale o mesmo binário nessa máquina e aponte-o para 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 iniciá-la novamente 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 conteúdo mais recente do que a importação anterior.

Os ficheiros no servidor são indexados através da indicação dos 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 texto UTF-8 válido são lidos como texto completo. Fotografias e vídeos não estão nessa 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 página individual é adicionada com hister index https://example.com. Transformar sites inteiros em texto limpo para outras ferramentas é uma tarefa separada, tratada por rastreadores autoalojados que convertem páginas em texto limpo.

A pesquisa é baseada em campos. Por isso, vale a pena dedicar dez minutos à leitura da linguagem de consulta:

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

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

O MCP (model context protocol) é a interface que um assistente utiliza para chamar ferramentas num servidor. O Hister disponibiliza essa interface em POST /mcp, no mesmo URL base, através do transporte HTTP streamable, e expõe search, get_preview e get_history. A autenticação utiliza o mesmo bearer token que o resto da API.

{
  "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 hoje. No caso de software que muda rapidamente, esses resultados são muitas vezes 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 manter, e get_preview disponibiliza a cópia armazenada. Assim, a resposta continua disponível mesmo que a página original fique offline. Dê ao agente as duas fontes se também quiser resultados públicos: uma skill de pesquisa no navegador baseada em SearXNG adiciona a Web aberta como uma ferramenta separada. Quando executar mais de um destes endpoints, vale a pena ler alojar servidores MCP num VPS, porque todos partilham este problema de exposição.

Disco, backups e manutenção

A documentação considera cerca de 100 KB por página indexada, incluindo a pré-visualização comprimida. Assim, cem mil páginas ocupam aproximadamente 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 da API.

O diretório indicado 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. Um backup consiste num serviço parado, numa cópia de todo esse diretório e numa cópia do ficheiro de configuração. hister export backup.json escreve os documentos em JSON para migração. Não é um backup do servidor.

Há dois comandos de manutenção que deve conhecer. hister reindex recria os índices de pesquisa. Isto é necessário 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 os índices. 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-a primeiro em modo de simulação:

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

Uma página eliminada volta a aparecer se algum coletor continuar a enviá-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 cria obrigações. 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 que verá

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 aparece danificada. Texto desordenado e imagens em falta indicam que server.base_url não corresponde ao URL na barra de endereço. Uma barra final também conta como diferença.

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

O contentor termina ao iniciar. Um erro de permissões em ./data significa que o diretório pertence a um UID diferente de 1000, que é a conta usada dentro da imagem predefinida.

403 Forbidden numa rota de administração. POST /api/reindex e POST /api/cleanup só podem ser usados por administradores quando a gestão de utilizadores está ativa. Por isso, uma conta normal recebe uma recusa.

O consumo de memória aumenta durante uma importação. A deteção de idioma num 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 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 completo das páginas que visitou e dos ficheiros que guarda. Assim, 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 configurar corretamente a exposição do serviç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 completo do que leu é texto simples. 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 é uma operação única para preencher o histórico existente. Lê a base de dados de histórico do próprio navegador, pelo que é 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 início de sessão, porque extrai o conteúdo no navegador depois de a página ser renderizada. Uma configuração comum consiste em fazer uma importação e instalar depois a extensão.

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

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