Ir al contenido

Instalar desde un paquete

La próxima release es 0.4; todavía no está publicada en GitHub. Los comandos siguientes describen los artefactos previstos. Compila desde el código fuente hasta su publicación y verifica cada artefacto antes de usarlo. El estado observado está en docs/releases/0.4-install-surfaces.json.

Esta es la vía para un host Linux normal en el que quieres el motor como servicio, no en un contenedor. Debian/Ubuntu y RHEL/Fedora/SUSE usan systemd por defecto. El init por defecto de Alpine es OpenRC, no systemd. Para contenedores, véase Despliega con Docker; para un host sin ruta de salida, Instala en un entorno aislado de red, a la que esta página vuelve en el paso de actualización.

1. Verifica la release antes de confiar en ella

Sección titulada «1. Verifica la release antes de confiar en ella»

En un producto de seguridad la cadena de construcción forma parte del modelo de confianza, así que nada aquí te pide que te fíes de la descarga. Pon el paquete, checksums.txt y la firma en un mismo directorio y ejecuta el verificador desde ese directorio:

Ventana de terminal
# The verifier is in a source checkout of the release tag, not a release asset; running it
# trusts the checkout. Without one, INSTALL.md shows the cosign + sha256sum commands.
# keyless / Sigstore (default; reaches Rekor over the network)
/path/to/olivares/scripts/verify-release.sh

Las releases se firman sin clave y no publican ninguna clave pública de cosign, así que usa el comando sin clave para los paquetes descargados de una release. Necesita el material de raíz de confianza de Sigstore, que cosign descarga salvo que ya esté en caché. --offline quita solo la consulta a Rekor; no hace que la verificación funcione sin red. --key solo sirve para archivos firmados con una clave privada que controlas, y esa clave pública debe obtenerse por separado de los archivos que verifica.

Qué comprueba cada paso, cómo se comporta ante una release parcial y cómo verificar la imagen de contenedor está en Verifica lo que has descargado.

Los tres formatos llevan el binario en /usr/bin/olivares, un fichero de entorno en /etc/olivares/olivares.env (config|noreplace), el directorio de datos /var/lib/olivares y los textos de licencia bajo /usr/share/doc/olivares/. .deb y .rpm entregan la unidad systemd endurecida. El .apk pone una unidad OpenRC ejecutable en /etc/init.d/olivares, con un sello package-init explícito para que los ganchos no adivinen por la presencia de systemctl en el host. Los archivos Linux llevan los mismos adaptadores de servicio: scripts/install-service.sh y packaging/service/.

Ventana de terminal
# Debian / Ubuntu
sudo dpkg -i olivares_0.4_linux_amd64.deb
# RHEL / Fedora / SUSE
sudo rpm -Uvh olivares_0.4_linux_amd64.rpm
# Alpine
sudo apk add --allow-untrusted olivares_0.4_linux_amd64.apk

La instalación crea el usuario y el grupo de sistema olivares (con /usr/sbin/nologin como shell y /var/lib/olivares como directorio de inicio), crea /var/lib/olivares con modo 0750 propiedad de ese usuario y crea /etc/olivares. Los paquetes systemd recargan systemd cuando systemctl está presente; los paquetes OpenRC no habilitan ni arrancan el servicio. No arranca nada — véase lo que el paquete no hace.

En Debian/Ubuntu y RHEL/Fedora/SUSE:

Ventana de terminal
sudo systemctl enable --now olivares

En OpenRC (.apk de este árbol fuente):

Ventana de terminal
sudo rc-service olivares start
# opcional; el paquete no lo hace:
sudo rc-update add olivares default

El token de primer arranque está en /var/log/olivares.log (y en logread si syslogd está en marcha). Los flags adicionales de OLIVARES_EXTRA_ARGS se añaden con el globbing desactivado y separados por espacios; el entrecomillado anidado no se interpreta, y el fichero de entorno no se evalúa como shell.

En el Alpine publicado anteriormente, systemctl no está y ese .apk no tiene unidad OpenRC. Arranca el motor como el usuario de servicio; el token de primer arranque se imprime en stdout:

Ventana de terminal
sudo -u olivares olivares serve --data-dir=/var/lib/olivares \
--listen=:8443 --grpc-listen=:8444 --checkpoint-interval=1h

La unidad systemd empaquetada ejecuta el motor como el usuario no privilegiado olivares con un conjunto de capacidades vacío — no retiene ninguna, ni ambiente ni de acotación — y NoNewPrivileges=true, de modo que nada de lo que lance puede ganar ninguna. Encima lleva ProtectSystem=full (/usr, /boot, /efi y /etc son de solo lectura), PrivateDevices=true, ProtectClock=true, ProtectKernelTunables=true, ProtectKernelModules=true, ProtectKernelLogs=true, ProtectControlGroups=true, RestrictNamespaces=user net mnt (una sesión obtiene su propio namespace de usuario y de red, y el ayudante que mantiene de solo lectura los hooks y la configuración de Git de una carpeta obtiene su propio namespace de montaje, donde el filtro de syscalls permite mount; se deniega cualquier otro tipo), RestrictSUIDSGID=true, RestrictRealtime=true, LockPersonality=true, SystemCallArchitectures=native, un filtro de syscalls @system-service que además descarta @privileged y @resources, y UMask=0027.

La unidad no oculta los directorios personales ni los temporales, y permite memoria ejecutable: fija ProtectHome=false, PrivateTmp=false y MemoryDenyWriteExecute=false. El motor llega a todo lo que los permisos normales de ficheros permiten a la cuenta olivares, incluidos /home, /tmp y /var/tmp, para que las carpetas que elijas para las sesiones sigan accesibles. El confinamiento es por sesión: antes de que arranque cada herramienta de agente o servidor MCP stdio, el motor aplica una política Landlock que le deja escribir en su carpeta de sesión, su home de herramienta y su directorio temporal, y nunca alcanzar el directorio de datos del motor, /etc/olivares ni las credenciales propias de la cuenta del motor. Los runtimes de agentes y MCP sobre Node/V8 necesitan memoria JIT ejecutable; por eso MemoryDenyWriteExecute=false. En un kernel sin Landlock, el motor se niega a iniciar sesiones; olivares doctor indica la causa.

26.10.0 publicó una unidad más estricta: todo el sistema de ficheros de solo lectura salvo el directorio de datos, los directorios personales ocultos, un /tmp privado y sin memoria ejecutable escribible. 26.10.1 la relajó a los valores de arriba. Puedes volver a añadir cualquiera de esos ajustes en un drop-in (systemctl edit olivares). Entonces las carpetas de sesión bajo directorios personales o /tmp y las herramientas basadas en JIT dejan de funcionar, y con el sistema de ficheros de solo lectura cada carpeta de sesión fuera del directorio de datos necesita su propia línea ReadWritePaths=.

En Alpine por defecto esas directivas systemd no aplican a un .apk publicado anteriormente, porque la unidad systemd de ese payload no está en ejecución. Los paquetes .apk construidos desde este árbol fuente corren bajo OpenRC en su lugar: usan la cuenta olivares, escriben el token de primer arranque en /var/log/olivares.log y no implementan las directivas de sandbox de systemd.

Los listeners aceptan conexiones de la red por defecto — --listen=:8443 para HTTP (REST más la consola embebida) y --grpc-listen=:8444 para gRPC, el comodín dual-stack. Esto es un servidor, y lo que lo protege es TLS activado, cero credenciales por defecto y un token de un solo uso. Restríngelo de forma deliberada con OLIVARES_EXTRA_ARGS=--listen=127.0.0.1:8443 --grpc-listen=127.0.0.1:8444 en /etc/olivares/olivares.env — esos flags se añaden después de los de la unidad y gana el último — y pon delante tu propia terminación TLS. Para loopback IPv6 usa --listen=[::1]:8443.

Este es el fallo que conviene conocer de antemano en un host systemd, porque el síntoma no nombra la causa.

Los conectores de primera parte fuera de proceso viajan embebidos en el binario. En el arranque el motor extrae los que necesita a un scratch privado y los ejecuta como subprocesos. Cuando TMPDIR no está definido, el scratch se crea bajo <data-dir>/tmp; solo un directorio de datos no escribible hace que el motor caiga al directorio temporal del sistema. Un TMPDIR explícito siempre gana.

El servicio systemd empaquetado usa por tanto /var/lib/olivares/tmp, no /tmp, por defecto. Comprueba el montaje que realmente sostendrá el scratch ejecutable:

Ventana de terminal
check_scratch_mount() {
target=${1:-/var/lib/olivares}
opts=$(findmnt -no OPTIONS --target "$target") || {
printf '%s\n' "cannot read mount options for $target (missing path or permission)" >&2
return 1
}
[ -n "$opts" ] || {
printf '%s\n' "mount options for $target are unknown" >&2
return 1
}
case ",$opts," in
*,noexec,*) printf '%s\n' 'noexec — set TMPDIR' ;;
*) printf '%s\n' 'exec-capable — nothing to do' ;;
esac
}
check_scratch_mount /var/lib/olivares

Si dice noexec, apunta TMPDIR a un directorio que el usuario olivares pueda escribir y que esté en un montaje capaz de ejecutar:

Ventana de terminal
sudo install -d -o olivares -g olivares -m 0750 /run/olivares-exec-tmp
sudo systemctl edit olivares # creates a drop-in; do not edit the shipped unit
[Service]
Environment=TMPDIR=/run/olivares-exec-tmp
ReadWritePaths=/run/olivares-exec-tmp

Luego reinicia. Si un exec se rechaza con EACCES o ENOEXEC, el error del motor nombra el montaje de extracción y los dos controles de reubicación (TMPDIR y data-dir); no informa un montaje noexec como un conector ausente.

Usa systemctl edit, nunca una edición directa de /usr/lib/systemd/system/olivares.service: ese fichero pertenece al paquete y una actualización lo sustituye.

quickstart es serve con valores por defecto amistosos y un banner guiado. Nunca inventa credenciales por defecto; te señala la consola embebida para crear el primer administrador con un token de un solo uso.

Si ya estás sirviendo bajo la unidad systemd empaquetada, no ejecutes quickstart — el token de configuración de primer arranque se imprime en el journal:

Ventana de terminal
journalctl -u olivares | sed -n '/FIRST-BOOT SETUP/,/========================/p'

Si arrancaste serve en primer plano (Alpine por defecto), el mismo banner está en stdout.

Abre la consola en https://127.0.0.1:8443 (en el primer arranque se genera un certificado autofirmado), presenta ese token y crea el administrador. El token es de un solo uso.

En una estación de trabajo, para mirar sin instalar un servicio, olivares quickstart hace lo mismo en primer plano con --listen/--grpc-listen/--data-dir si necesitas moverlo de los valores por defecto.

Una fuente es de donde el motor ingiere observaciones. Los verbos se parten por lo que cuesta cada uno, y conviene usarlos en ese orden: plan dice qué cambiaría y no escribe nada, validate dice que la configuración es coherente por sí misma sin tocar la red, test abre la fuente de verdad para demostrar que responde, y set aplica. La configuración lleva referencias a secretos (store:<name>), nunca valores.

pgAudit lee el registro de auditoría de PostgreSQL, así que log_path es el único campo obligatorio:

Ventana de terminal
# coherent by itself? (writes nothing, opens no socket)
sudo -u olivares olivares sources validate --name pg-prod --kind pgaudit \
--tenant <your-tenant-id> \
--config log_path=/var/log/postgresql/postgresql.log \
--data-dir /var/lib/olivares
# does it actually answer? (opens the source for real)
sudo -u olivares olivares sources test --name pg-prod --kind pgaudit \
--tenant <your-tenant-id> \
--config log_path=/var/log/postgresql/postgresql.log \
--data-dir /var/lib/olivares
# apply it
sudo -u olivares olivares sources set --name pg-prod --kind pgaudit \
--tenant <your-tenant-id> \
--config log_path=/var/log/postgresql/postgresql.log \
--actor "$(id -un)" --reason "onboard the production audit log" \
--data-dir /var/lib/olivares

Tres cosas de la línea de comandos anterior que no son relleno:

  • --tenant es obligatorio. Una fuente debe nombrar el tenant de negocio al que pertenecen sus observaciones; sin él el comando se niega en vez de adivinar un dueño para tus datos de auditoría.
  • --actor y --reason los exige set, y solo set. Una operación privilegiada fuera de línea tiene que registrar quién la hizo y por qué. validate no necesita ninguno, porque no escribe nada — la asimetría es el punto.
  • format vale por defecto csvlog y follow vale true, así que un despliegue estándar de pgAudit no necesita ninguno de los dos.

Al aplicar se imprime lo que cambió, campo a campo, y se te dice cómo hacer que un motor en ejecución lo recoja sin reiniciar — POST /v1/console/runtime/reload, o un SIGHUP. Bajo la unidad systemd empaquetada eso es sudo systemctl reload olivares. Si arrancaste serve en primer plano, envía SIGHUP a ese proceso.

El usuario de servicio necesita lectura sobre ese fichero de registro; en la mayoría de distribuciones eso significa añadir olivares al grupo adm o postgres — una concesión deliberada tuya, no algo que el paquete haga por ti.

Usa un único actualizador por host. Un host instalado desde un paquete o desde el repositorio se actualiza con su gestor de paquetes (apt, dnf, apk o un paquete más nuevo); olivares upgrade se niega a sustituir el binario que pertenece al paquete.

El gestor de paquetes es el dueño de /usr/bin/olivares en toda instalación por paquete (deb, rpm, apk, AUR). Sustituir ese fichero en el sitio dejaría la base de datos de paquetes describiendo un fichero que ya no existe tal cual, así que olivares upgrade se niega: termina con 2 antes de descargar nada y nombra la vía del paquete. Actualiza con el gestor de paquetes. olivares upgrade --check sigue funcionando; muestra el plan y no cambia nada:

Ventana de terminal
sudo olivares upgrade --check # what would change, without changing anything

Donde ningún gestor de paquetes es dueño del binario (uno colocado por install.sh o a mano), olivares upgrade lo sustituye en el sitio, y las propiedades de seguridad son la razón para usarlo allí: nunca sustituye el binario hasta que el candidato descargado se ha sondeado con éxito mediante exec, conserva una copia de seguridad con marca de tiempo y vuelve a esa copia si el sondeo posterior al intercambio falla. --target <ruta> es la anulación del operador: sustituye el fichero que nombras, incluido /usr/bin/olivares, y desde entonces la base de datos de paquetes ya no coincide con ese fichero.

Tres flags importan para --check y para una ejecución con --target:

  • --endpoint — toma actualizaciones de un repositorio de GitHub que controlas en vez del predeterminado. Es la vía de escape para un espejo o una bifurcación.
  • --bundle — La instalación sin conexión requiere Enterprise. Community verifica un bundle con --bundle --check, sin leer una licencia ni instalarlo.
  • --install-timer — emite un temporizador y un servicio systemd opcionales que comprueban actualizaciones según una programación. Nada lo instala por ti; véase lo que el paquete no hace. Es un generador systemd. En una instalación por paquete se niega: /usr/bin/olivares pertenece al gestor de paquetes, así que --install-timer termina con 2 y no escribe ninguna unidad. Actualiza con el gestor de paquetes (en el appliance de Olivares: systemctl start olivares-appliance-update.service).

Ten en cuenta que la puesta en escena y el sondeo exec ocurren en el directorio de instalación, junto al destino — no en /tmp, así que el montaje noexec comentado arriba no rompe una actualización. Un montaje noexec en el directorio de instalación es otro asunto y deja la versión instalada como no medible; ese caso, los canales de release, el despliegue por etapas y la reversión están en Actualizar y revertir.

El paquete escribe /var/lib/olivares/install-manifest.json. El desinstalador valida el manifiesto completo contra el índice de distribución firmado antes de tocar el servicio o el sistema de ficheros; una ruta inesperada devuelve 2. Inspecciona primero y elige la retención de forma explícita:

Ventana de terminal
sudo olivares uninstall --plan --data-dir /var/lib/olivares
sudo olivares uninstall --preserve --data-dir /var/lib/olivares
sudo olivares uninstall --purge --data-dir /var/lib/olivares --yes

Preserve es la política de retirada del paquete: retiene configuración, datos, registros, claves y su identidad de servicio. En los paquetes systemd el gancho de retirada ejecuta --preserve. En los paquetes .apk OpenRC construidos desde este árbol fuente, el gancho detiene el servicio si está activo, retira la entrada del runlevel por defecto sin fallar si nunca se habilitó, valida el manifiesto completo con --plan y deja que apk elimine los ficheros propiedad del paquete. Los paquetes Alpine publicados anteriormente solo validaban con --plan, porque ese payload no tenía unidad OpenRC que detener. Ejecuta --purge antes de quitar el paquete solo cuando la intención es el borrado. Exige confirmación y borra únicamente rutas indexadas.

Para un traslado de finca, crea primero un olivares dr backup, instala el destino y ejecuta allí olivares dr restore. Los bundles actuales usan hmac-sha256-kek-v1 para autenticar el manifiesto y cada carga bajo tu KEK. Una exportación de un motor más nuevo se rechaza antes de escribir; un bundle pre-v26.9 autenticado por separado necesita --allow-legacy-unsigned de forma explícita. La guía de copia de seguridad y restauración cubre la custodia del KEK y la prueba de continuidad posterior a la importación.

Dicho con claridad, porque un producto de seguridad vago aquí no merece la instalación:

  • No añade un repositorio. No se escribe nada en /etc/apt/sources.list.d, /etc/yum.repos.d ni /etc/apk/repositories. Instalaste un fichero; solo ese fichero se instaló. Las actualizaciones las disparas tú — con un paquete nuevo; olivares upgrade se niega a sustituir un binario que pertenece al paquete.
  • No arranca ni habilita el servicio. Los paquetes systemd recargan systemd cuando systemctl está presente e imprimen systemctl enable --now. Los paquetes OpenRC imprimen rc-service olivares start y no ejecutan rc-update add. Arrancar sigue siendo decisión tuya. Una actualización de un servicio OpenRC que ya está en marcha lo detiene, sustituye los ficheros y lo arranca de nuevo; un servicio inactivo sigue inactivo.
  • Verificar una licencia nunca llama a nadie. Descargar lo que pagaste, sí. La validación de licencia en la compilación abierta es Ed25519 fuera de línea, no hay interruptor remoto de apagado, y ninguna clave de licencia restringe ni degrada esa compilación — la compilación AGPL es la plataforma entera. No hay telemetría obligatoria ni egreso del plano de control por defecto: lo que cruza tu perímetro es lo que configuras para que lo cruce — llamadas a tus API de modelos, las salidas SIEM/webhook que cableas, un proveedor externo de embeddings si aprovisionas uno, y cualquier fuente que un conector consulte (su addr, base_url o endpoint) en el intervalo que fijes.
  • Pero olivares upgrade sí hace una llamada de red, de forma deliberada, cuando lo ejecutas — ese es el punto de una comprobación de actualización, y --check te muestra el plan antes de que se mueva nada. La forma honesta de la promesa es: verificar una licencia nunca llama a nadie; descargar lo que pagaste, sí. Usa --bundle si quieres que la vía de actualización tampoco haga ninguna llamada.
  • Abre un puerto a la red. La unidad enlaza todas las interfaces hasta que tú la amplías.