--- title: "Cómo instalar y configurar Meilisearch en Ubuntu 24.04" description: "Instala Meilisearch en Ubuntu 24.04 como servicio systemd con clave maestra, indexa documentos, configura filtros y sinónimos y publícalo con Nginx y HTTPS." category: "Motores de Búsqueda" language: es source: https://cubepath.com/es/docs/motores-de-búsqueda/instalacion-y-configuracion-de-meilisearch updated: 2026-09-25 --- # Cómo instalar y configurar Meilisearch en Ubuntu 24.04 Meilisearch es un motor de búsqueda de código abierto escrito en Rust que ofrece resultados mientras el usuario escribe, tolerancia a errores tipográficos y una API REST muy sencilla. Funciona sin apenas configuración, pero en producción necesita una clave maestra, un usuario propio y un proxy con HTTPS delante. En este tutorial instalarás Meilisearch en Ubuntu 24.04 como servicio systemd, indexarás documentos, configurarás filtros, ordenación y sinónimos, crearás una clave de solo búsqueda y publicarás la API con Nginx y Let's Encrypt. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS de 64 bits (x86_64 o arm64), por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo`. - Al menos 1 GB de RAM. El espacio en disco que ocupa el índice suele ser varias veces el tamaño de los datos originales. - Para el paso 8: un dominio o subdominio (en esta guía, `search.your_domain`) con un registro DNS A apuntando a la IP del servidor. ## Paso 1: Instalar el binario de Meilisearch Meilisearch se distribuye como un único binario en las versiones publicadas en GitHub. Consulta la última versión estable en la [página de releases](https://github.com/meilisearch/meilisearch/releases) y descárgala; esta guía usa la 1.54.0: ```bash MEILI_VERSION=1.54.0 cd /tmp curl -fL -o meilisearch "https://github.com/meilisearch/meilisearch/releases/download/v${MEILI_VERSION}/meilisearch-linux-amd64" sudo install -m 0755 meilisearch /usr/local/bin/meilisearch ``` En servidores arm64, descarga `meilisearch-linux-aarch64` en lugar de `meilisearch-linux-amd64`. Comprueba la instalación: ```bash meilisearch --version ``` ```output meilisearch 1.54.0 ``` ## Paso 2: Crear el usuario, los directorios y la configuración Ejecuta Meilisearch con un usuario de sistema sin shell, propietario solo de sus datos: ```bash sudo useradd --system --home-dir /var/lib/meilisearch --shell /usr/sbin/nologin meilisearch sudo mkdir -p /var/lib/meilisearch/data /var/lib/meilisearch/dumps /var/lib/meilisearch/snapshots sudo chown -R meilisearch:meilisearch /var/lib/meilisearch sudo chmod 750 /var/lib/meilisearch ``` En modo producción, Meilisearch exige una clave maestra de al menos 16 bytes. Genera una aleatoria y guárdala en un lugar seguro: ```bash openssl rand -base64 32 ``` Crea el fichero de configuración: ```bash sudo nano /etc/meilisearch.toml ``` Pega el siguiente contenido y sustituye `your_master_key` por la clave que acabas de generar: ```toml env = "production" master_key = "your_master_key" http_addr = "127.0.0.1:7700" db_path = "/var/lib/meilisearch/data" dump_dir = "/var/lib/meilisearch/dumps" snapshot_dir = "/var/lib/meilisearch/snapshots" no_analytics = true ``` `http_addr` en `127.0.0.1` hace que Meilisearch solo acepte conexiones locales; Nginx lo publicará en el paso 8. `no_analytics` desactiva la telemetría. Como el fichero contiene la clave maestra, restringe sus permisos: ```bash sudo chown root:meilisearch /etc/meilisearch.toml sudo chmod 640 /etc/meilisearch.toml ``` ## Paso 3: Crear el servicio systemd Crea la unidad del servicio: ```bash sudo nano /etc/systemd/system/meilisearch.service ``` ```ini [Unit] Description=Meilisearch After=network-online.target Wants=network-online.target [Service] Type=simple User=meilisearch Group=meilisearch WorkingDirectory=/var/lib/meilisearch ExecStart=/usr/local/bin/meilisearch --config-file-path /etc/meilisearch.toml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target ``` Recarga systemd, habilita el servicio y arráncalo: ```bash sudo systemctl daemon-reload sudo systemctl enable --now meilisearch ``` Comprueba que está activo y que responde. El endpoint `/health` es el único que no necesita clave: ```bash systemctl status meilisearch --no-pager curl http://127.0.0.1:7700/health ``` ```output {"status":"available"} ``` Los logs del servicio se consultan con `journalctl`: ```bash sudo journalctl -u meilisearch -n 20 --no-pager ``` ## Paso 4: Obtener las claves de API La clave maestra solo debe usarse para gestionar claves. Al arrancar con clave maestra, Meilisearch crea dos claves por defecto: una de administración para el backend y otra de solo búsqueda. Guarda la clave maestra en una variable e instala `jq` para leer las respuestas: ```bash sudo apt install -y jq export MEILI_MASTER_KEY='your_master_key' ``` Lista las claves: ```bash curl -s http://127.0.0.1:7700/keys \ -H "Authorization: Bearer ${MEILI_MASTER_KEY}" \ | jq '.results[] | {name, key}' ``` ```output { "name": "Default Search API Key", "key": "d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4" } { "name": "Default Admin API Key", "key": "380689dd379232519a54d15935750cc7625620a2ea2fc06907cb40ba5b421b6f" } ``` Guarda la clave de administración en otra variable. La usarás para todas las operaciones siguientes: ```bash export MEILI_ADMIN_KEY=$(curl -s http://127.0.0.1:7700/keys \ -H "Authorization: Bearer ${MEILI_MASTER_KEY}" \ | jq -r '.results[] | select(.name == "Default Admin API Key") | .key') ``` ## Paso 5: Indexar documentos Meilisearch crea el índice automáticamente al recibir los primeros documentos. Cada documento necesita un identificador único; aquí se indica de forma explícita con `primaryKey=id`. Crea un fichero de ejemplo: ```bash nano ~/productos.json ``` ```json [ {"id": 1, "nombre": "Camiseta básica de algodón", "descripcion": "Camiseta unisex de algodón 100 %", "categoria": "Ropa", "precio": 19.99, "stock": 150}, {"id": 2, "nombre": "Zapatillas de running", "descripcion": "Zapatillas ligeras con amortiguación", "categoria": "Calzado", "precio": 89.99, "stock": 45}, {"id": 3, "nombre": "Pantalón vaquero slim", "descripcion": "Vaquero ajustado de corte moderno", "categoria": "Ropa", "precio": 49.99, "stock": 80}, {"id": 4, "nombre": "Zapatillas de montaña", "descripcion": "Calzado impermeable para trail", "categoria": "Calzado", "precio": 119.00, "stock": 20} ] ``` Envía los documentos al índice `productos`: ```bash curl -s -X POST "http://127.0.0.1:7700/indexes/productos/documents?primaryKey=id" \ -H "Authorization: Bearer ${MEILI_ADMIN_KEY}" \ -H "Content-Type: application/json" \ --data-binary @"$HOME/productos.json" | jq ``` ```output { "taskUid": 0, "indexUid": "productos", "status": "enqueued", "type": "documentAdditionOrUpdate", "enqueuedAt": "2026-09-25T10:12:31.123456Z" } ``` Las escrituras en Meilisearch son asíncronas: la respuesta solo confirma que la tarea está en cola. Comprueba su resultado con el `taskUid` devuelto: ```bash curl -s http://127.0.0.1:7700/tasks/0 \ -H "Authorization: Bearer ${MEILI_ADMIN_KEY}" | jq '.status, .details' ``` ```output "succeeded" { "receivedDocuments": 4, "indexedDocuments": 4 } ``` Si el estado es `failed`, el campo `error` de la tarea explica el motivo. Para modificar solo algunos campos de documentos existentes, envíalos con `PUT` al mismo endpoint en lugar de `POST`; los campos que no incluyas se conservan. ## Paso 6: Configurar filtros, ordenación y sinónimos Por defecto, todos los campos son buscables, pero ninguno se puede usar para filtrar u ordenar. Declara qué campos cumplen cada función y añade sinónimos propios de tu catálogo. El orden de `searchableAttributes` también define la relevancia: una coincidencia en `nombre` pesa más que en `descripcion`: ```bash curl -s -X PATCH http://127.0.0.1:7700/indexes/productos/settings \ -H "Authorization: Bearer ${MEILI_ADMIN_KEY}" \ -H "Content-Type: application/json" \ -d '{ "searchableAttributes": ["nombre", "descripcion", "categoria"], "filterableAttributes": ["categoria", "precio"], "sortableAttributes": ["precio", "stock"], "synonyms": { "zapatillas": ["deportivas", "tenis"], "deportivas": ["zapatillas"], "tenis": ["zapatillas"] } }' | jq '.taskUid' ``` Cambiar los ajustes reindexa los documentos, así que también es una tarea asíncrona. Con pocos documentos termina en un instante; puedes comprobarlo con `/tasks/` como antes. Ahora prueba una búsqueda por un sinónimo, combinada con un filtro, un orden y facetas: ```bash curl -s -X POST http://127.0.0.1:7700/indexes/productos/search \ -H "Authorization: Bearer ${MEILI_ADMIN_KEY}" \ -H "Content-Type: application/json" \ -d '{ "q": "deportivas", "filter": "precio < 100", "sort": ["precio:asc"], "facets": ["categoria"] }' | jq '[.hits[] | {nombre, precio}], .facetDistribution' ``` ```output [ { "nombre": "Zapatillas de running", "precio": 89.99 } ] { "categoria": { "Calzado": 1 } } ``` Ningún documento contiene la palabra `deportivas`, pero el sinónimo la relaciona con `zapatillas`, y el filtro descarta las zapatillas de montaña por precio. Prueba también a buscar `zapatilas`: la tolerancia a errores tipográficos devuelve las mismas zapatillas sin configurar nada. `facetDistribution` devuelve los conteos por categoría, que puedes usar para construir filtros en la interfaz. ## Paso 7: Crear una clave de solo búsqueda La clave de búsqueda por defecto sirve para todos los índices. Para un frontend público es mejor una clave limitada a un índice concreto: ```bash curl -s -X POST http://127.0.0.1:7700/keys \ -H "Authorization: Bearer ${MEILI_MASTER_KEY}" \ -H "Content-Type: application/json" \ -d '{ "name": "Frontend productos", "description": "Búsqueda pública en el índice productos", "actions": ["search"], "indexes": ["productos"], "expiresAt": null }' | jq -r '.key' ``` El comando imprime la clave nueva. Comprueba que puede buscar pero no leer los ajustes del índice, sustituyendo `your_search_key` por su valor: ```bash curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:7700/indexes/productos/settings \ -H "Authorization: Bearer your_search_key" ``` ```output 403 ``` ## Paso 8: Publicar la API con Nginx y HTTPS Instala Nginx y Certbot: ```bash sudo apt install -y nginx certbot python3-certbot-nginx ``` Crea un sitio para el subdominio de búsqueda. `client_max_body_size` permite enviar lotes de documentos grandes a través del proxy; el límite por defecto de Nginx es de solo 1 MB: ```bash sudo nano /etc/nginx/sites-available/meilisearch ``` ```nginx server { listen 80; server_name search.your_domain; client_max_body_size 100M; location / { proxy_pass http://127.0.0.1:7700; 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; } } ``` Actívalo, comprueba la sintaxis y recarga Nginx: ```bash sudo ln -s /etc/nginx/sites-available/meilisearch /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` Si usas UFW, permite HTTP y HTTPS (y SSH, antes de activarlo): ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw enable ``` Obtén el certificado de Let's Encrypt: ```bash sudo certbot --nginx -d search.your_domain ``` Comprueba el acceso desde fuera del servidor: ```bash curl https://search.your_domain/health ``` ```output {"status":"available"} ``` No hace falta bloquear rutas de administración en Nginx: sin una clave válida, Meilisearch rechaza cualquier petición distinta de `/health`. ## Paso 9: Hacer copias de seguridad con dumps Un dump exporta documentos, ajustes y claves en un formato que se puede importar en la misma versión o en una posterior de Meilisearch, lo que lo hace útil tanto para copias de seguridad como para actualizar de versión. Lanza uno: ```bash curl -s -X POST http://127.0.0.1:7700/dumps \ -H "Authorization: Bearer ${MEILI_ADMIN_KEY}" | jq '.taskUid' ``` Cuando la tarea termine, el fichero aparecerá en el directorio configurado: ```bash sudo ls /var/lib/meilisearch/dumps/ ``` ```output 20260925-101845123.dump ``` Copia esos ficheros fuera del servidor con tu sistema de backups habitual. Para restaurar un dump, arranca Meilisearch con una base de datos vacía y la opción `--import-dump /ruta/al/fichero.dump`. ## Solución de problemas **El servicio no arranca.** Revisa el journal: ```bash sudo journalctl -u meilisearch -n 50 --no-pager ``` Si el error indica que la clave maestra es demasiado corta, genera otra de al menos 16 bytes. Si indica problemas de permisos en `/var/lib/meilisearch`, vuelve a ejecutar el `chown` del paso 2. **`The provided API key is invalid` o `missing_authorization_header`.** La cabecera debe ser `Authorization: Bearer `. Comprueba que la variable no está vacía en la sesión actual con `echo "$MEILI_ADMIN_KEY"`. **`Attribute precio is not filterable`.** El campo no está en `filterableAttributes`, o la tarea de ajustes del paso 6 aún no ha terminado o ha fallado. Consulta sus ajustes con `GET /indexes/productos/settings`. **Una importación grande devuelve `413 Request Entity Too Large`.** Si pasa por Nginx, sube `client_max_body_size`. Si viene de Meilisearch, el límite propio es de 100 MB por petición: divide el fichero en lotes más pequeños. ## Conclusión Tienes Meilisearch funcionando en Ubuntu 24.04 como servicio systemd protegido con clave maestra, con un índice configurado para filtrar, ordenar y entender sinónimos, una clave pública limitada y la API publicada con HTTPS. Como siguientes pasos, conecta tu frontend con el cliente oficial `meilisearch` de JavaScript o con InstantSearch, programa dumps periódicos con un temporizador de systemd y ajusta las reglas de relevancia (`rankingRules`) cuando tengas datos reales.