Rinux

Binarios de Linux,
sin recompilar.
Otro kernel debajo.

Rinux es un kernel nuevo, escrito en Rust y pensado para servidores, que ejecuta binarios de Linux ya compilados, tal cual, dentro de dominios: cada uno con su memoria, su CPU, su raíz y sus fallos. Cuando algo cae dentro de un dominio, el resto de la máquina no se entera.

Haz clic en un dominio para provocarle un fallo.

0fallos contenidos
0 skernel en pie

Rinux es el sistema operativo, no algo que corre encima de uno.

Arranca directo en el servidor o en la VM de la nube, en lugar de Linux.

Mascota de Rinux: un rinoceronte de smoking
No es Docker
Docker necesita un Linux debajo y sus contenedores comparten ese kernel. Aquí no hay Linux: el kernel es Rinux. Toma imágenes de Docker tal cual y corre cada una en un dominio aislado por el propio kernel.
No es una máquina virtual
No hay un Linux invitado por cada carga. Un solo kernel aísla a todos los dominios.
Sí es compatible con Linux
Los programas (Debian, systemd, apt, sshd) no saben que no están sobre Linux, porque Rinux habla su mismo idioma de llamadas al sistema.

Esto ya corre.

Debian 13, desde una imagen OCI verificada capa por capa con SHA-256, arranca con systemd en un dominio de Rinux, en una VM de Google Cloud. Por SSH, apt instala paquetes y curl habla HTTPS. Todo lo que hacen por debajo lo resuelve Rinux.

  • rinux> es la consola de rinuxd, el controlador del nodo. Crea, configura y arranca dominios.
  • root@rinux-1 es el shell de Debian dentro del dominio, con su propia raíz y procesos. El nombre es el del nodo, que da el DHCP de la nube.
  • La salida es la de una sesión real en x86_64, copiada del puerto serial de la VM y de SSH; se omiten líneas del arranque de systemd y de apt.
  • La red del nodo parte cerrada y abre únicamente lo que se le concede a cada dominio: aquí, el puerto 22 y la salida. También corre alpine:latest de Docker Hub, en x86_64 y aarch64.
  • En esa misma VM, apt install postgresql instala PostgreSQL 17 sin cambios, y atiende cientos de transacciones por segundo sobre el disco cifrado de Rinux.
Google Cloud n2-standard-2, 2 CPUs, 8 GiB

PostgreSQL, con cortes de energía de verdad.

Una base de datos es la prueba más dura para un kernel: cada transacción confirmada espera un fsync, y ese dato tiene que estar ahí después de cualquier apagón. PostgreSQL 17 de Debian corre sin modificar en un dominio de Rinux, y le cortamos la energía en plena carga.

200 / 200transacciones confirmadas que siguen ahí después de cortar la energía con carga en curso
368transacciones por segundo con 50 clientes en Google Cloud, sin una sola fallida
7,5 mspor transacción con un cliente: casi todo es el fsync del disco
El corte en la prueba
Con pgbench escribiendo, se confirman 200 transacciones marcadas y se apaga la máquina virtual sin aviso. Al volver, el disco reaplica su registro y PostgreSQL su WAL. Las 200 marcas están, los saldos de pgbench cuadran y pg_amcheck no encuentra corrupción. En x86_64 y aarch64.
Colgado a propósito
Se congela el proceso principal de PostgreSQL: el puerto sigue abierto pero nadie responde. La prueba de vida del kernel lo detecta, reinicia el dominio entero y PostgreSQL vuelve con las 200 marcas y los saldos cuadrados. En Google Cloud volvió en menos de un minuto.
El corte en la nube
Lo mismo en Google Cloud, con un reset duro de la VM desde la consola: 200 de 200 marcas, saldos cuadrados sobre casi 80.000 transacciones y pg_amcheck limpio.
Lo que pidió PostgreSQL
Hacerlo andar sacó a la luz siete fallas del kernel, cada una con su prueba: memoria compartida System V, E/S vectorial, montajes apilados, red local por dominio, contabilidad de memoria compartida y una lectura del disco que fallaba bajo carga pesada.
Medido en Google Cloud
n2-standard-2 con disco pd-balanced, pgbench escala 10: 133 transacciones por segundo con 1 cliente, unas 314 con 8 y 368 con 50. Los números de referencia son los de la nube, no los de una máquina de desarrollo.

Hecho para que nadie tenga que ir a arreglarlo.

Rinux apunta a nodos a los que no se puede ir: la red parte cerrada y todo pasa por el plano de control. Un nodo así tiene que volver solo de lo que lo deje sin servicio.

129 msdesde que entra el kernel hasta que está listo para trabajar
40 sdesde que arranca el kernel hasta entrar por SSH a Debian, con PostgreSQL y el disco cifrado
18 sde una falla a SSH otra vez: el dominio de Debian se reinicia entero, solo

Medido en Google Cloud, n2-standard-2 con disco pd-balanced. El canal de control responde SSH a los 11 segundos del arranque.

Disco que sobrevive al apagón
Sistema de archivos propio con copy-on-write y registro de intención: un corte en cualquier escritura deja el último estado confirmado, nunca una mezcla. Cada fsync que volvió está en el disco.
Cifrado por dominio
Cada volumen va cifrado con su propia llave, sellada en el TPM del nodo. Borrar un dominio destruye su llave, y sus datos quedan ilegibles para siempre.
Actualizaciones con vuelta atrás
El kernel nuevo se instala en la otra ranura del disco de arranque. Si no arranca bien dos veces, el cargador vuelve solo al anterior. Si arranca pero se cae tres veces antes de los 10 minutos, también.
Detector de bloqueo
Una CPU que pasa 20 segundos atrapada en el kernel, con o sin interrupciones, se detecta desde el propio kernel. Deja el motivo en el log y reinicia el nodo en lugar de quedar colgado para siempre.
Prueba de vida por dominio
El kernel verifica cada 10 segundos que el servicio de un dominio siga aceptando conexiones. Uno colgado, que conserva el puerto pero no responde, se reinicia según la política del dominio. Uno detenido a propósito no se toca.
Watchdog en dos niveles
Si el kernel entero se congela, el watchdog de hardware de la máquina virtual la reinicia. Y cada dominio tiene su propio /dev/watchdog: systemd lo alimenta, y si se cuelga, el dominio vuelve a arrancar. Funciona en cualquier nube.
Un canal de control aparte
Un segundo SSH, en un dominio independiente, sigue respondiendo cuando Debian no lo hace, y desde ahí se lo reinicia. fail2ban bloquea en el propio kernel las direcciones que insisten, en todos los puertos del nodo.
Escaneos que no cierran la puerta
Miles de conexiones que se abren y nunca se completan, como las de cualquier escáner de internet, no dejan sin SSH al nodo: las que quedan a medias vencen, y la más vieja cede su lugar.
Memoria sin sorpresas
Sin sobrecompromiso de memoria y sin un proceso que mate programas al azar: pedir de más da un error en el momento de pedir, siempre el mismo.

Dónde corre.

Rinux arranca como el sistema operativo de la máquina virtual. Todavía no está publicado: el código y las imágenes salen con la primera versión, bajo licencia MPL-2.0.

Google Cloud
Corre hoy en una VM n2-standard-2, con disco de arranque firmado, actualizaciones con vuelta atrás y PostgreSQL atendiendo carga. Las series nuevas (C3, C4, N4) necesitan el driver gVNIC, que viene.
Proxmox, QEMU/KVM y libvirt
Imagen lista: tres discos qcow2 y un TPM virtual, con el que se cifra el disco raíz. Se prueba arrancando, instalando Debian, apagando y volviendo a arrancar, en x86_64 y en aarch64.
AWS y Azure
En camino. AWS necesita el driver de red ENA; Azure, los dispositivos de Hyper-V.
Llaves desde la nube
La imagen no trae llaves ni contraseñas. En Google Cloud, AWS y Azure las toma del servidor de metadatos, como cualquier imagen de nube.

Cada afirmación tiene una prueba que arranca la máquina.

Nada cuenta como hecho hasta que una prueba arranca Rinux en QEMU, en x86_64 y en aarch64, corre programas Linux reales dentro de un dominio y verifica el resultado desde adentro.

245 / 375llamadas al sistema de Linux 6.12 implementadas en x86_64, cada una con su estado escrito
214 / 318en aarch64, con la tabla de números propia de esa arquitectura
35pruebas de arranque completo, en las dos arquitecturas
Las pruebas, en el orden en que se fueron sumando
PruebaQué verificaChecksx86_64aarch64
bootUEFI, sobre firmado, rinuxd en modo usuario, apagado1pasapasa
mmframes, heap, paginación, fallos, scheduler, timer8timer del hostpasa
elf-static64 procesos estáticos en 4 CPUs1pasapasa
domainsaislamiento de fallos, capabilities, límites de memoria y CPU8pasapasa
vfstmpfs, devfs, procfs, syscalls de archivos10pasapasa
procfork, execve, wait4, pipes, posix_spawn, /proc/self/exe17pasapasa
signalsmanejadores, máscaras, marcos de señal de Linux11pasapasa
ttyterminales, pseudoterminales, control de trabajos11pasapasa
dynamicBusyBox dinámico de Alpine como init15pasapasa
alpineimagen OCI desde un disco virtio, digest alterado rechazado21pasapasa
threadspthread, futex, copy-on-write, páginas perezosas, TLB, mremap, stack que crece15pasapasa
ipcmmap compartido, FIFOs, permisos, memoria compartida y semáforos System V, E/S vectorial, AIO nativo18pasapasa
eventsepoll, eventfd, timerfd, signalfd, temporizadores POSIX15pasapasa
socketsAF_UNIX, paso de descriptores, credenciales, netlink12pasapasa
systemmontajes apilados, opciones de tmpfs, sysfs, cgroup2, inotify15pasapasa
systemdDebian 13 con systemd como init, journal, login, nombre del nodo, SSH solo con llave, memoria según el nodo, hora de inicio de los procesos, watchdog, avisos de licencia15pasapasa
netvirtio-net, DHCP, ARP, ICMP, TCP3pasapasa
inetsockets TCP y UDP, red cerrada por defecto, DNS, netlink, entrantes, red local propia de cada dominio, salida solo a metadatos17pasapasa
gceimagen de Google Cloud: PCI sin MCFG, virtio legacy, login, SSH y actualización real4pasano aplica
blkwescritura en disco por virtio-blk, virtio-scsi y NVMe, verificada desde el host3pasapasa
rfssistema de archivos propio en disco, revisado desde el host al apagar9pasapasa
crypt-persistvolúmenes cifrados que sobreviven reinicios y se destruyen con su llave13pasapasa
tpmllaves selladas en el TPM, en tres arranques11pasapasa
loadercargador propio con ranuras A/B1pasapasa
updateactualización en caliente, firma, kernel que no arranca y vuelta atrás sola18pasapasa
load128 procesos escribiendo a la vez en un volumen cifrado2pasapasa
persistDebian instalado en disco: lo cambiado sobrevive al reinicio27pasapasa
pgPostgreSQL 17 con corte de energía en plena carga, y colgado a propósito15pasapasa
lockupuna CPU atrapada se detecta y el nodo se reinicia solo2pasapasa
unstableun kernel que se cae tres veces vuelve solo al anterior13pasapasa
healthun servicio colgado se reinicia; uno sano o detenido no; watchdog de cada dominio6pasapasa
watchdogel kernel entero congelado: el watchdog de hardware reinicia la máquina1pasapasa
synun escaneo de conexiones a medias no deja el puerto sin atender1pasapasa
keysllaves SSH desde el servidor de metadatos, usuarios, cambios en caliente12pasapasa
hvimagen para Proxmox y KVM: sin TPM lo explica; con TPM instala cifrado y vuelve a arrancar3pasapasa

Todo el código inseguro vive en un solo lugar.

Rust no impide tocar el hardware; lo obliga a declararlo. En Rinux, todo lo que necesita unsafe (tablas de páginas, registros de dispositivos, DMA, cambio de contexto) está en un único crate con sus invariantes escritas. El resto del kernel tiene prohibido usarlo.

6.512 líneas en rinux-frame, con unsafe 34.579 líneas en el kernel, con #![forbid(unsafe_code)]

Dominios

Programas Linux sin modificar, con musl o glibc, y rinuxd, el controlador del nodo. Corren en modo usuario.

ring 3 en x86_64, EL0 en aarch64

rinux-kernel

Memoria virtual, scheduler multiprocesador, dominios y capabilities, sistema de archivos, sockets, red TCP/IP, señales y la personalidad Linux que traduce cada syscall.

ring 0 / EL1, sin unsafe

rinux-frame

Paginación, interrupciones, contexto de CPU, MMIO y DMA, expuestos al kernel como tipos seguros.

el único crate con unsafe

Firmware

UEFI arranca una sola imagen, RINUX.EFI. El kernel descubre la máquina por ACPI y verifica la firma Ed25519 del sobre de arranque antes de ejecutar nada.

x86_64 y aarch64 desde la misma fuente

Más fuerte que un contenedor, más liviano que una máquina virtual.

Un dominio no es un truco de espacios de nombres sobre un kernel compartido. Es un objeto del propio kernel, que posee sus recursos y responde por sus fallos.

Capabilities con generación
Cada permiso apunta a un objeto y a su generación. Cuando un dominio se reinicia, su generación avanza y todo permiso viejo deja de servir.
Límites que se cumplen
CPU y memoria con cuotas que aplican el scheduler y el asignador. Pasarse de memoria es un error del dominio, nunca del nodo.
Perfil de syscalls
Cada dominio tiene su lista de llamadas permitidas. Lo que no está se niega con el error que Linux daría y queda en la traza del kernel.
Raíz propia en cada vida
Capas OCI verificadas, procfs, sysfs, cgroups y dispositivos propios. Cada arranque del dominio parte de una raíz nueva.
Política de fallo
Detener, reiniciar o avisar a rinuxd. Un proceso que falla dentro de un dominio termina; el kernel y los demás dominios siguen. Con una prueba de vida, también un servicio colgado cuenta como falla.
Red local propia
Cada dominio tiene su localhost: sus programas hablan entre sí por 127.0.0.1 sin abrir nada hacia afuera, y ningún dominio alcanza la red local de otro.
Una sola imagen
Kernel, controlador y programas de arranque en un RINUX.EFI firmado por arquitectura. Se arranca, se verifica y toma la máquina.

La base de nuestro stack.

Cada pieza corre en su propio dominio, con su propia autoridad, en el mismo nodo.

  • Hullorquesta cargas sobre dominios Rinux.
  • Cóndorproxy inverso, con colas de red directas.
  • OxideStorealmacenamiento de objetos y registro de imágenes.
  • Melangerecibe la telemetría de cada nodo y cada dominio.
  • Loaproxy de PostgreSQL delante de bases que corren en dominios.
  • Lumoservicio nativo en su propio dominio.