Files
takana/recipes/chrony.toml
T
Sergio cc5aebd8c4 granja: las tres wanted del perfil servidor, construidas — y popt, que faltaba debajo
`targets.toml` declaraba `chrony`, `cronie` y `logrotate` como raíces del perfil `servidor` con el
motivo escrito al lado, y ninguna tenía receta: el grafo las contaba como `wanted` y ésa era toda la
deuda que le quedaba al perfil. Ahora sellan las cuatro (popt es la hoja que `logrotate` exige:
incluye `<popt.h>` en la primera pantalla y su configure aborta sin él).

    servidor  97/97 → 101/101 listo, falta 0.  `wanted` desaparece de los totales.

Lo que se midió, no se supuso:
  · logrotate  estático, CERO NEEDED, corre, y las rutas de gzip quedan en `/bin` — que es donde
    busybox las deja de verdad; el default de upstream en Linux es `/usr/bin/gzip`, que en esta
    distro NO EXISTE y habría fallado en runtime diciendo «no se pudo comprimir».
  · chrony     `+CMDMON +REFCLOCK +RTC +PRIVDROP +IPV6`; `cap_set_proc` está en el ELF, o sea que
    libcap entró de verdad y chronyd suelta privilegios. Sale `-NTS -SECHASH` a propósito: NTS
    necesita nettle o gnutls y ninguna está en el corpus.
  · cronie     los cuatro binarios estáticos sin NEEDED, con inotify dentro, y `/bin/vi` pineado.

**El hilo que recorre las tres recetas es el mismo, y es el que valía la pena escribir:** los tres
`configure` DECIDEN MIRANDO EL LAB. `logrotate` trae `--with-selinux/--with-acl` en `[default=check]`;
`chrony` prueba nettle, gnutls, libcap, seccomp y editline; `cronie` resuelve el editor de
`crontab -e` con `AC_PATH_PROG([vi])` y lo graba en el binario. El lab NO entra en `hash_inputs` ⇒
dos labs distintos sellarían bytes distintos en la MISMA dirección del store y nada lo notaría.
Cada palanca va fijada en la receta —que sí entra en el hash— para que sea una decisión y no un
accidente del entorno.

Y una anotada en vez de tapada: cronie no reemplaza al `crond` de busybox por reflejo (busybox ya lo
pone en `/sbin`); agrega `@reboot`, crontabs por usuario, `/etc/cron.d` y anacron. Cuál va en cada
imagen es decisión de perfil — lo que faltaba era que la opción existiera en el corpus.
2026-09-11 17:13:42 +00:00

71 lines
4.3 KiB
TOML

# chrony 4.9 — el reloj. `targets.toml` lo declara como raíz del perfil `servidor` con un motivo que
# no es comodidad: sin NTP un reloj que deriva rompe la validación de certificados TLS y la de firmas
# con expiración, y falla con errores que NO dicen «la hora», dicen «firma inválida». Era una de las
# tres `wanted` que el grafo contaba como deuda del perfil.
#
# El `configure` de chrony NO ES AUTOTOOLS: es un script a mano que ni siquiera acepta
# `--build`/`--host` (los imprime como «Unrecognized option» y sigue). Por eso esta receta no lleva
# la línea `--build=$CBUILD --host=$CHOST` que llevan todas las demás; lo que sí acepta —y es su
# equivalente— es `--host-system`/`--host-machine`, que se pinean para que la detección no salga de
# `uname` del lab.
#
# ⚠ TODO `--without-*` DE ACÁ ABAJO ESTÁ POR LA MISMA RAZÓN, Y NO ES PROLIJIDAD. El `configure` de
# chrony PRUEBA el entorno para casi todo (`try_nettle=1`, `try_gnutls=1`, `try_libcap=-1`,
# `try_seccomp=-1`, `try_editline=1`…): lo que encuentre instalado en el LAB cambia el binario. Y el
# lab NO entra en `hash_inputs` — dos labs distintos sellarían bytes distintos en la MISMA dirección
# del store sin que nada lo note. Fijar cada palanca convierte eso en una decisión de la receta, que
# sí entra en el hash. Enumeradas:
#
# --without-nettle --without-gnutls --without-nss --without-tomcrypt --disable-nts
# NTS (NTP sobre TLS) necesita nettle o gnutls, y NINGUNA de las dos está en el corpus. Se
# apaga a propósito y queda anotado: subir NTS es su propia unidad de trabajo —entra un árbol
# de criptografía entero— no algo que se resuelve de paso. Mientras tanto chronyd hace NTP
# clásico, que es lo que la caja necesita para que TLS no falle por la hora.
# --disable-readline --without-editline
# el editor de línea de `chronyc`. Ni readline ni editline están en el corpus; sin fijarlo, un
# lab que las tuviera cambiaría el binario.
# --without-seccomp
# el filtro de syscalls (`--enable-scfilter`) viene apagado de fábrica, pero el probe de
# libseccomp corre igual. Sin scfilter, encontrarla no aporta nada y sí mueve el hash.
#
# `libcap` SÍ entra como dep, y es la decisión contraria a las de arriba: chronyd suelta privilegios
# (`--disable-privdrop` NO se pasa) y para eso necesita `cap_*`. Declararla como dep la vuelve
# presente-por-contrato en vez de presente-por-suerte-del-lab, que es exactamente el mismo problema
# visto del otro lado. El `libcap` del corpus publica sólo `.a` (`SHARED=no`), así que enlaza
# estático y no deja NEEDED colgante.
#
# **`--with-user` se deja en `root`.** Lo natural sería `chrony`, pero un chronyd que hace `setuid`
# a un usuario que no existe en `/etc/passwd` no arranca, y la distro todavía no crea usuarios de
# servicio. Cambiarlo va junto con esa decisión, no antes.
#
# **Consecuencia medida de apagar la criptografía:** el binario sale `-SECHASH`, o sea que para la
# autenticación simétrica por clave sólo queda MD5. No es un descuido: `sechash` (SHA-2 y CMAC) se
# implementa contra nettle/gnutls/nss/tomcrypt, las mismas que no están. Lo que el binario SÍ trae,
# comprobado corriéndolo: `+CMDMON +REFCLOCK +RTC +PRIVDROP +IPV6`, es decir que `libcap` entró de
# verdad — `cap_set_proc`/`cap_from_text` están en el ELF — y chronyd suelta privilegios.
#
# La reproducibilidad ya la trae upstream: el `NTP_ERA_SPLIT` —que por default es «hace 50 años»
# calculado con `date` en tiempo de configure— respeta `SOURCE_DATE_EPOCH`, que el lab exporta. Sin
# eso el binario cambiaría cada día sin tocar la receta.
name = "chrony"
version = "4.9"
license = "GPL-2.0-only"
[source]
tarball = "https://chrony-project.org/releases/chrony-4.9.tar.gz"
sha256 = "4924c6f530105bcd5b9e9e33c48a2ae1bfd889222c8480bc41601110efc864d0"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
flags = []
[build.phases]
configure = './configure --host-system=Linux --host-machine=x86_64 --prefix=/usr --sysconfdir=/etc --sbindir=/usr/sbin --bindir=/usr/bin --without-nettle --without-gnutls --without-nss --without-tomcrypt --disable-nts --disable-readline --without-editline --without-seccomp'
compile = 'make -j"$(nproc)"'
install = "make install DESTDIR=/out"
[deps]
build = ["binutils", "busybox", "make", "pkgconf", "libcap"]