Hospede o Meilisearch para busca rápida
Siga isso no seu próprio servidor. Comece grátis, sem cartão
Algolia e APIs de busca hospedadas parecidas cobram por volume de busca e por número de registros, o que soma rápido assim que um site tem tráfego real. O Meilisearch é um motor de busca open-source escrito em Rust que indexa busca instantânea e tolerante a erros de digitação sobre os seus próprios dados, e é leve o suficiente para rodar no servidor mais barato que um provedor de nuvem vende. No final deste guia, você vai ter ele rodando atrás de HTTPS com uma master key de verdade protegendo tudo, um snapshot do qual você consegue restaurar, e um caminho de upgrade curto.
O que você vai precisar
- Um servidor com Docker e o plugin Compose. Um Hetzner CX23 (2 vCPUs, 4 GB de RAM, 40 GB NVMe, €5,99/mês sem VAT) roda o Meilisearch com folga para um índice pequeno a médio.
- Um domínio ou subdomínio apontado para o endereço IP do servidor.
- Acesso SSH ao servidor.
- Seus dados prontos para indexar: o Meilisearch guarda documentos que você envia para ele, não rastreia nada por conta própria.
Etapa 1: Gere uma master key de verdade
O Meilisearch se recusa a iniciar em produção sem uma. MEILI_ENV=production exige uma chave de pelo menos 16 bytes, e sem ela (ou com uma menor), o servidor loga uma chave sugerida e encerra em vez de rodar desprotegido:
openssl rand -base64 48
Coloque o resultado num arquivo .env ao lado do seu arquivo compose, sem fazer commit no controle de versão:
MEILI_MASTER_KEY=paste-the-generated-value-here
chmod 600 .env
Etapa 2: Escreva o arquivo Docker Compose
services:
meilisearch:
image: getmeili/meilisearch:v1.55.0
restart: unless-stopped
environment:
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
MEILI_ENV: production
MEILI_NO_ANALYTICS: "true"
volumes:
- ./meili_data:/meili_data
expose:
- "7700"
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- meilisearch
volumes:
caddy_data:
caddy_config:
Este guia fixa a v1.55.0, a release estável atual no momento em que isso foi escrito. MEILI_ENV=production faz duas coisas: desativa a UI de playground de busca embutida na raiz (uma conveniência de desenvolvimento local que não tem motivo para estar acessível num servidor público), e é o que torna a master key obrigatória em vez de opcional. MEILI_NO_ANALYTICS=true retira a instância do envio de relatórios anônimos de uso do próprio Meilisearch. ./meili_data é um bind mount simples em vez de um volume nomeado especificamente para que um backup na Etapa 5 seja só copiar uma pasta, e é onde cada índice e log de tarefa de fato vive.
Confira se é interpretado corretamente:
docker compose config
Etapa 3: Aponte o DNS e adicione o Caddy
Crie um registro A para o seu subdomínio apontando para o IP do servidor, depois adicione um Caddyfile ao lado do compose.yml:
search.yourdomain.com {
reverse_proxy meilisearch:7700
}
Etapa 4: Inicie a stack e crie seu primeiro índice
docker compose up -d
docker compose ps
curl https://search.yourdomain.com/health
Você deve ver os dois serviços Up e o health check retornando {"status":"available"}. Crie um índice e adicione um documento para confirmar que a master key de fato funciona:
curl -X POST 'https://search.yourdomain.com/indexes' \
-H "Authorization: Bearer ${MEILI_MASTER_KEY}" \
-H 'Content-Type: application/json' \
--data-binary '{ "uid": "movies", "primaryKey": "id" }'
curl -X POST 'https://search.yourdomain.com/indexes/movies/documents' \
-H "Authorization: Bearer ${MEILI_MASTER_KEY}" \
-H 'Content-Type: application/json' \
--data-binary '[{ "id": 1, "title": "Carol" }]'
Você deve receber um taskUid de volta das duas chamadas. Confira se a tarefa terminou, e se uma busca de fato encontra o documento:
curl "https://search.yourdomain.com/indexes/movies/search?q=carol" \
-H "Authorization: Bearer ${MEILI_MASTER_KEY}"
Você deve ver "title": "Carol" no array hits. A partir daqui, sua aplicação deve gerar uma chave de API com escopo limitado, não master, por caso de uso (uma que só pode buscar, não gerenciar índices) através do endpoint /keys, em vez de enviar a própria master key para um navegador.
Etapa 5: Faça backup de /meili_data
O próprio endpoint /snapshots do Meilisearch (na verdade um dump agendado, não uma chamada de API de snapshot em tempo real) escreve um arquivo .snapshot dentro do container num intervalo que você configura, mas o backup mais simples e portável é um tarball do próprio volume enquanto o container não está escrevendo ativamente:
cat > /opt/meilisearch/backup.sh <<'EOF'
#!/bin/sh
cd /opt/meilisearch
docker compose stop meilisearch
tar czf backups/meili-$(date +%F).tar.gz meili_data
docker compose start meilisearch
find backups -name '*.tar.gz' -mtime +14 -delete
EOF
mkdir -p /opt/meilisearch/backups
chmod +x /opt/meilisearch/backup.sh
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/meilisearch/backup.sh") | crontab -
Rode uma vez à mão e confira que funcionou: ./backup.sh && ls -lh backups. Você deve ver um arquivo .tar.gz com a data de hoje. A parada e o início breves mantêm o arquivo internamente consistente; para um índice de busca voltado ao público, alguns segundos de indisponibilidade às 3h é uma troca razoável por um backup em que você de fato pode confiar. Copie o arquivo para fora do servidor também, para que perder a máquina não signifique também perder o índice.
Etapa 6: Faça upgrade
docker compose pull meilisearch
docker compose up -d meilisearch
O Meilisearch migra o próprio formato de dados em disco automaticamente na inicialização quando consegue, mas as release notes do projeto indicam saltos de versão que exigem reindexação via dump-and-import em vez de um upgrade in-place; leia o changelog da versão para a qual você está migrando antes de um salto de várias versões, principalmente através de uma fronteira de versão maior.
O caminho curto: faça com o Railyard
O Railyard oferece o Meilisearch como um template de aplicação de um clique (meilisearch no catálogo de templates), construído a partir da imagem oficial getmeili/meilisearch com MEILI_NO_ANALYTICS já definido e um volume de dados persistente ligado. Faça o deploy direto: app.railyard.run/deploy?template=meilisearch. Uma diferença real em relação ao caminho manual acima: o template hoje acompanha a tag flutuante latest em vez de uma versão fixa, então onde este guia faz você escolher e fazer upgrade de uma release específica por conta própria, o Railyard se move com o upstream automaticamente; defina MEILI_MASTER_KEY você mesmo como uma variável na página Settings do app de qualquer forma, ela não é gerada para você. Veja deploy with a button para entender como templates de um clique funcionam em geral, e databases and backups para como volumes persistentes são tratados na plataforma.
Solução de problemas
O container encerra imediatamente com uma mensagem sobre a master key. MEILI_ENV=production sem MEILI_MASTER_KEY definido, ou com uma de menos de 16 bytes, faz o Meilisearch se recusar a iniciar em vez de rodar aberto. Confira de novo se o arquivo .env da Etapa 1 realmente tem um valor real e se docker compose config mostra ele resolvido, não uma string vazia.
401 Unauthorized em toda chamada de API. O cabeçalho Authorization: Bearer <key> está faltando, ou você está passando a chave errada, lembre que a master key pode fazer tudo, incluindo gerar outras chaves, mas toda requisição ainda precisa dela (ou de uma chave com escopo) no cabeçalho; não existe caminho não autenticado depois que uma master key é definida.
O HTTPS não é emitido. Confira docker compose logs caddy em busca do erro de ACME; quase sempre é o registro de DNS da Etapa 3 ainda não apontando para este servidor, confirme com dig +short search.yourdomain.com.
Os resultados de busca não incluem um documento que você acabou de adicionar. A indexação é assíncrona; toda escrita retorna um taskUid, e o documento não fica buscável até aquela tarefa terminar. Consulte /tasks/{taskUid} se precisar confirmar a conclusão de forma programática em vez de adivinhar com um atraso fixo.
Falta de memória num servidor pequeno com um índice grande. O Meilisearch mantém uma quantidade significativa de dados do índice em memória para velocidade de consulta; os 4 GB de um CX23 estão bons para um catálogo modesto, mas um índice com milhões de documentos quer o CX33 (8 GB) ou maior em vez de swap, já que a latência de busca (não só a estabilidade) sofre assim que entra em swap.
Perguntas frequentes
O Meilisearch substitui o Elasticsearch? Para a maioria dos casos de busca de aplicação (um catálogo de e-commerce, um site de documentação, busca dentro do app), sim, e com muito menos esforço operacional; o Elasticsearch ainda ganha para agregação de logs e cargas de análise complexa para as quais o Meilisearch nunca foi feito.
Várias aplicações podem compartilhar uma instância do Meilisearch? Sim, os índices têm namespace por uid dentro da mesma instância, e chaves de API com escopo podem restringir uma chave a índices específicos, então uma instância atende com segurança mais de uma aplicação.
Eu também preciso de um banco de dados separado? Não, o Meilisearch é o sistema de registro para o que você indexar nele, embora a maioria das configurações o trate como um índice de busca derivado, mantido sincronizado com um banco de dados principal, em vez da única cópia dos dados.
Quão grande um índice pode ficar num CX23? Não há um limite rígido no próprio Meilisearch; o teto prático é RAM e disco no servidor, algumas centenas de milhares de documentos de tamanho típico cabem confortavelmente em 4 GB, bem além disso é onde redimensionar para cima realmente ajuda.
A API REST é a única forma de entrada? Não, existem SDKs oficiais para JavaScript, Python, PHP, Ruby, Go, Rust e mais, todos chamando a mesma API REST que este guia usa diretamente com curl.
Depois que a master key, o HTTPS e um backup estiverem no lugar, o Meilisearch basicamente se mantém por conta própria. As duas coisas que vale revisitar depois são uma chave com escopo por aplicação em vez da master key em todo lugar, e a agenda de backup da Etapa 5 depois que o índice se tornar algo que você de fato sentiria falta.
Por que escolhem o Railyard para isso
- Sua própria conta de cloud. Faça deploy no DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou em qualquer servidor Linux via SSH, cobrado direto pelo seu provedor, sem markup.
- Um preço fixo por equipe. O Free é grátis para sempre: um servidor mais um servidor de banco de dados, três apps, sem cartão. O Pro custa US$19 por mês para até cinco servidores e apps ilimitados. O Team custa US$49 por mês com servidores ilimitados. Sem cobrança por app, por deploy, por assento ou por gigabyte.
- Templates de um clique. Faça deploy de apps open source, como bancos de dados, analytics e ferramentas de dev, no seu próprio servidor em um clique.
- Bancos de dados gerenciados. Postgres, MySQL e Redis com backups programados, verificados por restauração, e recuperação point-in-time.
- Push-to-deploy. Faça deploy a partir do GitHub, GitLab ou da CLI, com HTTPS automático e releases sem downtime.