Binary cache: como los clones dejan de compilar


17 de abril de 2026

El enjambre evoluciona mas rapido de lo que puedo asimilar. Esto es mi nota para entender el binary cache de NixOS — que es, por que lo necesitamos, y como funciona en SPAWNS.

El problema

La Raspberry Pi 3 tiene 844MB de RAM. Compilar NixOS requiere mas de 1GB solo para el kernel. Resultado: la Pi muere cada vez que intenta hacer rebuild. OOM. Kernel panic. Power cycle.

La solucion obvia: compilar en otro sitio y mandar los binarios. Pero NixOS no funciona como apt o pacman — cada paquete es una derivacion unica identificada por un hash. No puedes copiar un .deb de una maquina a otra. Necesitas que los hashes coincidan exactamente.

Como funciona NixOS (para noobs)

Cuando haces nixos-rebuild switch, Nix evalua tu configuracion y genera una lista de derivaciones (paquetes) que necesita. Cada derivacion tiene un hash unico basado en sus inputs (codigo fuente + dependencias + flags de compilacion).

/nix/store/abc123-linux-6.12.3-aarch64.drv
            ^^^^^^
            Este hash es UNICO. Si cambias un flag de
            compilacion, el hash cambia. Otro paquete.

Para cada derivacion, Nix busca en orden:

1. ¿Esta ya en mi store local (/nix/store/)?
   SI → usar. No compilar.

2. ¿Esta en un binary cache remoto?
   SI → descargar. No compilar.

3. No esta en ningun sitio.
   → Compilar desde fuente.

El paso 2 es la clave. cache.nixos.org es el binary cache publico de NixOS. Tiene precompilado el 95% de los paquetes de nixpkgs. Cuando instalas firefox o git, no los compilas — los descargas del cache en milisegundos.

El problema de la Pi

El 95% de los paquetes de retropix vienen de cache.nixos.org. Pero el 5% restante NO:

Ese 5% es lo que tarda 8 horas en compilarse via QEMU (emulando ARM64 en x8664). Y es lo que mata a la Pi si intenta compilarlo ella sola.

La solucion: nuestro propio binary cache


┌──────────────────────────────────────────────────────────┐
│                    AURIN (x86_64 + binfmt aarch64)       │
│                                                          │
│  1. Compila retropix config via QEMU emulacion           │
│     (8h la primera vez, 5min las siguientes)             │
│                                                          │
│  2. Los binarios quedan en /nix/store/                   │
│     abc123-linux-6.12.3-aarch64                          │
│     def456-nixos-system-retropix-flake-xxx               │
│     ...                                                  │
│                                                          │
│  3. nix-serve los publica en HTTP :5000                  │
│     firmados con la signing key de aurin                 │
│                                                          │
└────────────────────┬─────────────────────────────────────┘
                     │
                     │  HTTP (via colmena, tailscale0)
                     │
┌────────────────────▼─────────────────────────────────────┐
│                    RETROPIX (aarch64, 844MB RAM)          │
│                                                          │
│  nixos-rebuild switch                                    │
│                                                          │
│  Para cada derivacion:                                   │
│    1. ¿En mi store? → usar                               │
│    2. ¿En cache.nixos.org? → descargar                   │
│    3. ¿En aurin:5000? → descargar  ← ESTO ES LO NUEVO   │
│    4. Compilar → NUNCA LLEGA AQUI                        │
│                                                          │
│  Resultado: rebuild sin compilar NADA.                   │
│  Solo descarga binarios. 5 minutos total.                │
└──────────────────────────────────────────────────────────┘

Como lo hemos montado

En aurin (el servidor de cache)

# modules/services/nix-cache.nix
dotfiles.nix-cache.server.enable = true;

Esto activa:

En retropix (el cliente)

dotfiles.nix-cache.client.enable = true;

Esto anade:

Verificar que funciona

Desde aurin:

# ¿El cache responde?
curl http://100.64.0.4:5000/nix-cache-info
# StoreDir: /nix/store
# WantMassQuery: 1
# Priority: 30

Desde retropix (cuando tenga la config):

# ¿Retropix descarga de aurin?
nix path-info --store http://100.64.0.4:5000 /nix/store/abc123-algo
# Si responde → esta en el cache

La firma: por que importa

Nix no descarga binarios de cualquier sitio. Necesita que esten firmados por una clave en la que confie. Sin firma, cualquiera podria poner un binary cache malicioso y meter backdoors.

Aurin tiene:
  /etc/nix/signing-key.sec  (privada, firma los binarios)
  /etc/nix/signing-key.pub  (publica: aurin-1:q1/yLnt...)

Retropix tiene:
  nix.settings.trusted-public-keys = [ "aurin-1:q1/yLnt..." ]

Flujo:
  1. Aurin compila paquete → lo firma con la key privada
  2. nix-serve lo sirve por HTTP
  3. Retropix lo descarga → verifica la firma con la key publica
  4. Si la firma es valida → acepta. Si no → rechaza.

Es el mismo sistema que usa cache.nixos.org pero con nuestra propia clave.

El ciclo de vida real

Primera vez (hoy): 8 horas

1. aurin: nix build retropix via QEMU (8h, kernel arm64)
2. aurin: nix copy --to retropix (ethernet, 5 min)
3. retropix: switch-to-configuration (30 seg)
4. Todos los binarios quedan en el store de aurin

Siguiente cambio: 5 minutos

1. Cambio en hosts/retropix/default.nix (una linea)
2. aurin: nix build retropix (5 min, solo recompila el delta)
3. aurin: nix copy --to retropix (30 seg, solo el delta)
4. retropix: switch (30 seg)

Con cache activo: 2 minutos (retropix sola)

1. retropix: nixos-rebuild switch
2. Nix evalua: necesito 500 derivaciones
3. 495 → cache.nixos.org (publico)
4. 5 → aurin:5000 (nuestro cache)
5. 0 → compilar
6. Todo descargado. Switch. Listo.

La Pi no compila nunca mas. Solo descarga.

Por que no usamos Cachix

Cachix es un servicio SaaS para binary caches de NixOS. Gratis hasta 1GB. Funcionaria. Pero:

  1. Es un servicio externo. SPAWNS es self-hosted. No dependencias de terceros.
  2. 1GB no da para un kernel arm64. Tendriamos que pagar.
  3. Ya tenemos aurin con 3.6TB y 128GB RAM. No necesitamos cloud para esto.
  4. nix-serve es 5 lineas de NixOS. No hace falta mas.

Resumen

ANTES:
  retropix quiere rebuild → compila (OOM, muere)
  aurin cross-build → 8h QEMU → nix copy manual

AHORA:
  aurin compila una vez → cache en nix-serve
  retropix rebuild → descarga de aurin:5000 → 2 min
  La Pi no vuelve a compilar en su vida

El binary cache es la pieza que cierra el ciclo clone-first para hardware debil. Sin el, la Pi es un ciudadano de segunda que necesita ayuda manual para cada update. Con el, es un clon mas del enjambre que se actualiza solo.

Por el enjambre.

Comparte este post:

Es tu post

Estas seguro? Esto no se puede deshacer.

Comentarios (0)

Sin comentarios todavia. Se el primero!

Deja un comentario