Node Exporter es el exportador oficial de Prometheus para métricas del sistema: CPU, memoria, disco, sistemas de archivos, red y carga. Expone esas métricas por HTTP en el puerto 9100 para que un servidor Prometheus las recoja periódicamente. En este tutorial instalarás la última versión de Node Exporter en Ubuntu 24.04 como servicio systemd, lo protegerás con TLS y usuario y contraseña, y lo añadirás a Prometheus junto con un par de reglas de alerta.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS que quieras monitorizar, por ejemplo un VPS de CubePath, con un usuario no root con privilegios sudo.
  • Un servidor Prometheus ya instalado que pueda llegar a este servidor por red (en la misma máquina o en otra). En los ejemplos, su IP es prometheus_server_ip y su configuración está en /etc/prometheus/prometheus.yml.
  • La IP del servidor monitorizado, que aparece como your_server_ip.

Paso 1: Crear un usuario de sistema

Node Exporter no necesita privilegios, así que se ejecutará con un usuario propio sin shell ni directorio personal:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin node_exporter

Comprueba que existe:

id node_exporter
uid=998(node_exporter) gid=998(node_exporter) groups=998(node_exporter)

Paso 2: Descargar e instalar el binario

Ubuntu incluye el paquete prometheus-node-exporter, pero trae una versión antigua. El proyecto publica binarios estáticos en GitHub, que es la forma recomendada de tener una versión actual. Consulta la última versión en la página de releases y guárdala en una variable (en el momento de escribir esto es la 1.12.1). En servidores ARM, cambia amd64 por arm64:

VERSION=1.12.1
ARCH=amd64
cd /tmp
curl -LO "https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/node_exporter-${VERSION}.linux-${ARCH}.tar.gz"
curl -LO "https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/sha256sums.txt"

Verifica la suma de comprobación antes de instalar nada:

sha256sum --check --ignore-missing sha256sums.txt
node_exporter-1.12.1.linux-amd64.tar.gz: OK

Extrae el archivo e instala el binario en /usr/local/bin:

tar xzf "node_exporter-${VERSION}.linux-${ARCH}.tar.gz"
sudo install -m 0755 "node_exporter-${VERSION}.linux-${ARCH}/node_exporter" /usr/local/bin/
node_exporter --version

La primera línea de la salida muestra la versión instalada:

node_exporter, version 1.12.1 (branch: HEAD, revision: ...)

Limpia los archivos temporales:

rm -rf /tmp/node_exporter-* /tmp/sha256sums.txt

Paso 3: Crear el servicio systemd

Crea también el directorio del recolector textfile, que usarás más adelante para publicar métricas propias:

sudo install -d -o node_exporter -g node_exporter -m 0755 /var/lib/node_exporter/textfile_collector

Crea la unidad de systemd:

sudo nano /etc/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
    --web.listen-address=:9100 \
    --collector.systemd \
    --collector.textfile.directory=/var/lib/node_exporter/textfile_collector
Restart=on-failure
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=read-only

[Install]
WantedBy=multi-user.target

La mayoría de recolectores (CPU, memoria, disco, red, sistemas de archivos) vienen activados por defecto. --collector.systemd añade el estado de cada unidad de systemd, útil para alertar de servicios caídos. Las opciones NoNewPrivileges y Protect* limitan lo que el proceso puede tocar, ya que solo necesita leer.

Recarga systemd, habilita el servicio y arráncalo:

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
systemctl status node_exporter --no-pager
● node_exporter.service - Prometheus Node Exporter
     Loaded: loaded (/etc/systemd/system/node_exporter.service; enabled; preset: enabled)
     Active: active (running) since Fri 2026-09-25 10:40:12 UTC; 3s ago
   Main PID: 5120 (node_exporter)

Si no arranca, revisa el motivo con journalctl -u node_exporter -n 50 --no-pager.

Paso 4: Comprobar las métricas

Pide el endpoint /metrics desde el propio servidor y filtra algunas métricas conocidas:

curl -s http://localhost:9100/metrics | grep -E '^node_(load1|memory_MemAvailable_bytes|filesystem_avail_bytes\{.*mountpoint="/")'
node_filesystem_avail_bytes{device="/dev/vda1",device_error="",fstype="ext4",mountpoint="/"} 3.1784534016e+10
node_load1 0.08
node_memory_MemAvailable_bytes 1.702846464e+09

Cada línea es una serie: nombre de la métrica, etiquetas entre llaves y valor actual. Prometheus guardará estos valores cada vez que haga un scrape.

Paso 5: Publicar métricas propias con el recolector textfile

El recolector textfile lee cualquier archivo *.prom del directorio configurado. Es la forma sencilla de exponer datos de tus propios scripts, por ejemplo la hora de la última copia de seguridad correcta. Añade al final de tu script de backup, tras comprobar que ha terminado bien:

DIR=/var/lib/node_exporter/textfile_collector
printf 'backup_last_success_timestamp_seconds %s\n' "$(date +%s)" > "$DIR/backup.prom.$$"
mv "$DIR/backup.prom.$$" "$DIR/backup.prom"

Escribir en un archivo temporal y renombrarlo después evita que Node Exporter lea un archivo a medio escribir. El script debe poder escribir en el directorio: ejecútalo como root o da permisos a su usuario.

Compruébalo:

curl -s http://localhost:9100/metrics | grep ^backup_
backup_last_success_timestamp_seconds 1.790332812e+09

Paso 6: Proteger Node Exporter con TLS y autenticación

Las métricas revelan información del servidor (versión del kernel, servicios, discos), así que no deben quedar abiertas a Internet. Node Exporter soporta TLS y autenticación básica mediante un archivo de configuración web.

Generar un certificado

Crea un certificado autofirmado válido para la IP del servidor. Prometheus confiará en él de forma explícita:

sudo install -d -o root -g node_exporter -m 0750 /etc/node_exporter
sudo openssl req -x509 -newkey rsa:4096 -nodes -days 3650 \
  -keyout /etc/node_exporter/node_exporter.key \
  -out /etc/node_exporter/node_exporter.crt \
  -subj "/CN=your_server_ip" \
  -addext "subjectAltName=IP:your_server_ip"
sudo chgrp node_exporter /etc/node_exporter/node_exporter.key
sudo chmod 640 /etc/node_exporter/node_exporter.key

Si el servidor tiene nombre DNS, usa DNS:your_domain en subjectAltName y apunta Prometheus a ese nombre.

Crear la contraseña

Node Exporter guarda las contraseñas como hash bcrypt. Instala apache2-utils y genera el hash de una contraseña robusta (te la pedirá dos veces):

sudo apt install apache2-utils
htpasswd -nBC 12 "" | tr -d ':\n'; echo
New password:
Re-type new password:
$2y$12$Qx0p9...resto_del_hash

Crear el archivo de configuración web

sudo nano /etc/node_exporter/web.yml

Pega el hash que has generado:

tls_server_config:
  cert_file: /etc/node_exporter/node_exporter.crt
  key_file: /etc/node_exporter/node_exporter.key

basic_auth_users:
  prometheus: $2y$12$Qx0p9...resto_del_hash

Ajusta los permisos y añade la opción --web.config.file al servicio:

sudo chgrp node_exporter /etc/node_exporter/web.yml
sudo chmod 640 /etc/node_exporter/web.yml
sudo nano /etc/systemd/system/node_exporter.service
ExecStart=/usr/local/bin/node_exporter \
    --web.listen-address=:9100 \
    --web.config.file=/etc/node_exporter/web.yml \
    --collector.systemd \
    --collector.textfile.directory=/var/lib/node_exporter/textfile_collector

Reinicia y prueba. Sin credenciales debes recibir un 401; con ellas, las métricas:

sudo systemctl daemon-reload
sudo systemctl restart node_exporter
curl -s -o /dev/null -w '%{http_code}\n' --cacert /etc/node_exporter/node_exporter.crt https://your_server_ip:9100/metrics
curl -s --cacert /etc/node_exporter/node_exporter.crt -u prometheus https://your_server_ip:9100/metrics | head -n 3
401
Enter host password for user 'prometheus':
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 2.1e-05

Abrir el puerto solo al servidor Prometheus

Con UFW, permite el puerto 9100 solo desde la IP de Prometheus. Si UFW no está activo todavía, permite SSH antes de activarlo para no perder el acceso:

sudo ufw allow OpenSSH
sudo ufw allow from prometheus_server_ip to any port 9100 proto tcp
sudo ufw enable
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
9100/tcp                   ALLOW       prometheus_server_ip
OpenSSH (v6)               ALLOW       Anywhere (v6)

Paso 7: Añadir el objetivo en Prometheus

Los siguientes comandos se ejecutan en el servidor Prometheus. Copia allí el certificado del servidor monitorizado (por ejemplo con scp) a /etc/prometheus/node_exporter.crt y guarda la contraseña en un archivo que solo pueda leer Prometheus.

sudo nano /etc/prometheus/node_exporter.pass

Escribe en él solo la contraseña en texto plano (la misma que usaste con htpasswd), guarda y ajusta los permisos:

sudo chown prometheus:prometheus /etc/prometheus/node_exporter.pass
sudo chmod 600 /etc/prometheus/node_exporter.pass

Edita la configuración de Prometheus:

sudo nano /etc/prometheus/prometheus.yml

Añade un trabajo dentro de scrape_configs:

scrape_configs:
  - job_name: "node"
    scheme: https
    tls_config:
      ca_file: /etc/prometheus/node_exporter.crt
    basic_auth:
      username: prometheus
      password_file: /etc/prometheus/node_exporter.pass
    static_configs:
      - targets: ["your_server_ip:9100"]
        labels:
          instance_name: "web01"

Valida la configuración y recarga Prometheus:

promtool check config /etc/prometheus/prometheus.yml
sudo systemctl reload prometheus
Checking /etc/prometheus/prometheus.yml
 SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax

Comprueba el estado del objetivo con la API de Prometheus. health debe ser up:

curl -s 'http://localhost:9090/api/v1/targets?state=active' | grep -o '"health":"[a-z]*"'
"health":"up"

También puedes abrir la interfaz web de Prometheus, ir a Status > Target health y lanzar la consulta up{job="node"}, que devuelve 1 cuando el scrape funciona.

Paso 8: Añadir reglas de alerta

Con las métricas en Prometheus ya puedes definir alertas. Crea un archivo de reglas en el servidor Prometheus:

sudo mkdir -p /etc/prometheus/rules
sudo nano /etc/prometheus/rules/node.yml
groups:
  - name: node
    rules:
      - alert: NodeDown
        expr: up{job="node"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }} no responde"

      - alert: DiskAlmostFull
        expr: |
          node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"}
            / node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"} < 0.10
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Menos del 10 % libre en {{ $labels.mountpoint }} de {{ $labels.instance }}"

      - alert: HighMemoryUsage
        expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.10
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Menos del 10 % de memoria disponible en {{ $labels.instance }}"

Referencia el archivo en prometheus.yml (si aún no hay una sección rule_files, créala al nivel superior):

rule_files:
  - /etc/prometheus/rules/*.yml

Valida las reglas y recarga:

promtool check rules /etc/prometheus/rules/node.yml
sudo systemctl reload prometheus
Checking /etc/prometheus/rules/node.yml
  SUCCESS: 3 rules found

Las reglas aparecen en Alerts en la interfaz de Prometheus. Para recibir notificaciones por correo, Slack u otros canales necesitas Alertmanager.

Solución de problemas

El objetivo aparece como down con connection refused o context deadline exceeded. El puerto no es accesible desde Prometheus. Comprueba que Node Exporter escucha (sudo ss -tlnp | grep 9100) y la regla de UFW para la IP de Prometheus.

x509: certificate is valid for ..., not .... La dirección de targets no coincide con el subjectAltName del certificado. Regenera el certificado con la IP o el nombre que usa Prometheus.

server returned HTTP status 401 Unauthorized. La contraseña de password_file no coincide con el hash de web.yml. Vuelve a generar el hash y reinicia Node Exporter.

No aparecen las métricas node_systemd_*. El recolector necesita acceso a D-Bus; revisa journalctl -u node_exporter en busca de errores del recolector systemd.

Conclusión

Node Exporter ya se ejecuta como servicio sin privilegios, expone las métricas solo por TLS con autenticación y únicamente al servidor Prometheus, que las recoge y evalúa reglas de alerta sobre ellas. Repite los pasos 1 a 6 en cada servidor que quieras monitorizar y añade su IP a targets.

Como siguientes pasos puedes instalar Grafana e importar el dashboard "Node Exporter Full" para visualizar las métricas, configurar Alertmanager para recibir las alertas, o automatizar la instalación en todos tus servidores con Ansible.