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.
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.
- 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:latestde Docker Hub, en x86_64 y aarch64. - En esa misma VM,
apt install postgresqlinstala PostgreSQL 17 sin cambios, y atiende cientos de transacciones por segundo sobre el disco cifrado de Rinux.
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.
fsync del disco- El corte en la prueba
- Con
pgbenchescribiendo, 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 depgbenchcuadran ypg_amcheckno 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_amchecklimpio. - 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,pgbenchescala 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.
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
fsyncque 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.
| Prueba | Checks | x86_64 | aarch64 |
|---|---|---|---|
| boot | 1 | pasa | pasa |
| mm | 8 | timer del host | pasa |
| elf-static | 1 | pasa | pasa |
| domains | 8 | pasa | pasa |
| vfs | 10 | pasa | pasa |
| proc | 17 | pasa | pasa |
| signals | 11 | pasa | pasa |
| tty | 11 | pasa | pasa |
| dynamic | 15 | pasa | pasa |
| alpine | 21 | pasa | pasa |
| threads | 15 | pasa | pasa |
| ipc | 18 | pasa | pasa |
| events | 15 | pasa | pasa |
| sockets | 12 | pasa | pasa |
| system | 15 | pasa | pasa |
| systemd | 15 | pasa | pasa |
| net | 3 | pasa | pasa |
| inet | 17 | pasa | pasa |
| gce | 4 | pasa | no aplica |
| blkw | 3 | pasa | pasa |
| rfs | 9 | pasa | pasa |
| crypt-persist | 13 | pasa | pasa |
| tpm | 11 | pasa | pasa |
| loader | 1 | pasa | pasa |
| update | 18 | pasa | pasa |
| load | 2 | pasa | pasa |
| persist | 27 | pasa | pasa |
| pg | 15 | pasa | pasa |
| lockup | 2 | pasa | pasa |
| unstable | 13 | pasa | pasa |
| health | 6 | pasa | pasa |
| watchdog | 1 | pasa | pasa |
| syn | 1 | pasa | pasa |
| keys | 12 | pasa | pasa |
| hv | 3 | pasa | pasa |
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.
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 aarch64rinux-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 unsaferinux-frame
Paginación, interrupciones, contexto de CPU, MMIO y DMA, expuestos al kernel como tipos seguros.
el único crate con unsafeFirmware
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 fuenteMá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.