Ir al contenido

Documentación

Agentes

El agente es la única parte de Provibr que se ejecuta en hardware propio. Guarda las credenciales de los sistemas que se conectan, ejecuta el trabajo que pide el panel e informa de lo que ve. La plataforma nunca se conecta hacia dentro.

Qué es un agente

Un agente cubre una red: el sitio desde el que se llega a sus hipervisores y sus paneles. Todo lo que Provibr hace en su infraestructura pasa por él.

  • La conexión es saliente. El agente la abre hacia la plataforma y la mantiene abierta; nada tiene que ser accesible desde internet y no hay que redirigir ningún puerto hacia él.
  • Las credenciales viven en su lado. Se envían al agente una sola vez y quedan selladas en un almacén cifrado de ese host; la plataforma solo guarda los nombres de los campos rellenados.
  • Informa de lo que observa. Las máquinas se sondean con un ritmo corto y cada pocos minutos se ejecuta una comparación completa, que es como el panel se entera de que una máquina se ha detenido fuera de Provibr.
  • Solo toca lo que se le ha entregado. Un recurso sin registro en Provibr se ignora, se cuenta y se vuelve a olvidar. El agente nunca adopta una máquina por su cuenta.

El host que necesita

Nada exótico, y nada que instalar antes. El agente es un único binario estático: lleva consigo su propia biblioteca de C, así que no hay ningún runtime, ningún intérprete ni ningún paquete de distribución que tenga que coincidir. Basta con una máquina virtual pequeña. Los tamaños que medimos están más abajo en esta página.

Lo que tiene que ofrecer un host de agente
RequisitoLo que hace faltaPor qué
Procesadorx86 de 64 bits (x86_64, también llamado amd64)Publicamos una única compilación para Linux y esta es la arquitectura para la que está creada. El instalador comprueba uname -m antes de descargar nada y se detiene ante cualquier otra arquitectura, en lugar de instalar algo que no puede ejecutarse. Todavía no hay una compilación para ARM.
Sistema operativoCualquier distribución de LinuxNada se enlaza con las bibliotecas del sistema, así que la distribución, su versión y su gestor de paquetes dan igual. La siguiente sección enumera aquellas en las que esta compilación se ha ejecutado de verdad.
Gestor de serviciossystemd, o el que se useEl instalador escribe una unidad de systemd y la activa. En un host sin systemd se instala y se registra todo igualmente, y después se imprime el comando para iniciar el agente con lo que se use en su lugar. Media instalación sería peor que una honesta.
Permisos al instalarroot, una vezLa instalación crea la cuenta de servicio provibr-agent, dos directorios y la unidad. Después el agente se ejecuta con esa cuenta sin privilegios, y el script de actualización, en el que no tiene permiso para escribir, es lo que hace que siga siendo así.
Conexiones salientesTCP 50051 y 50052 hacia gw.provibr.netEl puerto 50051 se usa una sola vez, durante el registro. El puerto 50052 lleva la sesión y permanece abierto. Ambos van por TLS. Si el cortafuegos filtra el tráfico saliente, esas dos reglas son todo lo que tiene que permitir.
Conexiones entrantesNingunaEl agente abre la conexión por su cuenta, así que nada tiene que ser accesible desde internet y no hay que redirigir ningún puerto hacia él. La instalación de máquinas por red es la única excepción, y aun así solo escucha en el segmento local.
Alcance dentro de su redA los sistemas que se van a conectarCon su hipervisor, su panel de control o su panel de juego se habla por su propia API, desde este host. Lo que el agente no alcanza, Provibr no lo puede gestionar.
Memoria512 MB sobranMedimos 18 MB con mil máquinas repartidas entre cinco sistemas, que es el caso más pesado de la tabla de abajo. El pico está en otro sitio: descifrar el archivo de licencia durante el registro consume unos 70 MB durante un instante, porque ese paso es deliberadamente costoso de romper por fuerza bruta.
Disco1 GB sobraEl binario ocupa 17 MB y todo lo que el agente guarda junto a él se quedó por debajo de 40 kB en nuestras mediciones. La instalación de máquinas por red es la excepción: guarda en caché los medios de arranque, hasta 20 GB de forma predeterminada.
RelojAproximadamente en horaLos certificados y los archivos de licencia llevan fechas de validez y los dos extremos las comprueban, así que un host con el reloj desfasado varios días no puede registrarse. Vale cualquier cliente NTP.
El agente se ejecuta con su propia cuenta sin privilegios bajo una unidad de systemd endurecida. Recibe exactamente dos capacidades adicionales, y solo para poder atender instalaciones por red; si se quitan, todo lo demás sigue funcionando.

Qué Linux

No hay ningún paquete que instalar ni ninguna distribución con la que coincidir, así que lo que sigue no es una lista de sistemas compatibles. Es la lista de sistemas en los que esta compilación se ha ejecutado de verdad. Cualquier otro con un kernel de Linux x86 de 64 bits debería comportarse igual, y si no lo hace nos gustaría saberlo.

Distribuciones de Linux en las que se ha ejecutado el agente
SistemaVersiónNotas
Debian13 (Trixie)
Debian12 (Bookworm)La distribución en la que se hizo la prueba completa: instalado, registrado, conectado y sondeando.
Ubuntu24.04 LTSUbuntu 24.04 es donde el kernel empezó a restringir justo los espacios de nombres que necesitan las automatizaciones. El agente incluye un perfil de AppArmor para eso; todo lo demás funciona sin tocar nada.
Ubuntu22.04 LTS
AlmaLinux9
AlmaLinux8Una biblioteca de C mucho más antigua que aquella con la que se creó esta compilación. Da igual, porque el agente lleva la suya.
Fedora42
openSUSE Leap15
Amazon Linux2023
Alpine Linux3.21musl y nada de glibc, la prueba más exigente que existe para un binario estático.
Dos límites honestos sobre esa lista. Demuestra que el binario arranca y hace su trabajo criptográfico en cada uno de estos espacios de usuario; la sesión completa, con certificados y sondeo, se midió en uno de ellos. Y todas las comprobaciones se ejecutaron en máquinas que comparten un mismo kernel, así que lo que demuestra es independencia de la distribución, no de la versión del kernel.

Cuánta máquina hace falta

El agente en sí es pequeño y se mantiene pequeño. Lo que crece es el inventario que vigila: cada veinte segundos lee la lista completa de máquinas de cada sistema conectado, la compara con la ronda anterior y solo reenvía lo que ha cambiado. Cada cinco minutos reenvía en su lugar el inventario completo, que es la red de seguridad para todo lo que, si no, habría costado un mensaje perdido, y esa es además la ronda en la que pregunta a sus nodos cuánta capacidad tienen.

Medido en un solo agente; cada fila es una ventana de cinco minutos
SituaciónMemoriaProcesador
Conectado, todavía sin nada asociado8 MB0,02 % de un núcleo
Un sistema, 10 máquinas12 MB0,03 %
Un sistema, 250 máquinas14 MB0,06 %
Un sistema, 1000 máquinas15 MB0,14 %
Cinco sistemas, 200 máquinas cada uno18 MB0,19 %
Los saltos entre las filas dicen más que las filas mismas. Asociar el primer sistema cuesta unos 4 MB y cada sistema posterior unos 0,75 MB, que es exactamente en lo que se diferencian las dos últimas filas. Las máquinas salen más baratas cuantas más hay: pasar de 10 a 1000 añadió 3 MB en total, unos 3 kB cada una, y el salto de 250 a 1000 salió aún más barato. Medido en agosto de 2026 contra sistemas simulados exactamente de esos tamaños, para que las cifras digan algo sobre el agente y no sobre el clúster de alguien.

El tráfico es la otra cifra que conviene tener. Esas mil máquinas cuestan unos 250 kB cada veinte segundos hacia sus propios sistemas, aproximadamente un gigabyte al día dentro de su red, mientras que diez máquinas cuestan 2,5 kB por ronda. De esa cifra de mil máquinas, unos 17 kB por ronda siguen hasta nosotros, unos 70 MB al día, porque solo se reenvía lo que ha cambiado.

¿Importa el tipo de sistema? Apenas. Da igual que el agente hable con un hipervisor, con un panel de control de hosting o con un panel de juego: el trabajo es el mismo, una llamada por sistema y por ronda, una comparación, un mensaje. Hay dos diferencias reales pero pequeñas: a un hipervisor se le piden además las direcciones dentro de sus sistemas invitados, como mucho una vez cada cinco minutos por máquina en marcha, y un panel que no mide nada no envía cifras de uso. Lo que sí varía enormemente es la máquina del otro lado, y esa se dimensiona por lo que ejecuta, no por el agente.

Por eso los tamaños de abajo no son mínimos medidos; el agente cabe en mucho menos. Son lo que pediríamos nosotros, porque un sistema operativo, sus registros y las herramientas propias quieren más sitio que el agente.

Lo que le daríamos a un host de agente
Cuánto tiene que gestionarvCPUMemoriaDisco
Hasta unos cientos de máquinas11 GB10 GB
Hasta unos miles de máquinas22 GB10 GB
Además, instalar máquinas por red22 GB40 GB

Qué piden los extras

Todo lo anterior es lo que un agente necesita para vigilar y controlar sus sistemas. Cuatro de sus funciones merecen además una mención aparte, y todas ellas se degradan con honestidad: si no se cumple un requisito, el agente sigue haciendo el resto e indica qué función no está ofreciendo.

Instalar máquinas por red
Esto necesita que el agente esté en el mismo segmento de red que la máquina que se está instalando, porque responde directamente a la petición de arranque de esa máquina. Su unidad ya lleva las dos capacidades que necesita para los puertos de arranque; se conceden de forma acotada y solo se usan mientras hay una instalación en marcha. Lo que sí añade es disco: los medios de arranque se guardan en caché en el host, hasta 20 GB de forma predeterminada, y se descartan primero los más antiguos.
Ejecutar automatizaciones
Las automatizaciones son TypeScript propio, así que se ejecutan dentro de un sandbox construido con espacios de nombres del kernel, y el runtime para eso no forma parte del agente: una versión fija de Bun tiene que estar en el directorio del agente que pertenece a root, donde la cuenta con la que se ejecuta el agente no puede sustituirla. Ubuntu 24.04 y posteriores restringen justo el espacio de nombres que esto necesita; el agente incluye un perfil de AppArmor que devuelve ese único permiso a ese único binario. Si falta cualquiera de las dos piezas, el agente lo indica al arrancar, no ofrece la función y sigue adelante. Cada ejecución dispone de al menos 4 GB de espacio de direcciones. Eso es virtual, no memoria que tenga que existir. Lo que de verdad cuesta en su host una automatización en marcha es algo que no hemos medido.
Reiniciar el host desde el panel
Reiniciar es una cuestión de autorización más que de privilegios: el agente le pregunta a logind, logind le pregunta a polkit, y el instalador deja una regla que permite exactamente dos acciones para exactamente esta cuenta. Los hosts instalados antes de que existiera esa regla necesitan que se ejecute el instalador una vez más, porque actualizar el agente desde el panel sustituye el binario y nada de /etc. Hasta entonces el panel lo rechaza indicando el motivo.
Consola y diagnóstico
Nada que instalar. El ping y el traceroute usan un socket ICMP que no necesita privilegios siempre que el host lo permita para el grupo de la cuenta de servicio, cosa que ocurría en todos los hosts que medimos; donde no es así, el agente mide con TCP en su lugar e indica qué método ha usado. La consola se transmite por la conexión que ya está abierta.

Instalar con el comando de una línea

En la pestaña de ajustes del agente, el panel construye un único comando que contiene un enlace de instalación. Ejecútelo como root en el host. El enlace funciona una sola vez: deja de funcionar en cuanto el agente se registra, y como mucho a las 72 horas. Puede crear uno nuevo en cualquier momento.

shell
curl -fsSL https://app.provibr.com/api/install/<token> | sh
Conviene tratar el enlace como una credencial. Quien lo tenga puede registrar este agente concreto, igual que se lo permitiría una clave de autenticación. No se guarda nunca en el panel, así que es mejor crear uno nuevo que buscar el anterior.
Los comandos y la salida del terminal están en inglés en todas partes, en el panel y en estas páginas. Un solo texto, una sola verdad: lo que se lee aquí es literalmente lo que devolverá su host.

Lo que hace el comando, en orden:

  • Comprueba que se está ejecutando como root en un host x86 de 64 bits y elige curl o wget, el que esté disponible.
  • Descarga el binario y su suma de comprobación y los verifica. Si el host no tiene ninguna herramienta para calcular una suma de comprobación, se detiene en lugar de saltarse la comprobación.
  • Crea la cuenta de servicio y los dos directorios, instala el binario y coloca el script de actualización y su clave pública, ambos propiedad de root, de modo que la cuenta con la que se ejecuta el agente no puede sustituirlos.
  • Pide el código de activación por el terminal, obtiene el archivo de licencia con ese código como cabecera de la petición y lo instala.
  • Registra el agente con la cuenta de servicio y, después, instala la unidad de systemd e inicia el servicio.

Compruebe el resultado en el host:

shell
systemctl status provibr-agent
journalctl -u provibr-agent -f
Volver a ejecutar el comando no supone ningún riesgo, con un enlace nuevo: el anterior dejó de funcionar cuando el agente se registró. Si el host ya está registrado, solo se renuevan el binario y la unidad; la identidad, el certificado y el almacén de credenciales quedan intactos. En un host sin systemd todo se instala y se registra igualmente, y el comando indica cómo ejecutar el agente a mano.

Instalar a mano

Todo lo que hace el comando de una línea son también un puñado de comandos, y el panel los imprime con los valores actuales ya rellenados. Esta es su forma.

  1. Preparar el host: la cuenta de servicio, los directorios y el binario.

    shell
    # System user without a shell and without a home directory
    id -u provibr-agent >/dev/null 2>&1 || \
      sudo useradd --system --no-create-home --shell /usr/sbin/nologin provibr-agent
    
    # Directories for configuration (license, key) and state (identity, vault)
    sudo install -d -o provibr-agent -g provibr-agent -m 0750 /etc/provibr-agent
    sudo install -d -o provibr-agent -g provibr-agent -m 0700 /var/lib/provibr-agent
    
    # The binary from the download
    sudo install -o root -g root -m 0755 ./provibr-agent-linux-x86_64 /usr/local/bin/provibr-agent
    /usr/local/bin/provibr-agent version
  2. Colocar el archivo de licencia. Se descarga desde la página del agente; está cifrado con el código de activación y se puede descargar una vez por token.

    shell
    sudo install -o root -g provibr-agent -m 0640 \
      ./provibr-<agent>.plic /etc/provibr-agent/license.plic
  3. Registrar el agente con la cuenta de servicio y el código de activación.

    shell
    sudo -u provibr-agent /usr/local/bin/provibr-agent enroll \
      --license /etc/provibr-agent/license.plic --code XXXXX-XXXXX
  4. Instalar la unidad e iniciar el servicio.

    shell
    sudo install -o root -g root -m 0644 provibr-agent.service /etc/systemd/system/provibr-agent.service
    sudo systemctl daemon-reload
    sudo systemctl enable --now provibr-agent
La descarga del binario ofrece también su suma de comprobación y su firma. Verificar la firma es el paso que una simple descarga no da, y es la misma comprobación que hace el paso de actualización con cada versión nueva.

Docker y Kubernetes

El agente también se ejecuta como contenedor. La imagen contiene el mismo binario firmado de la versión publicada que la descarga para Linux y nada más: ni shell ni gestor de paquetes, y se ejecuta como usuario sin privilegios de root. Solo se conecta hacia fuera, así que no necesita puertos publicados ni un service.

El registro ocurre en el primer arranque. Dé al contenedor el enlace de instalación del panel y el código de activación; descarga su archivo de licencia, se registra y guarda su identidad en el volumen. En cada arranque posterior se usa esa identidad y los dos valores ya no se leen.

El enlace de instalación y el código están en el entorno del contenedor, y por tanto en docker inspect, en el historial de la shell o en el secret de Kubernetes. Es la misma exposición que con el comando de una línea, y dura hasta que el agente se registra: desde entonces el enlace ya no funciona. Quítelo del secret igualmente; el agente no vuelve a leerlo.
Todo lo que guarda el agente está en el volumen, en /var/lib/provibr-agent: su certificado, el almacén cifrado con las credenciales y la clave de ese almacén. Sin volumen, cada contenedor nuevo es un agente nuevo sin registrar. Con volumen, ese volumen es todo el secreto: trate una copia como una copia del agente.

Docker

El panel muestra este comando con el enlace y el código del agente ya rellenados. El volumen con nombre toma el propietario de la imagen, así que el agente puede escribir en él sin chown.

shell
docker run -d --name provibr-agent --restart unless-stopped \
  --hostname provibr-agent \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  -v provibr-agent-data:/var/lib/provibr-agent \
  -e PROVIBR_INSTALL_URL='https://app.provibr.com/api/install/<token>' \
  -e PROVIBR_ACTIVATION_CODE='XXXXX-XXXXX' \
  ghcr.io/provibr/provibr-agent:latest

O lo mismo como archivo de Docker Compose:

docker-compose.yml
# Provibr agent — Docker Compose.
#
# The agent connects outbound to the platform; it needs no published ports.
# On the first start it enrolls itself with the installation link and the
# activation code below, and stores its identity on the volume. After that the
# two values are no longer read; the link expires 72 hours after it was made.
#
# Update: change the image tag, then `docker compose up -d`. The volume keeps
# identity and credentials.
services:
  provibr-agent:
    image: ghcr.io/provibr/provibr-agent:latest
    container_name: provibr-agent
    hostname: provibr-agent
    restart: unless-stopped
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    environment:
      PROVIBR_INSTALL_URL: "https://app.provibr.com/api/install/<token>"
      PROVIBR_ACTIVATION_CODE: "XXXXX-XXXXX"
    volumes:
      - provibr-agent-data:/var/lib/provibr-agent

volumes:
  provibr-agent-data:
¿Prefiere un bind mount a un volumen con nombre? Cree primero el directorio y déselo al usuario del agente: mkdir -p /srv/provibr-agent && chown 65532:65532 /srv/provibr-agent. Un bind mount empieza perteneciendo a root, y el agente, que no se ejecuta como root, no podría escribir en él.

Kubernetes

Manifiestos simples, sin Helm: un namespace, un secret con el enlace y el código, un volume claim y un deployment. El panel rellena el secret para el agente.

provibr-agent.yaml
# Provibr agent — Kubernetes (plain manifests, no Helm).
#
# kubectl apply -f provibr-agent.yaml
#
# The agent connects outbound to the platform; there is no Service and no port.
# On the first start it enrolls itself with the installation link and the
# activation code from the Secret, and stores its identity on the volume. After
# that the Secret is no longer read; the link expires 72 hours after it was made.
#
# Exactly one replica, and Recreate: one agent is one identity (one
# certificate). Two pods would be two agents fighting over it.
apiVersion: v1
kind: Namespace
metadata:
  name: provibr-agent
---
apiVersion: v1
kind: Secret
metadata:
  name: provibr-agent-enrollment
  namespace: provibr-agent
type: Opaque
stringData:
  PROVIBR_INSTALL_URL: "https://app.provibr.com/api/install/<token>"
  PROVIBR_ACTIVATION_CODE: "XXXXX-XXXXX"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: provibr-agent-data
  namespace: provibr-agent
spec:
  # One pod, and only one, may mount this volume. On clusters older than
  # Kubernetes 1.29 (or storage without it), use ReadWriteOnce instead; the
  # agent also refuses to start a second time on the same data directory.
  accessModes:
    - ReadWriteOncePod
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: provibr-agent
  namespace: provibr-agent
  labels:
    app.kubernetes.io/name: provibr-agent
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app.kubernetes.io/name: provibr-agent
  template:
    metadata:
      labels:
        app.kubernetes.io/name: provibr-agent
    spec:
      hostname: provibr-agent
      automountServiceAccountToken: false
      enableServiceLinks: false
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        runAsGroup: 65532
        fsGroup: 65532
        # Only when the volume root does not match yet; otherwise the kubelet
        # widens the modes on the private keys at every mount.
        fsGroupChangePolicy: OnRootMismatch
        seccompProfile:
          type: RuntimeDefault
        # The ping check uses an unprivileged ICMP socket. Some container
        # runtimes keep those closed, and then the check reports a source
        # error. This safe sysctl opens them for the agent's group only.
        sysctls:
          - name: net.ipv4.ping_group_range
            value: "65532 65532"
      containers:
        - name: agent
          image: ghcr.io/provibr/provibr-agent:latest
          args: ["run"]
          envFrom:
            # optional: the agent reads it on its first start only, so you can
            # delete the Secret once it is enrolled.
            - secretRef:
                name: provibr-agent-enrollment
                optional: true
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
          resources:
            requests:
              cpu: 50m
              memory: 32Mi
            limits:
              memory: 256Mi
          volumeMounts:
            - name: data
              mountPath: /var/lib/provibr-agent
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: provibr-agent-data
Mantenga replicas en 1 y la estrategia en Recreate. Un agente es una identidad: dos pods en el mismo volumen comparten un certificado y se echan mutuamente de la plataforma, y dos pods con su propio volumen se registran los dos, tras lo cual solo el último es válido. Una actualización progresiva haría justo eso durante un momento.
La comprobación de ping usa un socket ICMP sin privilegios, no la capability NET_RAW. Algunos entornos de ejecución de contenedores mantienen esos sockets cerrados; medido con ellos cerrados, un ping de diagnóstico recurrió a TCP y la comprobación de monitorización informó de un error de origen. El manifiesto los abre para el grupo del agente con el sysctl seguro net.ipv4.ping_group_range. Añadir NET_RAW no sirve de nada: el agente no se ejecuta como root, así que no obtiene capabilities efectivas.

Para Kubernetes, el archivo de licencia es la mejor vía: ponga en el secret el archivo de licencia y el código en lugar del enlace de instalación, monte el archivo en el pod y apunte PROVIBR_LICENSE_FILE a su ruta. El token del archivo funciona exactamente una vez, así que el secret no contiene nada con lo que registrar el agente una segunda vez.

Actualizar un contenedor

De forma predeterminada, un contenedor no se actualiza por sí mismo: la imagen es la versión publicada. El panel muestra qué imagen es la actual; descárguela y vuelva a crear el contenedor, o ponga la etiqueta nueva en el deployment. El volumen conserva la identidad y las credenciales. Las actualizaciones automáticas omiten estos agentes; la opción de abajo lo cambia.

shell
docker pull ghcr.io/provibr/provibr-agent:latest
docker stop provibr-agent && docker rm provibr-agent
# then run the same docker run command again with the new image
shell
kubectl -n provibr-agent set image deployment/provibr-agent agent=ghcr.io/provibr/provibr-agent:latest

Opción: actualizarse desde el volumen

Basta con definir PROVIBR_SELF_UPDATE=volume o marcar la opción en el panel. El contenedor participa entonces en el botón de actualización y en las actualizaciones nocturnas: se descarga una versión nueva, su firma se comprueba con la clave de la plataforma incluida en la imagen y se guarda en el volumen. El contenedor se detiene con el código de salida 0, Docker o el kubelet lo vuelve a iniciar, y el binario de la imagen inicia la versión nueva desde el volumen tras comprobar la firma una vez más.

shell
docker run -d --name provibr-agent --restart unless-stopped \
  --hostname provibr-agent \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  -v provibr-agent-data:/var/lib/provibr-agent \
  -e PROVIBR_INSTALL_URL='https://app.provibr.com/api/install/<token>' \
  -e PROVIBR_ACTIVATION_CODE='XXXXX-XXXXX' \
  -e PROVIBR_SELF_UPDATE=volume \
  ghcr.io/provibr/provibr-agent:latest

Una versión nueva tiene 60 segundos para llegar a la plataforma. Si no lo consigue, se marca como defectuosa en el volumen y no se vuelve a iniciar nunca, y el contenedor vuelve con la versión anterior. Al desplegar una imagen más reciente, manda la imagen: lo que se guardó en el volumen para la imagen anterior deja de usarse.

Lo que se cede: la etiqueta de la imagen ya no indica qué versión se ejecuta (el panel sí), los escáneres de imágenes analizan el binario de la imagen y no el del volumen, y una herramienta de GitOps ve un pod que ejecuta algo distinto de lo que dice su manifiesto. No lo recomendamos para clústeres gestionados por una herramienta de GitOps.

Opción: la imagen de herramientas para automatizaciones

La imagen estándar no incluye el runtime de automatizaciones. La imagen de herramientas, con el sufijo de etiqueta -tools, contiene el mismo agente firmado sobre Debian con el runtime de automatizaciones fijado, de modo que las automatizaciones pueden ejecutarse en el contenedor. Los ejemplos de Docker le dan un /tmp pequeño y un límite de pids (--pids-limit); en Kubernetes /tmp es un emptyDir en memoria, y el límite de pids se fija en el kubelet (podPidsLimit), no en el manifiesto. El sistema de archivos raíz sigue siendo de solo lectura.

shell
docker run -d --name provibr-agent --restart unless-stopped \
  --hostname provibr-agent \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  --tmpfs /tmp:rw,noexec,nosuid,size=16m --pids-limit 256 \
  -v provibr-agent-data:/var/lib/provibr-agent \
  -e PROVIBR_INSTALL_URL='https://app.provibr.com/api/install/<token>' \
  -e PROVIBR_ACTIVATION_CODE='XXXXX-XXXXX' \
  ghcr.io/provibr/provibr-agent:latest-tools
En un host Linux, una automatización se ejecuta en un sandbox con sus propios espacios de nombres: sin red, sin archivos del host y con su propio árbol de procesos. Un contenedor no puede crear esos espacios de nombres, así que en la imagen de herramientas el agente limita el runtime de otras dos formas. Un filtro seccomp, que funciona con cualquier kernel, bloquea todo socket de red (TCP y UDP), las señales a otros procesos, el arranque de procesos nuevos y la lectura de la memoria de otro proceso. Landlock (Linux 5.13 o posterior) limita los archivos: un script solo puede leer el runtime y las bibliotecas del sistema y no puede escribir nada. El agente prueba ambos al arrancar; si el kernel o el perfil seccomp del runtime de contenedores no los permiten, las automatizaciones quedan desactivadas en el contenedor. Lo que queda es más débil que en un host: un script todavía puede ver qué procesos se ejecutan en el contenedor. Elegir la imagen de herramientas es elegir eso.

Lo que no funciona en un contenedor

Algunas funciones necesitan el propio host, y un contenedor restringido no lo tiene:

  • Instalaciones por red (PXE): necesitan la red del host y puertos por debajo de 1024.
  • Reiniciar el host desde el panel: el contenedor no tiene acceso al sistema de arranque del host.
  • Automatizaciones en la imagen estándar: no incluye el runtime de automatizaciones, y el sandbox que reciben en un host necesita espacios de nombres de usuario, que un contenedor restringido no concede. La imagen de herramientas las ejecuta, en cambio, dentro del contenedor.
  • Métricas del host: la CPU, la memoria y el tiempo de actividad describen la máquina en la que se ejecuta el contenedor, no los límites del propio contenedor.

El código de activación y el archivo de licencia

Al crear un agente, el panel muestra un código de activación una sola vez. No se guarda en ningún sitio, ni siquiera como hash. El código es lo que cifra el archivo de licencia, así que el archivo del host está cifrado con algo que no está en ese host.

¿Se ha perdido el código o el archivo? Genere un token nuevo en la página del agente. Eso invalida el anterior, incluido un archivo de licencia que ya estuviera en camino, y da un código nuevo y una descarga nueva.

El archivo de licencia en sí no lleva ningún secreto sobre su infraestructura. Le dice al agente a qué plataforma pertenece, en qué autoridad certificadora confiar y con qué token de un solo uso registrarse.

Gestionar agentes en el panel

La lista de agentes lo muestra todo a la vez: el estado, la versión, si está conectado ahora mismo, cuándo se le vio por última vez y cuándo caduca su certificado.

  • El nombre y la descripción se pueden cambiar y son solo etiquetas. Un nombre que ya esté dentro de un archivo de licencia entregado se queda como estaba, lo cual es cosmético y no es motivo para volver a registrar el agente.
  • Si está conectado o no se lee de una señal en directo con una caducidad corta, no de la última vez que se escribió una fila. Si no se puede saber, el panel lo indica en lugar de afirmar que el agente está caído.
  • La versión y el sistema operativo son lo que informó el agente en su última conexión. Un agente que nunca se ha conectado muestra un guion en lugar de una suposición.
  • Se pueden seleccionar varios agentes de la lista para actualizarlos de una vez. El botón cuenta únicamente los agentes que se pueden actualizar ahora mismo, así que antes de pulsar ya se ve que doce seleccionados significan tres actualizados.
  • El progreso se lee del comando que se está ejecutando, no de algo que recuerde el navegador, así que una recarga lo retoma.

Los tres estados

Pendiente de registro
Creado en el panel, todavía sin registrar. Tiene un token y un código de activación esperándolo, y aún no tiene certificado.
Registrado
Tiene su propio certificado y puede conectarse. Es el único estado en el que se le puede encargar trabajo, y el único en el que no se puede eliminar.
Revocado
Retirado del servicio. Su sesión se cierra, los tokens pendientes quedan anulados y no puede volver.

Revocar un agente

Revocar es el interruptor al que se recurre cuando un host está comprometido, se retira del servicio o simplemente deja de ser suyo. Surte efecto sin tocar el host.

  • Una sesión en marcha se cierra en menos de un minuto. Al agente se le dice el motivo en lugar de cortarlo sin más.
  • Después el agente borra su propia identidad, su certificado y su almacén de credenciales. Las credenciales de su hipervisor desaparecen de ese host.
  • Los tokens de registro pendientes quedan anulados, así que un archivo de licencia ya descargado no sirve para volver.
No se puede deshacer. Un agente revocado por error hay que crearlo de nuevo, instalarlo de nuevo y volver a entregarle sus credenciales.

Eliminar un agente

Eliminar quita el agente del panel. Es un paso distinto de revocar y es deliberadamente exigente con el momento en que se permite.

  • Un agente registrado no se puede eliminar. Hay que revocarlo primero, porque de lo contrario se estaría borrando el registro de algo que sigue conectado.
  • Un agente con integraciones o servidores asociados tampoco se puede eliminar, y el rechazo indica las dos cifras. Esas filas cuelgan del agente, así que un solo clic se llevaría por delante el inventario.
  • Si el agente nunca ejecutó un comando ni tuvo un servidor, la fila desaparece de verdad. En caso contrario se oculta en todas partes, pero se conserva su historial de comandos, porque un registro de auditoría que se borra eliminando su sujeto no es un registro de auditoría.

Quitarlo del host

Revocar borra los secretos del agente, pero deja los archivos. Para limpiar el host, el panel ofrece un segundo comando de una línea y los mismos cuatro pasos a mano.

Este script no revoca nada. Primero se revoca en el panel y después se limpia el host, en ese orden. Al revés queda un host que todavía guarda una identidad válida.
  1. Detener el servicio, desactivarlo y eliminar la unidad.

    shell
    # Stop the service and forget the unit
    sudo systemctl disable --now provibr-agent
    sudo rm -f /etc/systemd/system/provibr-agent.service
    sudo systemctl daemon-reload
    sudo systemctl reset-failed provibr-agent 2>/dev/null || true
  2. Eliminar el binario, el script de actualización y la clave de actualización.

    shell
    # Binary, update script and the trust anchor of the update step
    sudo rm -f /usr/local/bin/provibr-agent
    sudo rm -f /usr/local/lib/provibr-agent/apply-update.sh /usr/local/lib/provibr-agent/license-signing.pub
    
    # The polkit rule that allowed host.reboot (and its 0.105 fallback)
    sudo rm -f /etc/polkit-1/rules.d/49-provibr-agent-reboot.rules /etc/polkit-1/localauthority/50-local.d/49-provibr-agent-reboot.pkla
    
    # Only if nothing else lives in there
    sudo rmdir /usr/local/lib/provibr-agent 2>/dev/null || true
  3. Eliminar los datos. Este es el paso que importa: aquí viven la licencia, la clave del almacén y las credenciales cifradas.

    shell
    # License and vault key
    sudo rm -rf /etc/provibr-agent
    
    # Identity, encrypted credential vault, outbox and staged updates
    sudo rm -rf /var/lib/provibr-agent
  4. Eliminar la cuenta de servicio.

    shell
    sudo userdel provibr-agent
    sudo groupdel provibr-agent 2>/dev/null || true

Después, estos dos comandos no deberían mostrar nada:

shell
ls -d /etc/provibr-agent /var/lib/provibr-agent /usr/local/lib/provibr-agent /usr/local/bin/provibr-agent /etc/systemd/system/provibr-agent.service /etc/polkit-1/rules.d/49-provibr-agent-reboot.rules /etc/polkit-1/localauthority/50-local.d/49-provibr-agent-reboot.pkla 2>/dev/null
id provibr-agent 2>/dev/null
# Both commands should print nothing at all