--- title: "Cómo instalar Elasticsearch 9 en Ubuntu 24.04" description: "Instala Elasticsearch 9 desde el repositorio oficial de Elastic en Ubuntu 24.04, con seguridad y TLS activados, un usuario para tu app y tus primeras búsquedas." category: "Despliegue de Aplicaciones" language: es source: https://cubepath.com/es/docs/despliegue-de-aplicaciones/instalacion-de-elasticsearch updated: 2026-09-25 --- # Cómo instalar Elasticsearch 9 en Ubuntu 24.04 Elasticsearch es un motor de búsqueda y análisis distribuido, basado en Apache Lucene, que indexa documentos JSON y permite hacer búsquedas de texto completo y agregaciones sobre millones de registros en milisegundos. En este tutorial instalarás Elasticsearch 9 en un único nodo con Ubuntu 24.04 desde el repositorio oficial de Elastic, con la seguridad (autenticación y TLS) que el paquete configura automáticamente. Después crearás un índice, harás búsquedas y darás de alta un usuario con permisos limitados para tu aplicación. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS de 64 bits, por ejemplo un VPS de CubePath. - Al menos 4 GB de RAM y 2 vCPU. Elasticsearch reserva por defecto la mitad de la RAM para la JVM; con menos memoria funciona para pruebas, pero no para producción. - Espacio en disco para tus datos más un margen del 20 %: Elasticsearch deja de asignar datos cuando el disco supera el 85 % de ocupación. - Un usuario no root con privilegios `sudo`. - UFW activo permitiendo SSH (`sudo ufw allow OpenSSH` y `sudo ufw enable`). No necesitas instalar Java: el paquete incluye su propio JDK. ## Paso 1: Añadir el repositorio oficial de Elastic Instala las herramientas para descargar y convertir la clave del repositorio: ```bash sudo apt update sudo apt install curl gnupg apt-transport-https ``` Descarga la clave GPG de Elastic en `/etc/apt/keyrings`: ```bash sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /etc/apt/keyrings/elasticsearch.gpg ``` Añade el repositorio de la rama 9.x firmado con esa clave: ```bash echo "deb [signed-by=/etc/apt/keyrings/elasticsearch.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-9.x.list ``` Actualiza el índice y comprueba que el paquete viene de `artifacts.elastic.co`: ```bash sudo apt update apt-cache policy elasticsearch ``` ```output elasticsearch: Installed: (none) Candidate: 9.1.4 Version table: 9.1.4 500 500 https://artifacts.elastic.co/packages/9.x/apt stable/main amd64 Packages ``` La versión que veas será la última publicada de la rama 9. ## Paso 2: Instalar Elasticsearch y guardar la contraseña de elastic Instala el paquete: ```bash sudo apt install elasticsearch ``` Durante la instalación el paquete activa la seguridad automáticamente: genera certificados TLS para la API HTTP y para la comunicación entre nodos, y crea una contraseña para el superusuario `elastic`. Busca este bloque en la salida: ```output --------------------------- Security autoconfiguration information ------------------------------ Authentication and authorization are enabled. TLS for the transport and HTTP layers is enabled and configured. The generated password for the elastic built-in superuser is : your_elastic_password ``` > Importante: copia esa contraseña a tu gestor de contraseñas ahora; no se vuelve a mostrar. Si la pierdes, puedes generar otra con el comando del paso 4. ## Paso 3: Configurar el nodo La configuración principal está en `/etc/elasticsearch/elasticsearch.yml`. Cambia el nombre del clúster y del nodo antes del primer arranque, porque el nombre del clúster queda asociado a los datos: ```bash sudo nano /etc/elasticsearch/elasticsearch.yml ``` Descomenta y ajusta estas líneas al principio del archivo: ```yaml cluster.name: mi-cluster node.name: es01 ``` No toques el bloque que empieza por `BEGIN SECURITY AUTO CONFIGURATION` al final del archivo: contiene las rutas de los certificados, `cluster.initial_master_nodes` con el nombre de tu servidor y `http.host: 0.0.0.0`. Esta última línea hace que la API escuche en todas las interfaces; el acceso lo controlarás con el cortafuegos en el paso 7. Los datos se guardan en `/var/lib/elasticsearch` y los logs en `/var/log/elasticsearch`. Si quieres los datos en otro disco, cambia `path.data` en este mismo archivo. ### Fijar el tamaño del heap (opcional) Elasticsearch calcula el heap de la JVM según la RAM del servidor, lo cual es adecuado si el servidor solo ejecuta Elasticsearch. Si comparte máquina con otros servicios, fíjalo tú. Crea un archivo en `jvm.options.d` (no edites `jvm.options` directamente): ```bash sudo nano /etc/elasticsearch/jvm.options.d/heap.options ``` ```text -Xms2g -Xmx2g ``` Usa el mismo valor en ambas líneas, como máximo la mitad de la RAM y nunca por encima de 31 GB. ## Paso 4: Arrancar Elasticsearch El paquete no arranca el servicio automáticamente. Recarga systemd, habilita el servicio y arráncalo: ```bash sudo systemctl daemon-reload sudo systemctl enable --now elasticsearch ``` El arranque tarda entre 20 y 60 segundos. Comprueba el estado: ```bash sudo systemctl status elasticsearch --no-pager ``` ```output ● elasticsearch.service - Elasticsearch Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; preset: enabled) Active: active (running) since Thu 2026-09-25 10:31:07 UTC; 25s ago ``` Si no guardaste la contraseña de `elastic` en el paso 2, genera una nueva con el servicio en marcha: ```bash sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic ``` ## Paso 5: Comprobar el acceso por HTTPS La API solo acepta HTTPS con el certificado que firmó la CA generada en la instalación. Copia el certificado de la CA a tu directorio personal para usarlo con `curl` sin `sudo` (es un certificado público, no una clave): ```bash sudo cp /etc/elasticsearch/certs/http_ca.crt ~/http_ca.crt sudo chown "$USER": ~/http_ca.crt ``` Carga la contraseña de `elastic` en una variable sin que quede en el historial; `read -rs` la pide sin mostrarla: ```bash read -rs ELASTIC_PASSWORD && export ELASTIC_PASSWORD ``` Haz una petición a la raíz de la API: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" https://localhost:9200 ``` ```output { "name" : "es01", "cluster_name" : "mi-cluster", "cluster_uuid" : "hR4Pz9xUQ3ivLr0nq0V8bA", "version" : { "number" : "9.1.4", ... }, "tagline" : "You Know, for Search" } ``` Comprueba la salud del clúster: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" "https://localhost:9200/_cluster/health?pretty" ``` ```output { "cluster_name" : "mi-cluster", "status" : "green", "number_of_nodes" : 1, "number_of_data_nodes" : 1, ... } ``` ## Paso 6: Crear un índice y buscar documentos Crea un índice `productos` con un mapeo explícito. Como solo hay un nodo, pon `number_of_replicas` a `0`: con el valor por defecto (1) la réplica no se podría asignar y el clúster quedaría en estado `yellow`: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" -X PUT "https://localhost:9200/productos?pretty" \ -H "Content-Type: application/json" -d ' { "settings": { "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "properties": { "nombre": { "type": "text" }, "categoria": { "type": "keyword" }, "precio": { "type": "float" } } } }' ``` ```output { "acknowledged" : true, "shards_acknowledged" : true, "index" : "productos" } ``` `text` se analiza para búsqueda de texto completo; `keyword` se guarda tal cual y sirve para filtros exactos y agregaciones. Indexa varios documentos de una vez con la API `_bulk`, que usa formato NDJSON (una línea de acción y otra de documento). `refresh=wait_for` espera a que los documentos sean visibles en las búsquedas: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" -X POST "https://localhost:9200/productos/_bulk?refresh=wait_for" \ -H "Content-Type: application/x-ndjson" --data-binary ' { "index": {} } { "nombre": "Portátil ligero de 14 pulgadas", "categoria": "portatiles", "precio": 899 } { "index": {} } { "nombre": "Portátil gaming de 16 pulgadas", "categoria": "portatiles", "precio": 1499 } { "index": {} } { "nombre": "Monitor de 27 pulgadas 4K", "categoria": "monitores", "precio": 349 } ' ``` La respuesta debe contener `"errors":false`. Busca los productos que contienen "portátil" con un precio máximo de 1000: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" "https://localhost:9200/productos/_search?pretty" \ -H "Content-Type: application/json" -d ' { "query": { "bool": { "must": { "match": { "nombre": "portátil" } }, "filter": { "range": { "precio": { "lte": 1000 } } } } } }' ``` ```output "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "hits" : [ { "_index" : "productos", "_score" : 0.5, "_source" : { "nombre" : "Portátil ligero de 14 pulgadas", "categoria" : "portatiles", "precio" : 899 } } ] } ``` Cuenta los productos y el precio medio por categoría con una agregación. `"size": 0` omite los documentos y devuelve solo el resultado agregado: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" "https://localhost:9200/productos/_search?pretty" \ -H "Content-Type: application/json" -d ' { "size": 0, "aggs": { "por_categoria": { "terms": { "field": "categoria" }, "aggs": { "precio_medio": { "avg": { "field": "precio" } } } } } }' ``` ```output "por_categoria" : { "buckets" : [ { "key" : "portatiles", "doc_count" : 2, "precio_medio" : { "value" : 1199.0 } }, { "key" : "monitores", "doc_count" : 1, "precio_medio" : { "value" : 349.0 } } ] } ``` ## Paso 7: Crear un usuario para tu aplicación y limitar el acceso El superusuario `elastic` es para administración; tu aplicación debe usar un usuario con permisos solo sobre sus índices. Crea un rol que permita leer y escribir en los índices que empiezan por `productos`: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" -X PUT "https://localhost:9200/_security/role/productos_rw?pretty" \ -H "Content-Type: application/json" -d ' { "indices": [ { "names": ["productos*"], "privileges": ["read", "write", "create_index", "view_index_metadata"] } ] }' ``` Crea el usuario `app_productos` con ese rol. Sustituye `your_app_password` por una contraseña larga, por ejemplo una generada con `openssl rand -base64 24`: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" -X POST "https://localhost:9200/_security/user/app_productos?pretty" \ -H "Content-Type: application/json" -d ' { "password": "your_app_password", "roles": ["productos_rw"] }' ``` ```output { "created" : true } ``` Comprueba que el nuevo usuario puede buscar en `productos` pero no consultar la configuración del clúster: ```bash curl --cacert ~/http_ca.crt -u "app_productos:your_app_password" "https://localhost:9200/productos/_count" curl --cacert ~/http_ca.crt -u "app_productos:your_app_password" "https://localhost:9200/_cluster/settings" ``` La primera petición devuelve `{"count":3,...}` y la segunda un error `security_exception` con estado 403. Por último, decide quién puede llegar al puerto 9200. Con UFW activo y sin reglas para ese puerto, la API solo es accesible desde el propio servidor. Si tu aplicación corre en otro servidor, permite únicamente su IP (sustituye `app_server_ip`), idealmente a través de una red privada: ```bash sudo ufw allow from app_server_ip to any port 9200 proto tcp sudo ufw status ``` No abras el puerto 9300: es el de comunicación entre nodos y en un nodo único no se usa desde fuera. ## Solución de problemas **El servicio no arranca o se detiene al poco.** Consulta el journal y el log del clúster, que se llama como `cluster.name`: ```bash sudo journalctl -u elasticsearch -n 50 --no-pager sudo tail -n 50 /var/log/elasticsearch/mi-cluster.log ``` Si el sistema lo mata por falta de memoria (`Out of memory: Killed process` en `sudo dmesg`), reduce el heap como en el paso 3 o amplía la RAM del servidor. **`curl: (52) Empty reply from server`.** Estás usando `http://` en lugar de `https://`. La API solo acepta TLS. **`curl: (60) SSL certificate problem`.** Falta `--cacert ~/http_ca.crt` o la ruta es incorrecta. No uses `-k` para saltarte la verificación salvo en una prueba puntual. **`security_exception` con estado 401.** Usuario o contraseña incorrectos. Comprueba que la variable `ELASTIC_PASSWORD` está cargada en la sesión actual o restablece la contraseña con `elasticsearch-reset-password`. **Los índices pasan a solo lectura (`index read-only / allow delete`).** El disco ha superado el 95 % de ocupación y Elasticsearch bloquea las escrituras para protegerse. Libera espacio o amplía el disco; el bloqueo se levanta automáticamente cuando la ocupación baja del umbral. Comprueba el uso por nodo con: ```bash curl --cacert ~/http_ca.crt -u "elastic:$ELASTIC_PASSWORD" "https://localhost:9200/_cat/allocation?v" ``` ## Conclusión Tienes Elasticsearch 9 funcionando en Ubuntu 24.04 con autenticación y TLS, un índice con mapeo explícito, búsquedas y agregaciones, y un usuario con permisos mínimos para tu aplicación. Como siguientes pasos puedes instalar Kibana y conectarlo con un token de inscripción (`elasticsearch-create-enrollment-token -s kibana`), configurar instantáneas periódicas con un repositorio de snapshots y usar el cliente oficial de Elasticsearch para tu lenguaje en lugar de `curl`.