--- title: "Cómo montar un registro centralizado con ELK en Ubuntu 24.04" description: "Instala Elasticsearch, Logstash, Kibana y Filebeat 9 en Ubuntu 24.04, procesa los logs de Nginx con grok y consúltalos en Kibana con seguridad TLS activada." category: "Stack de Observabilidad" language: es source: https://cubepath.com/es/docs/stack-de-observabilidad/registro-centralizado-guia-completa-de-elk-stack updated: 2026-09-25 --- # Cómo montar un registro centralizado con ELK en Ubuntu 24.04 ELK Stack es la combinación de Elasticsearch (almacenamiento y búsqueda), Logstash (procesamiento) y Kibana (visualización), a la que se suma Filebeat como agente ligero que recoge los logs en cada servidor. En este tutorial montarás las cuatro piezas de la versión 9 en un único servidor Ubuntu 24.04, enviarás los logs de acceso de Nginx a través de Logstash, los separarás en campos con grok y los consultarás en Kibana. La seguridad (TLS y autenticación) que Elasticsearch activa por defecto se mantiene en todo momento. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 4 GB de RAM (8 GB recomendados), 2 vCPU y 40 GB de disco libres. Elasticsearch y Logstash son procesos Java y no funcionan bien con menos memoria. - Un usuario no root con privilegios `sudo`. - Acceso SSH desde tu equipo local, que usarás para abrir un túnel hacia Kibana. El flujo que vas a construir es: Nginx escribe `/var/log/nginx/access.log`, Filebeat lo lee y lo envía a Logstash por el puerto 5044, Logstash lo analiza y lo indexa en Elasticsearch (puerto 9200, solo en localhost) y Kibana (puerto 5601, solo en localhost) lo muestra. ## Paso 1: Añadir el repositorio de Elastic Los cuatro componentes se distribuyen desde el mismo repositorio APT oficial de Elastic. Descarga su clave GPG 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/elastic.gpg ``` Añade el repositorio de la rama 9.x firmado con esa clave: ```bash echo "deb [signed-by=/etc/apt/keyrings/elastic.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 de paquetes y comprueba que APT ve la versión de Elastic: ```bash sudo apt update apt-cache policy elasticsearch ``` ```output elasticsearch: Installed: (none) Candidate: 9.x.y Version table: 9.x.y 500 500 https://artifacts.elastic.co/packages/9.x/apt stable/main amd64 Packages ``` ## Paso 2: Instalar y arrancar Elasticsearch Instala Elasticsearch. Durante la instalación se genera la configuración de seguridad: certificados TLS en `/etc/elasticsearch/certs/` y una contraseña para el superusuario `elastic`: ```bash sudo apt install elasticsearch ``` Busca en la salida el bloque de seguridad y guarda la contraseña en un lugar seguro: ```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 : xxxxxxxxxxxxxxxxxxxx ... ``` > Nota: si la has perdido, genera una nueva con `sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic` una vez que el servicio esté arrancado. Elasticsearch calcula el tamaño del heap de Java según la RAM disponible. En un servidor que comparte memoria con Logstash y Kibana conviene fijarlo. Crea un archivo de opciones: ```bash sudo nano /etc/elasticsearch/jvm.options.d/heap.options ``` Para un servidor de 8 GB, 2 GB de heap es un punto de partida razonable (usa `1g` con 4 GB de RAM): ```text -Xms2g -Xmx2g ``` Por defecto Elasticsearch solo escucha en `localhost`, que es lo que quieres en una instalación de un solo nodo. Habilita e inicia el servicio: ```bash sudo systemctl enable --now elasticsearch ``` El arranque tarda unos segundos. Comprueba que responde por HTTPS usando la CA generada y la contraseña de `elastic`: ```bash sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200 ``` ```output { "name" : "your_hostname", "cluster_name" : "elasticsearch", "version" : { "number" : "9.x.y", ... }, "tagline" : "You Know, for Search" } ``` ## Paso 3: Instalar y enlazar Kibana Instala Kibana: ```bash sudo apt install kibana ``` Kibana se conecta a Elasticsearch mediante un token de inscripción, que configura automáticamente la URL, la CA y las credenciales internas. Genera el token: ```bash sudo /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana ``` Pásalo a Kibana (el token caduca a los 30 minutos): ```bash sudo /usr/share/kibana/bin/kibana-setup --enrollment-token ``` ```output ✔ Kibana configured successfully. To start Kibana run: bin/kibana ``` Habilita e inicia Kibana como servicio: ```bash sudo systemctl enable --now kibana ``` Kibana escucha en `localhost:5601`, así que no queda expuesto a internet. Comprueba su estado tras un minuto: ```bash sudo systemctl status kibana --no-pager ``` ```output ● kibana.service - Kibana Loaded: loaded (/usr/lib/systemd/system/kibana.service; enabled; preset: enabled) Active: active (running) since ... ``` ## Paso 4: Crear un usuario de escritura para Logstash Logstash no debe usar el superusuario `elastic`. Crea un rol que solo pueda escribir en los índices `nginx-*` y un usuario asociado. Primero, el rol: ```bash sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic \ -X POST "https://localhost:9200/_security/role/logstash_writer" \ -H "Content-Type: application/json" -d ' { "cluster": ["monitor", "manage_index_templates", "manage_ilm"], "indices": [ { "names": ["nginx-*"], "privileges": ["write", "create", "create_index", "manage", "manage_ilm"] } ] }' ``` ```output {"role":{"created":true}} ``` Después el usuario. Sustituye `your_strong_password` por una contraseña larga y aleatoria: ```bash sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic \ -X POST "https://localhost:9200/_security/user/logstash_internal" \ -H "Content-Type: application/json" -d ' { "password": "your_strong_password", "roles": ["logstash_writer"], "full_name": "Logstash internal user" }' ``` ```output {"created":true} ``` ## Paso 5: Instalar y configurar Logstash Instala Logstash: ```bash sudo apt install logstash ``` Logstash necesita la CA de Elasticsearch para validar su certificado. Cópiala a un directorio propio con permisos de lectura para el usuario `logstash`: ```bash sudo mkdir -p /etc/logstash/certs sudo cp /etc/elasticsearch/certs/http_ca.crt /etc/logstash/certs/ sudo chown -R root:logstash /etc/logstash/certs sudo chmod 640 /etc/logstash/certs/http_ca.crt ``` Si el servidor tiene 4 GB de RAM, reduce el heap de Logstash (1 GB por defecto) editando `/etc/logstash/jvm.options` y cambiando `-Xms1g` y `-Xmx1g` por `-Xms512m` y `-Xmx512m`. Con 8 GB puedes dejarlo como está. Crea el pipeline. Cada archivo de `/etc/logstash/conf.d/` terminado en `.conf` se carga en el pipeline principal: ```bash sudo nano /etc/logstash/conf.d/nginx.conf ``` La entrada `beats` recibe los eventos de Filebeat, el filtro `grok` separa la línea de log de Nginx (formato `combined`) en campos, `date` usa la fecha de la petición como `@timestamp` y la salida escribe un índice diario: ```ruby input { beats { port => 5044 } } filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } date { match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"] remove_field => ["timestamp"] } } output { elasticsearch { hosts => ["https://localhost:9200"] user => "logstash_internal" password => "your_strong_password" ssl_certificate_authorities => ["/etc/logstash/certs/http_ca.crt"] index => "nginx-%{+YYYY.MM.dd}" } } ``` El archivo contiene una contraseña, así que restringe su lectura: ```bash sudo chown root:logstash /etc/logstash/conf.d/nginx.conf sudo chmod 640 /etc/logstash/conf.d/nginx.conf ``` Valida la sintaxis antes de arrancar el servicio (tarda unos 30 segundos): ```bash sudo -u logstash /usr/share/logstash/bin/logstash --path.settings /etc/logstash -t ``` ```output ... Configuration OK [INFO ][logstash.runner] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash ``` Habilita e inicia Logstash y comprueba que el puerto 5044 queda a la escucha: ```bash sudo systemctl enable --now logstash sudo ss -tlnp | grep 5044 ``` ```output LISTEN 0 4096 *:5044 *:* users:(("java",pid=12345,fd=120)) ``` ## Paso 6: Instalar Nginx y Filebeat Para tener una fuente de logs real, instala Nginx y genera algunas peticiones: ```bash sudo apt install nginx for i in $(seq 1 20); do curl -s -o /dev/null http://localhost/; done curl -s -o /dev/null http://localhost/no-existe ``` Instala Filebeat desde el mismo repositorio: ```bash sudo apt install filebeat ``` El `filebeat.yml` de ejemplo trae una salida hacia Elasticsearch activada. Guarda una copia y sustitúyelo por una configuración mínima: ```bash sudo mv /etc/filebeat/filebeat.yml /etc/filebeat/filebeat.yml.orig sudo nano /etc/filebeat/filebeat.yml ``` La entrada `filestream` necesita un `id` único y lee el log de acceso de Nginx. La salida apunta a Logstash: ```yaml filebeat.inputs: - type: filestream id: nginx-access paths: - /var/log/nginx/access.log output.logstash: hosts: ["localhost:5044"] ``` Filebeat se niega a arrancar si su configuración es escribible por otros usuarios, así que ajusta los permisos y prueba la configuración y la conexión: ```bash sudo chmod 600 /etc/filebeat/filebeat.yml sudo filebeat test config sudo filebeat test output ``` ```output Config OK logstash: localhost:5044... connection... parse host... OK dns lookup... OK addresses: 127.0.0.1 dial up... OK TLS... WARN secure connection disabled talk to server... OK ``` Habilita e inicia Filebeat: ```bash sudo systemctl enable --now filebeat ``` ## Paso 7: Comprobar que los datos llegan a Elasticsearch Tras unos segundos debe existir el índice del día con documentos: ```bash sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic "https://localhost:9200/_cat/indices/nginx-*?v" ``` ```output health status index uuid pri rep docs.count ... yellow open nginx-2026.09.25 aBcD1234EfGh5678IjKl 1 1 21 ... ``` El estado `yellow` es normal en un clúster de un solo nodo: las réplicas no tienen otro nodo donde asignarse. Consulta un documento para ver los campos que ha generado grok: ```bash sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic "https://localhost:9200/nginx-*/_search?size=1&pretty&q=http.response.status_code:404" ``` Deberías ver campos como `source.address`, `http.request.method`, `url.original`, `http.response.status_code` y `user_agent.original`. Logstash 9 aplica nombres ECS (Elastic Common Schema) por defecto. Si el documento tiene la etiqueta `_grokparsefailure`, la línea no coincide con el formato `combined`; revisa si has cambiado `log_format` en Nginx. ## Paso 8: Consultar los logs en Kibana Kibana solo escucha en localhost, así que accede mediante un túnel SSH desde tu equipo local: ```bash ssh -L 5601:localhost:5601 your_user@your_server_ip ``` Con la sesión abierta, visita `http://localhost:5601` en tu navegador e inicia sesión con el usuario `elastic` y su contraseña. Crea una vista de datos (data view) para los índices de Nginx: 1. Abre el menú principal y ve a **Stack Management > Data Views**. 2. Pulsa **Create data view**. 3. En **Index pattern** escribe `nginx-*` y elige `@timestamp` como campo de tiempo. 4. Pulsa **Save data view to Kibana**. Ve a **Discover**, selecciona la vista `nginx-*` y verás las peticiones. Puedes filtrar con KQL, por ejemplo: ```text http.response.status_code >= 400 ``` Desde **Visualize Library** o **Dashboards** puedes crear un gráfico de barras de peticiones por código de estado o una tabla de las URL más solicitadas usando esos mismos campos. ## Enviar logs desde otros servidores Para recoger logs de más servidores, instala Filebeat en cada uno (pasos 1 y 6, sin Nginx si no lo necesitas) y cambia la salida a la IP del servidor ELK: ```yaml output.logstash: hosts: ["your_server_ip:5044"] ``` En el servidor ELK abre el puerto 5044 solo para esas IP: ```bash sudo ufw allow from your_client_ip to any port 5044 proto tcp ``` > Importante: la entrada `beats` de este tutorial no cifra el tráfico. Si los servidores se comunican por internet y no por una red privada, configura TLS en la entrada `beats` de Logstash y en `output.logstash` de Filebeat antes de enviar logs sensibles. ## Solución de problemas - **Elasticsearch no arranca**: revisa `sudo journalctl -u elasticsearch -n 50` y `/var/log/elasticsearch/elasticsearch.log`. La causa más habitual es falta de memoria; reduce el heap del paso 2. - **Logstash no escribe**: `sudo journalctl -u logstash -n 50`. Un error `401` indica credenciales incorrectas del usuario `logstash_internal`; un error `403` indica que el índice no encaja con `nginx-*`. - **Filebeat no envía nada**: `sudo journalctl -u filebeat -n 50`. Si el log ya se había leído, Filebeat solo envía líneas nuevas; genera más peticiones a Nginx. - **Kibana muestra "Kibana server is not ready yet"**: espera un par de minutos tras arrancar y revisa `sudo journalctl -u kibana -n 50`. ## Conclusión Ya tienes un ELK Stack de un nodo con seguridad activada que recibe los logs de Nginx a través de Filebeat y Logstash, los estructura con grok y los muestra en Kibana. Como siguientes pasos, define una política de ciclo de vida (ILM) en **Stack Management > Index Lifecycle Policies** para borrar índices antiguos, publica Kibana detrás de Nginx con HTTPS en lugar del túnel SSH y añade más entradas a Filebeat para los logs de tus aplicaciones.