Filebeat es el agente ligero de Elastic que lee archivos de log en el servidor y los envía a Elasticsearch o Logstash, recordando hasta dónde ha leído cada archivo para no perder ni duplicar eventos. En este tutorial instalarás Filebeat en Ubuntu 24.04, lo conectarás por HTTPS a un clúster de Elasticsearch con un usuario de permisos mínimos, activarás el módulo de Nginx y añadirás un input propio para los logs JSON y multilínea de una aplicación. Al terminar verás los eventos en Kibana.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con un usuario no root con privilegios sudo.
  • Un clúster de Elasticsearch y Kibana en funcionamiento y accesible desde el servidor (por defecto Elasticsearch escucha en el puerto 9200 y Kibana en el 5601).
  • La contraseña del usuario elastic (o de otro superusuario) para la configuración inicial, y el certificado de la CA del clúster si usa certificados autofirmados (en una instalación estándar está en /etc/elasticsearch/certs/http_ca.crt del nodo de Elasticsearch).
  • Nginx instalado en el servidor si quieres seguir el paso del módulo de Nginx.

En los ejemplos se usan estos valores de ejemplo, que debes sustituir por los tuyos: your_es_host (nombre o IP de Elasticsearch) y your_kibana_host (nombre o IP de Kibana).

Paso 1: Instalar Filebeat desde el repositorio de Elastic

Importa la clave con la que Elastic firma sus paquetes y guárdala en /etc/apt/keyrings:

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, firmado con esa clave:

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

Instala el paquete:

sudo apt update
sudo apt install filebeat

Comprueba la versión instalada:

filebeat version
filebeat version 9.1.4 (amd64), libbeat 9.1.4 [...]

Todavía no arranques el servicio: primero hay que configurar la salida.

Paso 2: Crear un usuario de publicación en Elasticsearch

Filebeat solo necesita escribir en sus propios índices, así que no uses el superusuario elastic para el día a día. Crea un rol con los permisos que Elastic documenta para publicar eventos y un usuario con ese rol. Ejecuta estos comandos desde el servidor de Filebeat (curl pedirá la contraseña de elastic).

Crea un directorio para el certificado de la CA del clúster:

sudo install -d -m 0755 /etc/filebeat/certs

Copia en él el archivo http_ca.crt desde el nodo de Elasticsearch (por ejemplo con scp) y comprueba que está en su sitio:

ls -l /etc/filebeat/certs/http_ca.crt

Crea el rol filebeat_writer:

curl --cacert /etc/filebeat/certs/http_ca.crt -u elastic -X POST \
  "https://your_es_host:9200/_security/role/filebeat_writer" \
  -H "Content-Type: application/json" -d '{
  "cluster": ["monitor", "read_ilm", "read_pipeline"],
  "indices": [
    {
      "names": ["filebeat-*"],
      "privileges": ["create_doc", "view_index_metadata", "auto_configure"]
    }
  ]
}'

Crea el usuario filebeat_internal con ese rol. Sustituye your_strong_password por una contraseña larga y única:

curl --cacert /etc/filebeat/certs/http_ca.crt -u elastic -X POST \
  "https://your_es_host:9200/_security/user/filebeat_internal" \
  -H "Content-Type: application/json" -d '{
  "password": "your_strong_password",
  "roles": ["filebeat_writer"]
}'

Ambas peticiones deben responder con {"created":true} (o {"role":{"created":true}} en el caso del rol).

Paso 3: Guardar la contraseña en el keystore de Filebeat

Para no dejar la contraseña en texto plano en filebeat.yml, guárdala en el keystore cifrado de Filebeat:

sudo filebeat keystore create
sudo filebeat keystore add ES_PWD

El segundo comando pide el valor: introduce la contraseña de filebeat_internal. Comprueba que la clave existe:

sudo filebeat keystore list
ES_PWD

Paso 4: Configurar la salida a Elasticsearch

Haz una copia del archivo original y ábrelo:

sudo cp /etc/filebeat/filebeat.yml /etc/filebeat/filebeat.yml.orig
sudo nano /etc/filebeat/filebeat.yml

Sustituye todo su contenido por esta configuración mínima. Los inputs propios se añadirán en el paso 7:

filebeat.inputs: []

filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false

output.elasticsearch:
  hosts: ["https://your_es_host:9200"]
  username: "filebeat_internal"
  password: "${ES_PWD}"
  ssl.certificate_authorities: ["/etc/filebeat/certs/http_ca.crt"]

setup.kibana:
  host: "https://your_kibana_host:5601"
  ssl.certificate_authorities: ["/etc/filebeat/certs/http_ca.crt"]

processors:
  - add_host_metadata: ~

Valida la sintaxis y la conexión con Elasticsearch:

sudo filebeat test config
sudo filebeat test output
Config OK
elasticsearch: https://your_es_host:9200...
  parse url... OK
  connection...
    parse host... OK
    dns lookup... OK
    addresses: 203.0.113.10
    dial up... OK
  TLS...
    security: server's certificate chain verification is enabled
    handshake... OK
    TLS version: TLSv1.3
    dial up... OK
  talk to server... OK
  version: 9.1.4

Si talk to server falla con un error de autenticación, revisa el usuario y el valor de ES_PWD.

Paso 5: Activar el módulo de Nginx

Los módulos traen la ruta de los logs, un pipeline de ingesta que los parsea en Elasticsearch y dashboards de Kibana. Activa el de Nginx:

sudo filebeat modules enable nginx

En las versiones actuales, cada conjunto de logs (fileset) del módulo viene desactivado por defecto. Abre su configuración:

sudo nano /etc/filebeat/modules.d/nginx.yml

Activa los logs de acceso y de error. Las rutas por defecto (/var/log/nginx/access.log* y /var/log/nginx/error.log*) son las de Ubuntu, así que no hace falta indicarlas:

- module: nginx
  access:
    enabled: true
  error:
    enabled: true

Comprueba que el módulo aparece como activo:

sudo filebeat modules list | head -5
Enabled:
nginx

Disabled:
activemq

Paso 6: Cargar la plantilla de índice y los dashboards

filebeat setup crea en Elasticsearch la plantilla de índice, la política de ciclo de vida y el flujo de datos filebeat-*, y carga los dashboards en Kibana. Necesita más permisos que el usuario de publicación, por lo que se ejecuta una sola vez con el superusuario, pasando las credenciales solo en la línea de comandos:

sudo filebeat setup -e \
  -E output.elasticsearch.username=elastic \
  -E output.elasticsearch.password='your_elastic_password'

El proceso tarda uno o dos minutos. Al terminar deberías ver:

Index setup finished.
Loading dashboards (Kibana must be running and reachable)
Loaded dashboards

Carga también los pipelines de ingesta del módulo de Nginx. El usuario de publicación solo puede leerlos, no crearlos, así que este paso también va con el superusuario:

sudo filebeat setup --pipelines --modules nginx \
  -E output.elasticsearch.username=elastic \
  -E output.elasticsearch.password='your_elastic_password'
Loaded Ingest pipelines

Repite este comando cada vez que actives un módulo nuevo.

Ahora arranca Filebeat y actívalo en el arranque:

sudo systemctl enable --now filebeat
sudo systemctl status filebeat --no-pager
● filebeat.service - Filebeat sends log files to Logstash or directly to Elasticsearch.
     Loaded: loaded (/usr/lib/systemd/system/filebeat.service; enabled; preset: enabled)
     Active: active (running) since ...

Genera algo de tráfico en Nginx (curl -s http://localhost > /dev/null) y comprueba que llegan documentos:

curl --cacert /etc/filebeat/certs/http_ca.crt -u elastic \
  "https://your_es_host:9200/filebeat-*/_count?pretty"
{
  "count" : 42,
  ...
}

Paso 7: Añadir un input propio para logs JSON y multilínea

Para logs que ningún módulo cubre se usa el input filestream. Cada input necesita un id único y estable: Filebeat lo usa para recordar la posición de lectura.

Supón una aplicación que escribe una línea JSON por evento en /var/log/myapp/app.log, y otra en Java o Python cuyos errores ocupan varias líneas (stack traces) en /var/log/myapp/worker.log. Abre de nuevo filebeat.yml:

sudo nano /etc/filebeat/filebeat.yml

Sustituye la línea filebeat.inputs: [] por este bloque:

filebeat.inputs:
  - type: filestream
    id: myapp-json
    paths:
      - /var/log/myapp/app.log
    parsers:
      - ndjson:
          target: ""
          overwrite_keys: true
          add_error_key: true
    fields:
      service: myapp
    fields_under_root: true

  - type: filestream
    id: myapp-worker
    paths:
      - /var/log/myapp/worker.log
    parsers:
      - multiline:
          type: pattern
          pattern: '^\d{4}-\d{2}-\d{2}'
          negate: true
          match: after
          max_lines: 500
    fields:
      service: myapp-worker
    fields_under_root: true
    processors:
      - drop_event:
          when:
            regexp:
              message: '^\S+ \S+ DEBUG '

Qué hace cada parte:

  • ndjson con target: "" coloca los campos del JSON en la raíz del documento, y add_error_key marca las líneas que no son JSON válido en lugar de descartarlas.
  • El parser multiline considera que un evento nuevo empieza por una fecha AAAA-MM-DD; cualquier línea que no empiece así (negate: true) se une a la anterior (match: after). Así un stack trace completo llega como un solo documento.
  • fields añade un campo service para filtrar en Kibana, y drop_event descarta las líneas de nivel DEBUG antes de enviarlas.

Adapta el pattern al formato de fecha de tu aplicación. Valida y reinicia:

sudo filebeat test config
sudo systemctl restart filebeat

Para probar el input JSON, escribe una línea de ejemplo:

sudo mkdir -p /var/log/myapp
echo '{"level":"error","msg":"pago rechazado","order_id":1234}' | sudo tee -a /var/log/myapp/app.log

Busca el evento en Elasticsearch:

curl --cacert /etc/filebeat/certs/http_ca.crt -u elastic \
  "https://your_es_host:9200/filebeat-*/_search?q=service:myapp&size=1&pretty"

El documento devuelto debe tener level, msg y order_id como campos de primer nivel.

Paso 8: Ver los logs en Kibana

Abre Kibana en el navegador y ve a Analytics > Discover. Selecciona la vista de datos filebeat-* y filtra por service : "myapp" o event.module : "nginx".

Para los dashboards del módulo, ve a Analytics > Dashboards y busca nginx. El dashboard [Filebeat Nginx] Overview ECS muestra peticiones por código de respuesta, URL más visitadas y origen geográfico de los clientes.

Solución de problemas

filebeat test output falla con x509: certificate signed by unknown authority. La ruta de ssl.certificate_authorities no apunta a la CA que firmó el certificado de Elasticsearch. Copia de nuevo http_ca.crt desde el nodo de Elasticsearch.

El servicio arranca pero no llegan eventos. Revisa el log del servicio:

sudo journalctl -u filebeat -n 50 --no-pager

Un error 403 Forbidden con action [indices:data/write/bulk] indica que al rol le faltan permisos o que el nombre del índice no coincide con filebeat-*.

Un archivo ya existente no se vuelve a leer. Filebeat guarda la posición de cada archivo en /var/lib/filebeat/registry. Es el comportamiento esperado: no reenvía lo que ya envió. Si necesitas reenviar todo desde el principio en un entorno de pruebas, para el servicio, borra ese directorio y arranca de nuevo, sabiendo que los eventos se duplicarán en Elasticsearch.

Los eventos multilínea llegan partidos. El pattern no coincide con el inicio real de las líneas. Revisa unas líneas del log con head y ajusta la expresión regular.

Conclusión

Tienes Filebeat instalado desde el repositorio oficial, enviando por TLS a Elasticsearch con un usuario de permisos mínimos, los logs de Nginx parseados por su módulo y un input propio para logs JSON y multilínea. Como siguientes pasos puedes activar otros módulos (sudo filebeat modules list muestra los disponibles, como system o mysql), definir alertas en Kibana sobre los errores de tu aplicación o ajustar la política de ciclo de vida filebeat para controlar cuántos días se conservan los datos.