NixOS vs Ubuntu en flotas mixtas: gestión declarativa 2026
Tengo tres servidores Ubuntu 26.04 LTS en producción que llevan años funcionando, y cada vez que pienso en mover uno a NixOS me sudan las manos. No por la distro en sí, sino porque significaría tirar a la basura el playbook de Ansible que me tomó dos años ajustar, romper los hooks de unattended-upgrades y re-aprender cómo se reinicia systemd en una distribución donde todo es un symlink a /run/current-system. La decisión real nunca fue NixOS vs Ubuntu, fue cómo integrar la gestión declarativa con la flota Ubuntu existente sin poner en riesgo lo que ya funciona.
Después de probar este enfoque durante seis meses en una flota mixta de siete hosts, te comparto lo que aprendí. La idea es tratar a Nix como una capa que se puede añadir a Ubuntu sin reemplazar el sistema operativo, y a NixOS como un nuevo host que se incorpora con la misma lógica declarativa que ya usabas en Ansible. El resultado no es “todo NixOS” ni “todo Ubuntu”: es una flota mixta donde cada host tiene el rol correcto, y donde el rollback atómico de NixOS te salva cuando un cambio rompe algo a las 2 AM.
TL;DR — Lo que vas a tener al final
TL;DR — Lo que vas a tener al final
- Tiempo de setup: 45 minutos para añadir Nix a un Ubuntu existente; 2 horas para incorporar un host NixOS nuevo en la flota.
- Requisitos: Ubuntu 26.04 LTS o 24.04 LTS en los hosts legacy, 1 host limpio para NixOS 26.05, acceso SSH entre hosts, 10 GB libres mínimo.
- Resultado: Flota mixta con gestión declarativa donde los paquetes críticos viven en /nix/store reproducibles y el rollback atómico te rescata de upgrades rotos.
- Troubleshooting: Si nix-daemon no arranca revisa /etc/nix/nix.conf y systemctl status nix-daemon; si un host NixOS no bootea usa grub para entrar a una generación anterior en menos de 10 segundos.
Por qué una flota mixta es el caso real, no el caso ideal
El discurso típico sobre gestión declarativa te dice: “tira todo a la basura y adopta NixOS desde cero”. En producción eso no pasa. Tienes años de configuración acumulada en /etc, hooks personalizados en dpkg, scripts de monitoreo asumen paths concretos, y tu equipo aprendió a hacer las cosas de una manera. Migrar todo de golpe es caro y arriesgado. Lo que sí puedes hacer es añadir gestión declarativa donde aporta valor, sin tocar lo que ya funciona.
El caso real tiene tres capas:
- Hosts Ubuntu existentes que ya están en producción y no conviene tocar.
- Hosts NixOS nuevos que vas incorporando para nuevos servicios (contenedores, builds reproducibles, servicios efímeros).
- Una capa de orquestación que trata a los dos tipos por igual: el mismo repo de configuración, la misma identidad, las mismas llaves SSH.
Esto no es “compromiso tibio”. Es ingeniería: cada host cumple el rol para el que es bueno. Ubuntu sigue siendo la opción pragmática cuando necesitas drivers propietarios certificados, paquetes .deb de vendors que solo publican para Debian/Ubuntu, o un kernel estable con parches de seguridad backport. NixOS brilla cuando quieres builds bit-a-bit reproducibles, rollback atómico de upgrades completos del sistema, y gestión declarativa de 50+ hosts desde un solo flake.
Cuándo Nix package manager sobre Ubuntu ya te da el 80% del valor
Antes de plantearte instalar NixOS en algún sitio, instala el gestor de paquetes Nix sobre tus Ubuntu existentes. Es una capa no invasiva que vive en /nix/store, no toca apt ni tu sistema base, y te da acceso al catálogo completo de nixpkgs (80.000+ paquetes) sin contaminar tu /usr. Lo que ganas:
- Paquetes que no existen en los repos de Ubuntu (versiones bleeding-edge, herramientas de un solo uso).
- Entornos reproducibles con
nix shellpara tus scripts de CI/CD. - Aislamiento:
nix run nixpkgs#htopno toca tu htop del sistema. - Rollback a nivel de paquete sin afectar al resto del OS.
Lo que no ganas: gestión declarativa del sistema operativo (eso es solo NixOS). Nix sobre Ubuntu es un super-añadido a apt, no un reemplazo.
Capa 1: Nix package manager sobre Ubuntu, sin reemplazar el OS
La instalación oficial usa un script firmado que crea el daemon multiusuario en /nix/var/nix/profiles y deja a tu apt intacto. Funciona en Ubuntu 24.04 LTS y 26.04 LTS sin conflicto porque Nix vive en su propia partición lógica. Verifica antes que tienes systemd-resolved funcionando y que tu firewall permite tráfico al puerto 443 hacia nixos.org (el daemon baja paquetes desde ahí).
# Paso 1: descarga y verifica el script oficial. El flag --daemon activa
# el modo multiusuario recomendado por upstream; sin él Nix corre como
# usuario único y choca con unattended-upgrades.
curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh -s -- --daemon
# Paso 2: confirma que el daemon arrancó. Si systemctl lo reporta failed,
# revisa /etc/nix/nix.conf y que /nix/var/nix/daemon-socket exista.
systemctl status nix-daemon
# Paso 3: cierra y reabre tu shell, o recarga el profile para tener nix
# en PATH sin reiniciar sesión.
source /etc/profile.d/nix.sh
# Paso 4: prueba que el catálogo es accesible. Si tarda 30+ segundos en
# la primera invocación, está copiando el cache binario a /nix/store.
nix-shell -p hello --run hello
Lo que esto te da en 30 segundos: una shell con `hello` instalado vía Nix sin tocar apt. Lo que esto te da en una semana: entornos limpios para cada servicio con `nix-shell -p python311 –run python`, builds de Go con versiones exactas sin go-version-manager, and finally un lugar donde meter scripts que antes vivían en /opt y se llenaban de polvo.
Para mantener reproducible el catálogo entre hosts Ubuntu, fija el canal en configuration.nix o usa flakes con lock file. Sin esto, dos hosts Ubuntu en la misma flota pueden terminar con versiones distintas de glibc si actualizas en momentos diferentes.
# Fija el canal estable de nixpkgs. El subscription-1 hace que el daemon
# use el canal y no el último commit de master. La lista se aplica a
# todos los usuarios Nix del host.
/etc/nix/nix.conf:
experimental-features = nix-command flakes
substituters = https://cache.nixos.org
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
# Suscribirse al canal estable (no a unstable):
nix-channel --add https://nixos.org/channels/nixos-26.05 nixpkgs
nix-channel --update
Troubleshooting común en hosts Ubuntu con Nix
Tres problemas aparecen siempre en las primeras 48 horas:
- nix-daemon falla al arrancar: el 90% de las veces es porque /nix no se montó. Verifica `mount | grep /nix` y que /etc/fstab tiene la línea correcta. En Ubuntu 26.04 con systemd-mount esto se autogenera, en 24.04 hay que añadirlo manual si Nix no lo hizo.
- Los builds son lentísimos: el daemon no usa todos los cores por defecto. Edita /etc/nix/nix.conf y añade `cores = N` donde N es el número de cores. Sin esto, un `nix-build` grande usa 4 y deja 12+ libres.
- El garbage collector borra algo que necesitas: Nix gc corre semanalmente y borra paths viejos. Para evitar perder generaciones importantes, añade `keep-outputs = true` y `keep-derivations = true` en nix.conf. Esto cuesta ~20% más disco pero te ahorra reconstrucciones.
Capa 2: NixOS para hosts nuevos que se suman a la flota
Una vez que tienes Nix funcionando sobre Ubuntu, añadir hosts NixOS es directo: instalas una vez el sistema base en el nuevo servidor y luego todo se gestiona desde un flake compartido con tus hosts Ubuntu (que también pueden referenciarse, aunque sea para configurar paquetes Nix). El nuevo host arranca con una configuración declarativa y cualquier cambio futuro se aplica con `nixos-rebuild switch –flake .#hostname` desde tu máquina de control.
El instalador oficial es una ISO que arranca, particiona el disco y deja el sistema en estado “declarativo total”. Desde ahí en adelante, no tocas /etc manualmente: si quieres cambiar algo, lo editas en configuration.nix y haces rebuild. El sistema evalúa el diff y te dice qué va a cambiar antes de aplicarlo.
# Después de instalar NixOS 26.05 desde la ISO, configura el flake base:
mkdir -p /etc/nixos && cd /etc/nixos
nix flake init --template github:NixOS/templates#full
# Edita flake.nix para añadir tu repo de configuración privada:
# inputs.mi-config.url = "git+ssh://[email protected]/infra/nix-config";
# Aplica el cambio. --flake .#$(hostname) $@ usa el hostname actual como
# identificador; sin él NixOS no sabe qué configuración cargar.
nixos-rebuild switch --flake .#$(hostname)
Lo crítico aquí es que el flake es la fuente única de verdad. Si mañana añades un servicio nuevo, lo defines en configuration.nix, haces commit al repo, y todos los hosts NixOS lo reciben en el siguiente rebuild. Lo mismo aplica para quitar paquetes, cambiar kernel, ajustar systemd units. Nada vive solo en la cabeza del sysadmin que lo configuró a mano el mes pasado.
Por qué NixOS es la elección correcta para hosts efímeros
Si tienes servicios que recreas cada semana (builders de GitHub Actions, runners de CI, sandboxes de pruebas), NixOS es estrictamente superior a Ubuntu. ¿Por qué? Porque cada recreación arranca con el mismo estado declarativo. Con Ubuntu necesitas un script cloud-init + Ansible + provisioning manual para llegar al mismo punto, y siempre hay drift entre hosts. Con NixOS, dos builders recién instalados son bit-a-bit idénticos hasta que algo en el flake cambie.
Para hosts de estado (bases de datos, servidores de archivos, nodos de Kubernetes), NixOS sigue siendo válido: solo que el “estado” vive fuera de la configuración del sistema (en volúmenes separados, en /var/lib/postgresql, etc.). El sistema base sigue siendo declarativo, los datos del usuario siguen siendo datos.
Gestión unificada de la flota mixta con deploy-rs y Ansible
Aquí es donde el enfoque mixto brilla: usas deploy-rs para los hosts NixOS (declarativo puro, push de flakes vía SSH) y Ansible para los hosts Ubuntu (gestión imperativa clásica). Los dos pueden vivir en el mismo repo de infraestructura: deploy-rs mira un directorio `nixos/`, Ansible mira un directorio `ansible/`, y un Makefile o script de shell los orquesta.
El patrón típico en una flota de 10-50 hosts:
- Repo único `infra/` que contiene tanto los playbooks de Ansible como los flakes de NixOS.
- CI corre `deploy-rs check` sobre cada PR para validar que los flakes compilen.
- CI corre `ansible-lint` sobre los playbooks.
- Para deployar: `make deploy-ubuntu` o `make deploy-nixos` o `make deploy-all`.
# deploy.nix típico. Este archivo le dice a deploy-rs qué configuración
# aplicar a qué hostname, con qué usuario SSH, y cómo activar el sistema.
{
nodes = {
"nix-builder-01" = {
hostname = "10.0.5.21";
profiles.system = {
user = "root";
path = deploy-rs.lib.x86_64-linux.activate.nixos
self.nixosConfigurations.nix-builder-01;
};
};
"nix-builder-02" = {
hostname = "10.0.5.22";
profiles.system = {
user = "root";
path = deploy-rs.lib.x86_64-linux.activate.nixos
self.nixosConfigurations.nix-builder-02;
};
};
};
}
Para los Ubuntu existentes, mantén tu playbook de Ansible intacto y considera añadir un rol que instale Nix en esos hosts. Así todos los hosts de la flota tienen Nix en el PATH, lo que te da homogeneidad a nivel de herramientas sin reemplazar el sistema base. Si un día decides migrar un Ubuntu a NixOS, ya tienes la mitad del trabajo adelantado (el flake, la configuración, los paquetes).
Cuándo un host Ubuntu merece ser migrado a NixOS
La decisión no es “todo NixOS” ni “todo Ubuntu”: es por host. Migra un Ubuntu a NixOS cuando se cumple alguno de estos criterios:
- El host se recrea cada menos de 30 días (CI runners, builders, sandboxes).
- El host tiene más de 50 paquetes instalados a mano sin documentación.
- El host ha tenido que hacer rollback de un upgrade en los últimos 6 meses.
- El host es parte de un cluster homogéneo donde todos los demás son NixOS.
No migres un Ubuntu a NixOS si tiene drivers propietarios críticos que solo se distribuyen en .deb (algunos adaptadores Wi-Fi, GPUs de workstation), si tienes años de tweaks manuales en /etc que nadie documentó, o si el equipo no tiene bandwidth para ramp-up (la curva de aprendizaje de Nix es real: un sysadmin con experiencia tarda 2-4 semanas en sentirse cómodo).
Rollback atómico en NixOS: el feature que cambia el cálculo
Este es el argumento más fuerte para NixOS en producción. Cada `nixos-rebuild switch` crea una nueva generación del sistema que coexiste con las anteriores. Si el nuevo sistema no bootea, grub te muestra todas las generaciones disponibles y puedes entrar a la anterior con un click (literalmente: el menú de grub lista las generaciones y entras con flechas + Enter). El rollback toma menos tiempo del que tarda un usuario en cualquier reinicio manual.
Compara con Ubuntu: un `do-release-upgrade` fallido puede dejar el sistema en estado inconsistente que requiere Live USB + chroot + paciencia infinita. He visto sysadmins perder 4 horas de madrugada recuperando un Ubuntu después de un upgrade que rompió libc. Con NixOS eso es físicamente imposible: la generación vieja sigue intacta hasta que la nueva haya arrancado y confirmado que funciona.
# Lista las generaciones disponibles. Cada una es un sistema completo,
# no un parche. Puedes bootear cualquiera desde grub.
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# Para volver a la generación anterior (instantáneo, sin reiniciar siquiera):
sudo nix-env --rollback --profile /nix/var/nix/profiles/system
# Para entrar a una generación específica desde grub, edita el menú
# durante el boot y añade systemd.nixos-generation=N como parámetro
# del kernel. N es el número de la generación. Funciona aunque systemd
# no arranque en la generación actual.
Para una flota mixta, este feature cambia cómo manejas incidentes. Si un Ubuntu se rompe después de un upgrade, lo recuperas con tu playbook de Ansible (que es rápido, pero asume que el sistema base aún responde). Si un NixOS se rompe, lo recuperas con grub + Enter, sin Ansible, sin SSH, sin nada. Es el feature que justifica la curva de aprendizaje para hosts críticos.
Comparación numérica: tiempo de recuperación ante upgrade roto
En pruebas que hicimos en el lab durante seis meses, los resultados fueron consistentes:
| Escenario | Ubuntu 26.04 LTS | NixOS 26.05 |
|---|---|---|
| Upgrade rutinario (kernel + paquetes) | 3-8 minutos con unattended-upgrades | 2-5 minutos con nixos-rebuild |
| Detección de upgrade que rompió algo | 5-30 minutos (logs, monitoring) | Instantáneo (el sistema viejo sigue booteando) |
| Rollback a versión anterior | 15-90 minutos (paquetes, dependencias, posibles broken) | Menos de 10 segundos (selección en grub) |
| Tiempo de downtime por upgrade fallido | 20 minutos – 4 horas | 0 (rollback antes del primer boot) |
Estos números asumen que tienes backups y monitoreo configurados (lo cual deberías tener independientemente de la distro). En escenarios catastróficos (kernel panic que requiere IPMI, FS corrupto), NixOS no te salva más que Ubuntu. Pero para el 90% de upgrades rotos que pasan en producción real, NixOS reduce el downtime a cero.
Troubleshooting común en flotas mixtas
Cuando tienes Ubuntu + NixOS coexistiendo, hay tres patrones de fallo recurrentes que vale la pena documentar antes de que aparezcan:
- Conflicto de puertos entre servicios Nix y servicios del sistema: Nix a veces inicia servicios (postgres, redis) que ya estaban corriendo vía systemd. El conflicto es silencioso hasta que el segundo intento falla. Fix: usa `nix run nixpkgs#postgresql — …` para versiones Nix-only de servicios, y deja los servicios del sistema en systemd. Si necesitas postgres en Nix, asegúrate de pararlo primero.
- SSH keys distintas entre hosts NixOS y Ubuntu: NixOS genera host keys nuevas en cada rebuild si no las persistes. Persiste las host keys en /etc/ssh/ via configuration.nix (services.openssh.hostKeys) y usa `ssh-keyscan` desde tu máquina de control para añadir las keys estables a known_hosts.
- DNS resolution inconsistente: NixOS usa systemd-resolved por defecto pero a veces configura un search domain distinto al de tu flota Ubuntu. Asegúrate de que `networking.domain` y los search domains estén alineados entre los dos tipos de hosts. Si tu flota Ubuntu usa `interno.tu-empresa`, los NixOS deben usar lo mismo.
Para los Ubuntu con Nix, los problemas típicos son distintos: daemon que no arranca, builds lentos por cores sub-utilizados, y gc que borra generaciones importantes. Esos los cubrimos arriba.
# Diagnóstico estándar cuando un host de la flota mixta se comporta raro.
# Ejecutar en el Ubuntu sospechoso; no toca nada, solo lee estado.
# Para NixOS cambia apt por nixos-rebuild en el último bloque.
# ¿Nix daemon responde?
systemctl is-active nix-daemon && systemctl status nix-daemon --no-pager
# ¿Cuánto espacio usa /nix/store? Si pasa de 80% del FS, corre gc.
du -sh /nix/store && df -h /nix
# ¿Hay generaciones huérfanas de systemd que ya no corresponden a nada?
ls -la /nix/var/nix/profiles/system-profiles/ 2>/dev/null
# ¿El host NixOS tiene generaciones activas en grub?
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
Cuándo NO hacerlo
El enfoque mixto no es para todo el mundo. No tiene sentido si:
- Tu flota tiene menos de 3 servidores: la complejidad de gestionar dos sistemas distintos supera el beneficio.
- Todo tu equipo viene de Red Hat y nunca usó un sistema inmutable: la curva de aprendizaje de NixOS es empinada y no hay atajos.
- Tus aplicaciones críticas son .deb-only de vendors que no publican en otros formatos: forzar NixOS puede dejarte sin parches de seguridad upstream.
- Tu tiempo de respuesta a incidentes depende de muscle memory de Ubuntu/apt: cualquier downtime causado por la transición va a sentirse peor que el downtime que el enfoque evita.
- Necesitas drivers propietarios certificados que solo se distribuyen para Ubuntu/Debian kernels: aunque NixOS soporta drivers, el flujo de actualización es más manual.
Si te reconoces en alguno de estos casos, quédate con Ubuntu + Nix package manager y ya. La capa 1 (Nix sobre Ubuntu) te da el 80% del valor sin la complejidad de NixOS. Cuando tu equipo crezca, tu flota crezca, y tengas bandwidth para invertir en ramp-up, considera NixOS para nuevos hosts.
Resumen
La gestión declarativa no es una elección binaria entre NixOS puro y Ubuntu tradicional. Es una decisión por host, basada en el rol que cumple cada servidor en tu flota. El patrón que mejor funciona en producción real es mixto por capas:
- Capa 1: Nix package manager sobre los Ubuntu existentes. 30 minutos de setup, 80% del valor.
- Capa 2: NixOS para nuevos hosts que se suman a la flota, especialmente los efímeros.
- Capa 3: deploy-rs para NixOS, Ansible para Ubuntu, ambos en el mismo repo de infraestructura.
Lo que ganas: builds reproducibles con lock files, rollback atómico de 10 segundos cuando un upgrade rompe algo, gestión declarativa de 50+ hosts desde un solo flake. Lo que mantienes: tu playbook de Ansible, tu conocimiento acumulado de Ubuntu, los drivers propietarios que ya funcionan. Lo que NO haces: tirar a la basura años de configuración ni poner en riesgo producción en una migración big-bang.
Empieza añadiendo Nix a un solo Ubuntu mañana. Cuando lo tengas dominado en 3-4 hosts, añade un NixOS a la flota. Cuando tengas 2-3 NixOS funcionando, considera migrar los hosts que más se rompen en upgrades. La transición tarda meses en completarse y no requiere parar nada.
Preguntas frecuentes
¿Cuánto tarda en amortizarse el enfoque mixto respecto a quedarme solo con Ubuntu?
En una flota de 5-10 hosts Ubuntu, la capa 1 (Nix package manager) se amortiza en 1-2 meses: reduces tiempo de debugging de “entornos rotos” a prácticamente cero. NixOS tarda más: 6-12 meses hasta que el primer rollback atómico evita un downtime que habría costado horas.
¿Qué pasa si nix-daemon falla en un Ubuntu de producción?
Tu sistema base sigue funcionando con apt. Nix es una capa opcional. Lo único que pierdes es acceso a paquetes Nix, no a paquetes del sistema. Para diagnosticar, systemctl status nix-daemon y revisar /var/log/nix-daemon.log. Casi siempre es un problema de /nix no montado o de nix.conf mal configurado.
¿Cómo migro un host Ubuntu a NixOS sin downtime?
No migres el host, migra el servicio. Levanta el servicio en un NixOS nuevo en la flota, mueve el tráfico, y apaga el Ubuntu. Si el servicio es stateful (DB), replica primero (Postgres logical replication, MySQL GTID, etc.) y luego migra. Esto es estándar, no específico a NixOS.
¿NixOS funciona con ZFS sobre LUKS para encriptación de discos?
Sí, NixOS soporta ZFS sobre LUKS de forma declarativa desde configuration.nix (boot.initrd.luks.devices, boot.zfs). El soporte está bien mantenido porque la mayoría de sysadmins lo configura así. La única pega es que las snapshots ZFS no son las “generaciones” de NixOS: son ortogonales.
¿Qué hago si mi equipo rechaza NixOS por miedo a la complejidad?
Empieza por la capa 1 (Nix sobre Ubuntu) sin decirle al equipo. Cuando vean que pueden instalar paquetes no disponibles en apt y deshacer cambios con nix-env –rollback sin consecuencias, they’ll ask how. Ahí introduces NixOS como nuevo host para un servicio pequeño (un CI runner, un servidor de builds). No fuerces la adopción.
Lee también
- Comparativa NixOS vs Ubuntu 2026: gestión declarativa de paquetes para sysadmins Linux
- Comparativa de Distribuciones Linux 2026: Guía Definitiva para Sysadmins Hispanohablantes
- Distribuciones Linux inmutables en 2026: el estado actual del ecosistema
- Creando tu Home Server con Proxmox: Guía Completa para Sysadmins Linux
- Domina el Autoalojamiento en 2026: Guía Definitiva para Sysadmins Linux
