tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

imagen e instalador: UTC por defecto — nacían SIN /etc/localtime

La caja `takana` no tenía /etc/localtime, y las dos rutas de instalación lo
explican: el TUI sólo lo escribe si el usuario eligió zona (guarda
`[ -n "$CFG_TZ" ]`), y una caja volcada con `dd` no pasa por el TUI. Así que
quien no elegía nada se quedaba sin el fichero.

⚠ Parece inofensivo y no lo es, y el coste no es la hora: es el DIAGNÓSTICO.
musl asume UTC cuando el fichero falta, así que la hora sale bien y nada parece
roto. Pero cada programa que llama a localtime() se come un
`open("/etc/localtime") = -1 ENOENT` que DEJA errno SUCIO, y cualquier error
posterior que reporte errno sin ser un fallo de errno miente con esa cadena.

Medido ayer persiguiendo otro bug: `makewhatis` abortaba por una razón que no
tiene nada que ver y culpaba a «No such file or directory»; con TZ=UTC el MISMO
fallo pasaba a decir «No error information». Gasté varias vueltas creyendo que
el localtime era la causa cuando sólo coloreaba el mensaje.

Poner UTC no cambia el comportamiento —es lo que el sistema ya asumía;
comprobado en la caja, `date` y `TZ=UTC date` dan lo mismo— y quita la trampa.

Las dos guardas son ruidosas a propósito: si el destino no trae zoneinfo, un
enlace apuntaría a la nada y sería PEOR que no tenerlo (localtime() seguiría
dando ENOENT y encima el fichero existiría). `tzdata` está en `base`, que
heredan todos los perfiles menos `escritorio-mirada`, que es slim a propósito
y para el que el aviso saldrá — correctamente.

`TZ_IMAGEN` permite otra zona en una imagen deliberada.

fac9bb0b3e2c757c74694c39625a434d33c01729 · por Sergio · (hace 21 h) · padre 101b561e6 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

2 archivos · +44 −3

diff --git a/scripts/servidor-image.sh b/scripts/servidor-image.sh
index b27a37c3..fa246597 100755
--- a/scripts/servidor-image.sh
+++ b/scripts/servidor-image.sh
@@ -134,6 +134,34 @@ echo "==> init    : $antes → $(readlink "$RFS/sbin/init")"
 # ordenado de arje (`apagar_maquina()`) existía entero y no estaba conectado a ningún botón.
 sh scripts/servidor/arje-botones.sh "$RFS"
 
+# ── 3 ter. la ZONA HORARIA, que nadie ponía y cuesta horas de diagnóstico ────────────────────────
+# Esta imagen nacía **sin `/etc/localtime`**, y el instalador TUI sólo lo escribe si el usuario
+# eligió zona (`takana-live-install.sh:145`, guardado por `[ -n "$CFG_TZ" ]`). Una caja volcada con
+# `dd` no pasa por el TUI ⇒ nunca tenía el fichero. Medido en `takana` el 2026-10-21.
+#
+# ⚠ **No es cosmético, y el coste real no es la hora: es el diagnóstico.** musl asume UTC cuando el
+# fichero falta, así que la hora sale bien y nada parece roto. Pero cada programa que llama a
+# `localtime()` se come un `open("/etc/localtime") = -1 ENOENT` que **deja `errno` sucio**, y
+# cualquier error posterior que reporte `errno` sin tener un fallo de `errno` miente con esa cadena.
+# Pasó: `makewhatis` abortaba por otra razón y decía «No such file or directory»; con `TZ=UTC` el
+# MISMO fallo pasaba a decir «No error information». Perseguí el localtime varias vueltas creyendo
+# que era la causa.
+#
+# ⇒ UTC por defecto, que es lo que el sistema ya asumía: **cero cambio de comportamiento**
+# (comprobado en la caja: `date` y `TZ=UTC date` dan lo mismo), y el fichero deja de faltar.
+# `TZ_IMAGEN` permite otra zona para una imagen deliberada.
+TZ_IMG="${TZ_IMAGEN:-UTC}"
+if [ -e "$RFS/usr/share/zoneinfo/$TZ_IMG" ]; then
+  ln -sf "/usr/share/zoneinfo/$TZ_IMG" "$RFS/etc/localtime"
+  printf '%s\n' "$TZ_IMG" > "$RFS/etc/timezone"
+  echo "==> zona    : $TZ_IMG (/etc/localtime -> /usr/share/zoneinfo/$TZ_IMG)"
+else
+  # Ruidoso a propósito: si `tzdata` no viaja en el perfil, un enlace apuntaría a la nada y sería
+  # PEOR que no tenerlo —`localtime()` seguiría dando ENOENT y encima el fichero existiría—.
+  echo "==> zona    : ⚠ SIN /etc/localtime: el perfil '$PERFIL' no trae zoneinfo/$TZ_IMG." >&2
+  echo "              Declarar 'tzdata' en el perfil, o TZ_IMAGEN=<zona que exista>." >&2
+fi
+
 # ── 4. la clave ──────────────────────────────────────────────────────────────────────────────────
 install -d -m 700 "$RFS/root/.ssh"
 install -m 600 "$AUTHKEYS" "$RFS/root/.ssh/authorized_keys"
diff --git a/scripts/takana-live-install.sh b/scripts/takana-live-install.sh
index 04af8f62..88f215a4 100755
--- a/scripts/takana-live-install.sh
+++ b/scripts/takana-live-install.sh
@@ -142,9 +142,22 @@ apply_post_install_config() {
         printf '%s\n' "$CFG_ROOT_AUTHKEYS" >> "$_mnt/root/.ssh/authorized_keys"
         bb chmod 600 "$_mnt/root/.ssh/authorized_keys"
     fi
-    if [ -n "${CFG_TZ:-}" ] && [ -e "$_mnt/usr/share/zoneinfo/$CFG_TZ" ]; then
-        bb ln -sf "/usr/share/zoneinfo/$CFG_TZ" "$_mnt/etc/localtime"
-        printf '%s\n' "$CFG_TZ" > "$_mnt/etc/timezone"
+    # ⚠ **UTC POR DEFECTO, no "sin zona".** Antes esto estaba guardado por `[ -n "$CFG_TZ" ]` a
+    # secas, así que quien no elegía zona en el TUI se quedaba SIN `/etc/localtime`. Parece
+    # inofensivo —musl asume UTC y la hora sale bien— pero cada `localtime()` se come un
+    # `open("/etc/localtime") = -1 ENOENT` que deja `errno` sucio, y cualquier error posterior que
+    # reporte `errno` sin ser un fallo de `errno` miente con esa cadena. Medido el 2026-10-21:
+    # `makewhatis` abortaba por otro motivo y culpaba a «No such file or directory»; con `TZ=UTC`
+    # el mismo fallo decía «No error information». Horas de diagnóstico por un fichero ausente.
+    # ⇒ Poner UTC no cambia el comportamiento (es lo que ya se asumía) y quita la trampa.
+    _tz="${CFG_TZ:-UTC}"
+    [ -e "$_mnt/usr/share/zoneinfo/$_tz" ] || _tz=UTC
+    if [ -e "$_mnt/usr/share/zoneinfo/$_tz" ]; then
+        bb ln -sf "/usr/share/zoneinfo/$_tz" "$_mnt/etc/localtime"
+        printf '%s\n' "$_tz" > "$_mnt/etc/timezone"
+    else
+        # Sin zoneinfo en el destino un enlace apuntaría a la nada, que es PEOR que no tenerlo.
+        echo "  ⚠ sin /etc/localtime: el sistema instalado no trae /usr/share/zoneinfo (¿falta tzdata?)" >&2
     fi
     _ts=$(bb date -u +%FT%TZ 2>/dev/null || echo unknown)
     {