Del japonés 降ろす (órosu) — «descargar», «desembarcar».

El Problema

Los sistemas de CI son buenos construyendo software y malos entregándolo. Llevar un artefacto de compilación desde un pipeline hasta una máquina de producción suele reducirse a uno de varios patrones conocidos pero frágiles:

  • Claves privadas SSH copiadas en los secretos de CI y repartidas por cada pipeline y repositorio que necesita desplegar
  • Scripts SFTP/rsync copiados de un proyecto a otro, cada uno con sus propios pequeños errores
  • Rutas y permisos codificados que se rompen en cuanto cambia la estructura de un servidor
  • Servidores de producción directamente accesibles desde los runners de CI, ampliando la superficie de ataque con cada pipeline
  • Proliferación de secretos, que convierte la rotación de una sola clave comprometida en una auditoría de todos los repositorios que podrían referenciarla

Nada de esto es específico de una plataforma de en particular — es la forma por defecto de "ejecutar un script en una máquina remota desde un pipeline", y el riesgo se acumula con cada proyecto que la adopta.

Cómo lo Resuelve Orosu

Orosu se instala una vez en la máquina de destino como orosu-server y convierte el despliegue en una solicitud acotada y autenticada en lugar de una sesión SSH abierta:

  1. CI compila la aplicación — un binario, una imagen de contenedor, archivos estáticos, lo que sea que produzca el pipeline
  2. CI dispara una tarea a través de una conexión , adjuntando archivos si es necesario
  3. orosu-server autentica la solicitud usando firmas Ed25519 — sin contraseñas ni secretos compartidos en tránsito
  4. orosu-server ejecuta un script predefinido — uno de un conjunto fijo configurado en el servidor, nunca un comando arbitrario enviado por CI
  5. El script despliega, usando los archivos y argumentos que la tarea adjuntó

Sin SSH directo, sin malabares de credenciales por pipeline y sin más superficie del lado del servidor que los scripts específicos que un operador ha configurado explícitamente.

Instalación

orosu-server y su CLI complementaria orosu-keygen se distribuyen como paquetes de Debian/Ubuntu desde un repositorio apt:

curl -fsSL https://packages.nerdy.pro/NerdyPro.gpg | sudo gpg --dearmor -o /usr/share/keyrings/nerdy-pro.gpg
echo "deb [signed-by=/usr/share/keyrings/nerdy-pro.gpg] https://packages.nerdy.pro/ stable main" | sudo tee /etc/apt/sources.list.d/nerdy-pro.list
sudo apt update
sudo apt install orosu

GitHub Releases también publica binarios precompilados de orosu-server y orosu-keygen directamente, para máquinas donde no se puede añadir un repositorio apt.

Primeros Pasos

Genera un par de claves de cliente con orosu-keygen, desde /etc/orosu:

orosu-keygen --name my-ci-client --private-key-output my-ci-client.key --public-key-output my-ci-client.pub

La clave pública va en la configuración del servidor; la clave privada se convierte en un secreto de CI.

Configura el servidor en /etc/orosu/orosu-server.toml — una dirección de escucha y la clave pública del cliente:

listen:
  tcp: "127.0.0.1:8081"
clients:
  - name: my-ci-client
    secret_file: /etc/orosu/my-ci-client.pub

Un servidor escuchando en localhost normalmente está detrás de un proxy inverso que termina y reenvía las actualizaciones de WebSocket — el README documenta una configuración de nginx para esto.

Define un script que el cliente tiene permitido disparar:

#!/bin/bash
echo "Hello, $1!"
clients:
  - name: my-ci-client
    secret_file: /etc/orosu/my-ci-client.pub
    scripts:
      - name: test-script
        command:
          - "bash"
          - "/etc/orosu/scripts/test.sh"

Dispáralo desde CI con la GitHub Action complementaria, pasando la dirección del servidor y la clave privada del cliente como secretos:

- name: Remotely execute a script
  uses: orosu-ci/orosu@v0
  with:
    address: ${{ secrets.OROSU_SERVER_URL }}
    script: test-script
    key: ${{ secrets.OROSU_CLIENT_KEY }}
    arguments: "from CI pipeline"

Cifrado de Extremo a Extremo

WSS/:termTLS cubre la conexión, pero cuando TLS se termina en un proxy inverso frente a orosu-server — la configuración estándar de arriba — los argumentos del script, los archivos subidos y la salida en streaming quedan en texto plano en ese proxy. Un protocolo opcional de (X25519 + HKDF-SHA256 + ChaCha20-Poly1305) cierra esa brecha:

orosu-keygen --kind server --private-key-output server.key --public-key-output server.pub

La clave pública del servidor se añade a su configuración y se entrega a CI como el parámetro server_key de la Action. La actualización es opcional y aditiva de forma independiente en ambos extremos — un servidor con el cifrado configurado sigue sirviendo a los clientes que omiten server_key exactamente igual que antes, y no se requiere una migración coordinada.

Seguridad

La seguridad es una restricción de diseño de primer orden, no un añadido posterior:

  • Autenticación criptográfica — cada tarea se firma con la clave Ed25519 del cliente; no hay contraseña ni secreto compartido en la conexión que un atacante pueda interceptar.
  • Un conjunto cerrado de acciones — CI solo puede disparar scripts que un operador haya predefinido explícitamente en el servidor. No existe una ruta desde una tarea de CI hasta un comando de shell arbitrario.
  • Manejo reforzado de adjuntos — los nombres de entrada de los zip se validan contra path traversal, y tanto el número de entradas como el tamaño descomprimido total tienen límite, de modo que un adjunto manipulado o desmesurado no puede salirse de su directorio de extracción ni agotar el disco.
  • Cifrado en profundidad — el protocolo opcional de cifrado de extremo a extremo verifica ataques de low-order-point en su intercambio X25519, además de la confidencialidad que ya proporciona.
  • Permisos de archivo seguros por defectoorosu-keygen escribe los archivos de claves privadas con permisos 0600 sin importar el umask vigente.

Estas protecciones llegaron en la versión 0.7.0 como una actualización directa — sin cambios de configuración, CLI ni protocolo. Consulta CHANGELOG.md para el historial completo de versiones.

Licencia

Orosu está licenciado bajo Apache-2.0.

Los pasos improvisados de despliegue por SSH/SCP en pipelines de CI — claves privadas en secretos, scripts rsync copiados y servidores de producción directamente accesibles. CI dispara una tarea autenticada por WebSocket en lugar de abrir una sesión SSH.
Cada cliente de CI tiene un par de claves Ed25519. La clave pública se registra en la configuración del servidor; la privada se guarda como secreto de CI y se usa para firmar las solicitudes de tareas. El servidor solo ejecuta scripts explícitamente configurados para ese cliente.
No. orosu-server solo ejecuta scripts predefinidos configurados de antemano en orosu-server.toml. Una tarea de CI selecciona un script por nombre y pasa argumentos y adjuntos — no puede proporcionar un comando arbitrario.
Por defecto la conexión está cubierta por WSS/TLS, normalmente terminado en un proxy inverso frente a orosu-server. Se puede habilitar una capa opcional de cifrado de extremo a extremo (X25519 + ChaCha20-Poly1305) para que los argumentos del script, los archivos y la salida sigan siendo confidenciales incluso para ese proxy.
A través de un repositorio apt (packages.nerdy.pro) para Debian/Ubuntu, o como binarios precompilados adjuntos a GitHub Releases para orosu-server y el CLI orosu-keygen.
Solicitudes firmadas con Ed25519, un conjunto cerrado de scripts definidos en el servidor que CI puede disparar, protección contra path traversal y límites de tamaño en la extracción de adjuntos, protección contra ataques low-order-point en el cifrado opcional de extremo a extremo, y permisos de archivo seguros por defecto para las claves generadas.