Vector es un agente de observabilidad escrito en Rust que recoge logs y métricas, los transforma y los envía a uno o varios destinos con un consumo de recursos muy bajo. Su configuración se organiza en fuentes (sources), transformaciones (transforms) y destinos (sinks), y las transformaciones se escriben en VRL (Vector Remap Language). En este tutorial instalarás Vector en Ubuntu 24.04, leerás los logs de acceso de Nginx, los convertirás en eventos estructurados, descartarás el ruido y los enviarás a Grafana Loki.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Vector funciona con 512 MB de RAM libres para cargas moderadas.
  • Un usuario no root con privilegios sudo.
  • Nginx instalado y sirviendo tráfico, que será la fuente de logs del ejemplo. Si no lo tienes, instálalo con sudo apt install nginx.
  • Opcional para el paso 6: un servidor Grafana Loki accesible desde este servidor. Si todavía no tienes uno, puedes completar los pasos 1 a 5 enviando los eventos a la consola.

Paso 1: Instalar Vector desde su repositorio oficial

Vector publica paquetes .deb en un repositorio APT mantenido por Datadog. La forma soportada de configurarlo es un script que añade las claves GPG y el archivo de origen de APT. Descárgalo y revísalo antes de ejecutarlo:

curl -fsSL -o setup-vector.sh https://setup.vector.dev
less setup-vector.sh

El script crea /etc/apt/sources.list.d/vector.list apuntando a https://apt.vector.dev/ y guarda las claves en /usr/share/keyrings/datadog-archive-keyring.gpg. Ejecútalo (pedirá sudo cuando lo necesite) e instala el paquete:

bash setup-vector.sh
sudo apt install -y vector

Comprueba la versión instalada:

vector --version
vector 0.50.0 (x86_64-unknown-linux-gnu)

El número de versión será el más reciente disponible cuando hagas la instalación. El paquete crea el usuario de sistema vector, lo añade a los grupos adm y systemd-journal para que pueda leer /var/log y el journal, e instala la unidad vector.service, que lee la configuración de /etc/vector/vector.yaml.

Paso 2: Entender la configuración de ejemplo

El paquete incluye un vector.yaml de demostración que genera logs de prueba en formato syslog, los analiza y los imprime. Guárdalo como referencia antes de sustituirlo:

sudo mv /etc/vector/vector.yaml /etc/vector/vector.yaml.example

Toda configuración de Vector tiene la misma forma:

  • sources: de dónde vienen los eventos (archivos, journald, syslog, Docker, Kafka, HTTP).
  • transforms: qué se hace con ellos (analizar, filtrar, enriquecer, muestrear). Cada transformación declara en inputs de qué componentes recibe eventos.
  • sinks: a dónde se envían (Loki, Elasticsearch, S3, la consola). También declaran sus inputs.

Cada componente tiene un identificador que eliges tú, y los inputs enlazan unos con otros para formar la topología.

Paso 3: Leer y analizar los logs de Nginx

Crea la nueva configuración con una fuente que lee el log de acceso de Nginx, una transformación que lo analiza y un destino de consola para comprobar el resultado:

sudo nano /etc/vector/vector.yaml
api:
  enabled: true
  address: "127.0.0.1:8686"

sources:
  nginx_access:
    type: file
    include:
      - /var/log/nginx/access.log
    read_from: end

transforms:
  parse_nginx:
    type: remap
    inputs:
      - nginx_access
    source: |
      parsed, err = parse_nginx_log(.message, "combined")
      if err != null {
        abort
      }
      . = merge(., parsed)
      del(.message)

sinks:
  console:
    type: console
    inputs:
      - parse_nginx
    encoding:
      codec: json

Qué hace cada bloque:

  • api activa la API local de Vector en 127.0.0.1:8686, que usan las herramientas vector top y vector tap. Solo escucha en localhost.
  • La fuente file sigue access.log y guarda su posición en /var/lib/vector, así que tras un reinicio continúa donde se quedó. Con read_from: end ignora las líneas anteriores al primer arranque.
  • La transformación remap ejecuta VRL. parse_nginx_log con el formato combined (el predeterminado de Nginx) devuelve campos como client, method, path, status, size, referer y agent. Si una línea no encaja, el evento se descarta con abort. VRL obliga a tratar ese posible error: por eso la función se llama con la forma parsed, err = ... en lugar de ignorarlo.

Valida la configuración antes de aplicarla. vector validate comprueba la sintaxis, los tipos de VRL y que los componentes estén bien enlazados:

sudo -u vector vector validate /etc/vector/vector.yaml
√ Loaded ["/etc/vector/vector.yaml"]
√ Component configuration
√ Health check "console"
------------------------------------
                           Validated

Ejecutarlo como el usuario vector confirma además que ese usuario puede leer los archivos. Reinicia el servicio:

sudo systemctl restart vector
sudo systemctl status vector --no-pager
● vector.service - Vector
     Loaded: loaded (/usr/lib/systemd/system/vector.service; enabled; preset: enabled)
     Active: active (running) since ...

Paso 4: Comprobar los eventos procesados

Genera algo de tráfico contra Nginx:

curl -s -o /dev/null http://localhost/
curl -s -o /dev/null http://localhost/no-existe

El destino console escribe en la salida estándar, que systemd guarda en el journal. Mira los últimos eventos:

sudo journalctl -u vector -n 2 --no-pager -o cat
{"agent":"curl/8.5.0","client":"127.0.0.1","file":"/var/log/nginx/access.log","host":"your_hostname","method":"GET","path":"/","protocol":"HTTP/1.1","size":615,"source_type":"file","status":200,"timestamp":"2026-09-25T10:12:03Z"}
{"agent":"curl/8.5.0","client":"127.0.0.1","file":"/var/log/nginx/access.log","host":"your_hostname","method":"GET","path":"/no-existe","protocol":"HTTP/1.1","size":162,"source_type":"file","status":404,"timestamp":"2026-09-25T10:12:04Z"}

La línea de texto de Nginx se ha convertido en un objeto con tipos: status y size son números, y timestamp es la hora de la petición, no la de lectura.

Para inspeccionar el flujo en directo sin tocar la configuración, usa vector tap, que se conecta a la API y muestra los eventos que salen de un componente:

vector tap parse_nginx

Y para ver el rendimiento de cada componente (eventos por segundo, errores), vector top. Sal de ambos con Ctrl+C o q.

Paso 5: Filtrar el ruido y añadir campos

Los health checks y las peticiones de monitorización suelen ser la mayoría de las líneas y no aportan nada. Añade una transformación filter que los descarte y otra remap que clasifique cada petición por su código de estado. Edita el archivo:

sudo nano /etc/vector/vector.yaml

Sustituye la sección transforms y cambia el inputs del destino console para que reciba eventos de la última transformación:

transforms:
  parse_nginx:
    type: remap
    inputs:
      - nginx_access
    source: |
      parsed, err = parse_nginx_log(.message, "combined")
      if err != null {
        abort
      }
      . = merge(., parsed)
      del(.message)

  drop_healthchecks:
    type: filter
    inputs:
      - parse_nginx
    condition: '!includes(["/health", "/healthz", "/favicon.ico"], .path)'

  classify:
    type: remap
    inputs:
      - drop_healthchecks
    source: |
      status = to_int(.status) ?? 0
      .level = if status >= 500 {
        "error"
      } else if status >= 400 {
        "warning"
      } else {
        "info"
      }

sinks:
  console:
    type: console
    inputs:
      - classify
    encoding:
      codec: json

filter deja pasar solo los eventos cuya condición VRL es verdadera. En classify, el operador ?? da un valor por defecto si la conversión falla, algo que VRL exige para compilar: no permite ignorar errores posibles.

Valida y recarga. La unidad de systemd ejecuta vector validate y envía SIGHUP, por lo que la configuración se aplica sin perder eventos:

sudo -u vector vector validate /etc/vector/vector.yaml
sudo systemctl reload vector

Repite las peticiones del paso 4 y añade una a /health. En el journal verás los dos primeros eventos con el campo level (info y warning) y ninguno para /health.

Paso 6: Enviar los logs a Grafana Loki

Cuando el pipeline produce los eventos que quieres, añade un destino real. Sustituye your_loki_host por la dirección de tu servidor Loki y añade este bloque dentro de sinks:

  loki:
    type: loki
    inputs:
      - classify
    endpoint: http://your_loki_host:3100
    encoding:
      codec: json
    labels:
      job: nginx
      host: "{{ host }}"
      level: "{{ level }}"

Usa como etiquetas de Loki solo campos con pocos valores distintos (job, host, level). Campos como path o client tienen miles de valores y degradan Loki; déjalos dentro de la línea JSON, donde puedes filtrarlos con LogQL.

Antes de recargar, comprueba que Loki responde desde este servidor:

curl http://your_loki_host:3100/ready
ready

Valida y recarga Vector:

sudo -u vector vector validate /etc/vector/vector.yaml
sudo systemctl reload vector

vector validate ejecuta también el health check del destino de Loki, así que un error de conexión aparecerá aquí. Cuando todo funcione, puedes quitar el destino console para no llenar el journal. En Grafana, una consulta como {job="nginx", level="error"} mostrará las respuestas 5xx.

Solución de problemas

Permission denied al leer /var/log/nginx/access.log. El usuario vector debe pertenecer al grupo adm. Compruébalo con id vector; si falta, ejecuta sudo usermod -aG adm vector y reinicia el servicio (una recarga no aplica cambios de grupo).

El servicio no arranca tras un cambio. La unidad ejecuta vector validate antes de iniciar, y si falla no arranca. Lee el motivo con sudo journalctl -u vector -n 50 --no-pager; los errores de VRL señalan la línea exacta del programa y el motivo.

No llega nada al destino. Usa vector tap parse_nginx y luego vector tap classify para ver en qué componente desaparecen los eventos. Si vector tap no conecta, revisa que la sección api esté activada.

Eventos perdidos cuando Loki no está disponible. Por defecto, cada destino usa un búfer en memoria de 500 eventos. Para cortes largos, configura en el destino un búfer en disco con buffer.type: disk y buffer.max_size en bytes.

Conclusión

Tienes Vector en Ubuntu 24.04 leyendo los logs de acceso de Nginx, convirtiéndolos en eventos estructurados con VRL, descartando el ruido y enviándolos a Grafana Loki, con validación antes de cada recarga. Como siguientes pasos puedes añadir una fuente journald para los logs de systemd, generar métricas a partir de los logs con la transformación log_to_metric o archivar una copia comprimida en un bucket S3 compatible con el destino aws_s3.