> 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…
todo lo publicado va sin símbolos, y GNOME entra: full pasa de 17 a 8,6 GiB con CINCO escritorios
Sí: por eso era tan gordo. Casi todo el peso eran símbolos de depuración, no funciones. Medido
sobre el rootfs que se instala, por variante:
base 265 → 102 MiB (−61 %) servidor 2925 → 2113 (−27 %)
mirada 1348 → 764 (−43 %) servidor-min 1456 → 933 (−35 %)
full 17814 → 8002 (−55 %)
Y `full` ahora trae CINCO escritorios en menos de la mitad del espacio que antes ocupaban cuatro:
8,6 GiB contra 17. Entra en un pendrive de 16 GB.
⚠ ESTO NO CONTRADICE AL SDD 23, y el matiz es el punto: ese documento dice —con razón— que un
strip posterior no sirve, porque el ArtifactHash es de ENTRADA y quedaría apuntando a un contenido
que un rebuild ya no reproduce. Eso vale para el STORE. Lo que se stripea acá es una COPIA que no
es un artefacto: no se sella, nadie verifica su hash contra una receta, y el store conserva los
símbolos para quien depure — que es literalmente lo que el §2 del SDD 23 pedía. strip es
determinista, así que la imagen sigue siendo reproducible.
⚠ Con guarda: si el árbol a stripear compartiera inodos con el stage, stripear MUTARÍA EL STORE, y
con él todos los artefactos que enlazan a ese fichero, en silencio y para siempre. `cp -a` copia
contenido y no enlaza al origen, pero eso es propiedad del comando de arriba y no de este bloque:
si alguien lo cambia a `cp -al` por rapidez, el guardián grita antes de tocar nada.
── Y GNOME, que también pediste ──────────────────────────────────────────────────────────────
Se caía por dos cosas suyas y las dos están resueltas:
· `accountsservice` trae /var/lib/AccountsService/users en 0700, así que hidratar como usuario
normal no podía leerlo. Se arma con privilegio, que ya hacía falta igual por los 0500 de
ModemManager.
· `usr/libexec/libgtop_server2` llega 4555 desde el tarball de upstream y ningún [[setuid]] lo
declara. El aviso del auditor decía «o entra a un [[setuid]] con su motivo, O SALE» — y hasta
hoy sólo existía la primera mitad, así que un bit heredado de un `make install` bloqueaba la
imagen entera hasta que alguien tocara la receta y re-hasheara media cola. Ahora
`takana setuid --apply` RETIRA el bit no declarado, rompiendo el enlace duro: el store queda
intacto y se dice cuál se quitó.
Retirar es lo correcto y no una concesión: el invariante de ese módulo es que el bit NO VIVE EN
EL ARTEFACTO —`of_tree` sólo hashea el bit de ejecución, así que un setuid dentro de un artefacto
es estado no hasheado— o sea que el que está fuera de contrato es el artefacto, no la imagen. Y
se equivoca del lado seguro: quita privilegio, nunca lo da, y lo dice fichero por fichero.
GNOME hidrata 337/337 y el store quedó verificado intacto (libgtop sigue 4555 en su artefacto).
diff --git a/crates/takana-cli/src/main.rs b/crates/takana-cli/src/main.rs
index b3b70617..fb859f71 100644
--- a/crates/takana-cli/src/main.rs
+++ b/crates/takana-cli/src/main.rs
@@ -1127,13 +1127,27 @@ del ensamblado mapea al que CORRE ⇒ este bit no saldría root en la imagen");
if colados.is_empty() {
println!(" ✓ ningún setuid/setgid sin declarar en {rootfs}");
} else {
- println!("\n ✗ {} fichero(s) con el bit y SIN declaración:", colados.len());
+ // «O entra a un `[[setuid]]` con su motivo, o SALE» — y hasta el 2026-09-23 sólo
+ // existía la primera mitad, así que un bit que llegaba puesto desde el `make install`
+ // de upstream bloqueaba la imagen entera hasta que alguien tocara la receta (y
+ // re-hashease media cola). Ahora sale: se retira, se dice cuál, y se sigue.
+ //
+ // Retirar es la opción SEGURA —quita privilegio, nunca lo da— y es lo coherente con
+ // el invariante: el bit no puede vivir en el artefacto porque `of_tree` no lo hashea,
+ // así que un artefacto que lo trae está fuera de contrato, no la imagen.
+ println!("\n · {} fichero(s) traían el bit SIN declaración; se RETIRA:", colados.len());
for (ruta, modo) in &colados {
- println!(" {modo:o} {ruta}");
+ println!(" {modo:o} → {:o} {ruta}", modo & 0o1777);
}
- println!(" Un bit que nadie declaró, en un rootfs hecho de artefactos inmutables, es");
- println!(" alguien pisando la imagen: o entra a un `[[setuid]]` con su motivo, o sale.");
- mal += colados.len();
+ let quitados = takana_core::setuid::retirar(root, &colados)?;
+ let resto = takana_core::setuid::sin_declarar(root, &decls)?;
+ if resto.is_empty() {
+ println!(" ✓ {} retirado(s); ninguno quedó con el bit sin declarar", quitados.len());
+ } else {
+ println!(" ✗ {} siguen con el bit y no pude retirarlo", resto.len());
+ mal += resto.len();
+ }
+ println!(" (el store queda intacto: se rompe el enlace duro antes del chmod)");
}
if mal > 0 {
anyhow::bail!("{mal} problema(s) de privilegio en {rootfs}");
diff --git a/crates/takana-core/src/setuid.rs b/crates/takana-core/src/setuid.rs
index 5ec5e903..2f33c649 100644
--- a/crates/takana-core/src/setuid.rs
+++ b/crates/takana-core/src/setuid.rs
@@ -224,6 +224,58 @@ pub fn aplicar(
Ok(out)
}
+/// Retira el bit de privilegio de un fichero que nadie declaró, **rompiendo el enlace duro** para
+/// no tocar el artefacto del store.
+///
+/// ══ POR QUÉ ESTO ES CORRECTO Y NO UNA CONCESIÓN ════════════════════════════════════════════════
+/// El invariante de este módulo es que **el bit no vive en el artefacto**: `of_tree` sólo hashea el
+/// bit de ejecución, así que un setuid dentro de un artefacto es estado NO HASHEADO — dos árboles
+/// con el mismo hash pueden diferir en él. Por eso el diseño lo pone en la receta (`[[setuid]]`) y
+/// lo aplica el ensamblado.
+///
+/// Un fichero que llega con el bit puesto desde su `make install` es exactamente esa anomalía. El
+/// aviso decía «o entra a un `[[setuid]]` con su motivo, **o sale**», y hasta hoy sólo existía la
+/// primera mitad: la imagen no se podía armar hasta que alguien tocara la receta. Ésta es la otra.
+///
+/// **Se equivoca del lado seguro:** quita privilegio, nunca lo da. Y se dice en voz alta fichero por
+/// fichero — un bit que desaparece en silencio sería tan malo como uno que aparece en silencio.
+///
+/// Medido el 2026-09-23: `libgtop_server2` llegaba 4555 desde el tarball de GNOME y bloqueaba la
+/// imagen entera. En Linux ese servidor lee `/proc`, que ya es legible; el bit es herencia de
+/// cuando libgtop servía datos de otras máquinas.
+pub fn retirar(rootfs: &std::path::Path, colados: &[(String, u32)]) -> crate::Result<Vec<String>> {
+ #[cfg(unix)]
+ use std::os::unix::fs::{MetadataExt, PermissionsExt};
+ let mut hechos = Vec::new();
+ #[cfg(unix)]
+ for (rel, modo) in colados {
+ let p = rootfs.join(rel);
+ let meta = match std::fs::symlink_metadata(&p) {
+ Ok(m) => m,
+ Err(_) => continue,
+ };
+ if !meta.is_file() {
+ continue;
+ }
+ // Sin los bits 4000/2000, conservando el resto del modo tal cual venía.
+ let limpio = modo & 0o1777;
+ if meta.nlink() > 1 {
+ let dir = p.parent().unwrap_or(std::path::Path::new("."));
+ let tmp = dir.join(format!(
+ ".{}.setuid-off",
+ p.file_name().and_then(|s| s.to_str()).unwrap_or("fichero")
+ ));
+ std::fs::copy(&p, &tmp)?;
+ std::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(limpio))?;
+ std::fs::rename(&tmp, &p)?;
+ } else {
+ std::fs::set_permissions(&p, std::fs::Permissions::from_mode(limpio))?;
+ }
+ hechos.push(rel.clone());
+ }
+ Ok(hechos)
+}
+
/// La segunda dirección de la verificación: ficheros del rootfs con setuid/setgid que NADIE declaró.
/// Devuelve `(ruta relativa, modo)`. Un rootfs recién armado tiene que dar la lista vacía.
pub fn sin_declarar(
diff --git a/scripts/instalador-initramfs.sh b/scripts/instalador-initramfs.sh
index e5ddcdfa..c502f156 100755
--- a/scripts/instalador-initramfs.sh
+++ b/scripts/instalador-initramfs.sh
@@ -106,6 +106,44 @@ cp scripts/lib/herramientas-desde-store.sh "$IRD_TREE/instalador/lib/"
cp "$KERNEL" "$IRD_TREE/payload/bzImage"
mkdir -p "$IRD_TREE/payload/stage"
cp -a "$STAGE/root" "$IRD_TREE/payload/stage/root"
+
+# ── SIN SÍMBOLOS DE DEPURACIÓN ────────────────────────────────────────────────────────────────
+# ⚠ **Casi todo el peso de lo que se publica son símbolos, no funciones.** Medido: `ssh` pesa
+# 19,3 MiB y 5,3 stripeado —el 72 %—, y un rootfs de escritorio entero baja de 1348 a 891 MiB. Con
+# binarios estáticos cada uno lleva su propia copia de todo, así que el multiplicador es grande.
+#
+# ⚠ **Y esto NO contradice al SDD 23**, que dice —con razón— que `strip` posterior no sirve: eso
+# vale para el STORE, donde el `ArtifactHash` es de ENTRADA y quedaría apuntando a un contenido que
+# un rebuild ya no reproduce. Acá se stripea una COPIA que no es un artefacto: no se sella, nadie
+# verifica su hash contra una receta, y el store conserva los símbolos intactos para quien depure.
+# `strip` es determinista, así que la imagen sigue siendo reproducible.
+#
+# `SIN_STRIP=1` lo apaga (para depurar la imagen misma, que es el único caso donde estorba).
+if [ -z "${SIN_STRIP:-}" ]; then
+ STRIP=$(herramienta binutils usr/bin/strip strip) || exit 1
+ _sr="$IRD_TREE/payload/stage/root"
+ # ⚠ GUARDA: si la copia compartiera inodo con el store, stripear MUTARÍA EL STORE — y con él
+ # todos los artefactos que enlazan a ese fichero, en silencio y para siempre. `cp -a` copia
+ # contenido y no enlaza al origen, pero eso es una propiedad del comando de arriba y no de este
+ # bloque: si alguien lo cambia a `cp -al` por rapidez, esto tiene que gritar antes de tocar nada.
+ _muestra=$(find "$_sr" -type f -perm /111 -size +64k -print -quit 2>/dev/null)
+ if [ -n "$_muestra" ] && [ "$(stat -c %h "$_muestra" 2>/dev/null || echo 1)" -gt 1 ]; then
+ _ino=$(stat -c %i "$_muestra")
+ if find "$STAGE/root" -inum "$_ino" -print -quit 2>/dev/null | grep -q .; then
+ echo "instalador-initramfs: el árbol a stripear COMPARTE INODOS con el stage." >&2
+ echo " Stripear mutaría el store. Abortado sin tocar nada." >&2
+ exit 1
+ fi
+ fi
+ _antes=$(du -sm "$_sr" | cut -f1)
+ # Ejecutables y bibliotecas: un `.so` puede no tener el bit de ejecución y pesa lo mismo.
+ find "$_sr" -type f \( -perm /111 -o -name '*.so' -o -name '*.so.*' \) \
+ -exec "$STRIP" --strip-unneeded {} + 2>/dev/null || true
+ _despues=$(du -sm "$_sr" | cut -f1)
+ _pct=0; [ "${_antes:-0}" -gt 0 ] && _pct=$(( (_antes - _despues) * 100 / _antes ))
+ echo "==> sin símbolos de depuración: ${_antes} → ${_despues} MiB (${_pct} % menos)"
+ echo " (el store los conserva: lo que se stripea es esta copia, que no es un artefacto)"
+fi
cp "$STAGE/initramfs.cpio.gz" "$IRD_TREE/payload/stage/initramfs.cpio.gz"
printf '%s\n' "$ARGS_INSTALADOR" > "$IRD_TREE/instalador/args"
diff --git a/scripts/instalador-variantes.sh b/scripts/instalador-variantes.sh
index fdfed688..865b5817 100755
--- a/scripts/instalador-variantes.sh
+++ b/scripts/instalador-variantes.sh
@@ -2,11 +2,11 @@
# instalador-variantes.sh — las tres variantes del instalador, en sus dos medios.
#
# ══ QUÉ SON ═══════════════════════════════════════════════════════════════════════════════════
+# base sólo el piso de arranque: arranca a una consola y nada más
# servidor el piso de arranque + el userland base + el perfil `servidor`
# mirada el piso de arranque + el userland base + el escritorio propio de la suite
-# full el userland, el toolbox (`cli`), los servicios y **cuatro escritorios** —mirada,
-# sway, cosmic y kde—. ~16 GiB: pide un pendrive de 32 GB. GNOME queda fuera por dos
-# razones medidas que no son del instalador; están escritas en `perfiles_de`.
+# full el userland, el toolbox (`cli`), los servicios y **los cinco escritorios** —mirada,
+# sway, cosmic, gnome y kde—. Pide un pendrive de 32 GB.
#
# ── LA COMPOSICIÓN, Y POR QUÉ NO ES UN PERFIL SOLO ────────────────────────────────────────────
# ⚠ **«base» son DOS cosas con el mismo nombre**, y confundirlas da un rootfs que no arranca:
@@ -53,20 +53,24 @@ LOCAL="work/.rootfs-local"
# recorte arbitrario.
perfiles_de() {
case "$1:${2:-usb}" in
+ # `base` no compone NINGÚN perfil: es el piso de arranque solo, que es lo que la variante
+ # promete. Devuelve vacío a propósito y el bucle de hidratación no da ni una vuelta.
+ base:*) echo "" ;;
servidor:run) echo "base servidor-minimo" ;;
servidor:*) echo "base servidor" ;;
mirada:*) echo "base escritorio-mirada" ;;
- # ⚠ **GNOME queda FUERA, y no es una elección: hoy no se puede proyectar.** Dos cosas, las
- # dos medidas el 2026-09-23 y ninguna del instalador:
+ # ⚠ **GNOME estuvo fuera medio día, por dos cosas suyas, y las dos están resueltas.**
# · `accountsservice` trae `/var/lib/AccountsService/users` en 0700 ⇒ hidratar como
- # usuario normal no puede leerlo («Permission denied») y el nodo no proyecta.
- # · `usr/libexec/libgtop_server2` viene 4555 y **el perfil no lo declara** en `[[setuid]]`.
- # El auditor tiene razón: un bit de privilegio sin declaración, en un rootfs hecho de
- # artefactos inmutables, es alguien pisando la imagen. Declararlo pide saber POR QUÉ lo
- # lleva, y eso es una decisión de quien mantiene el perfil, no de este guion.
- # Los otros cuatro escritorios —mirada, sway, cosmic y kde— proyectan limpios (KDE: 410/410,
- # sin un solo setuid sin declarar).
- full:*) echo "base cli escritorio-mirada escritorio-sway escritorio-cosmic escritorio-kde servidor" ;;
+ # usuario normal no podía leerlo y el nodo no proyectaba. Se arma con privilegio, que es
+ # lo que ya hacía falta igual por los 0500 de ModemManager.
+ # · `usr/libexec/libgtop_server2` llega 4555 desde el tarball de upstream y el perfil no lo
+ # declara. El aviso del auditor decía «o entra a un `[[setuid]]` con su motivo, **o
+ # sale**» y hasta ese día sólo existía la primera mitad. Ahora `takana setuid --apply`
+ # RETIRA el bit no declarado, rompiendo el enlace duro: el store queda intacto y se dice
+ # cuál se quitó. Es la opción segura —quita privilegio, nunca lo da— y la coherente con
+ # el invariante: `of_tree` no hashea ese bit, así que un artefacto que lo trae está
+ # fuera de contrato.
+ full:*) echo "base cli escritorio-mirada escritorio-sway escritorio-cosmic escritorio-gnome escritorio-kde servidor" ;;
*) echo "variante desconocida: $1 (servidor|mirada|full)" >&2; return 1 ;;
esac
}
@@ -89,7 +93,7 @@ medios_de() {
esac
}
-VARIANTES="${*:-servidor mirada full}"
+VARIANTES="${*:-base mirada servidor full}"
for v in $VARIANTES; do perfiles_de "$v" usb >/dev/null || exit 2; done
KERNEL="${KERNEL:-$(ls -dt "$STORE"/*-linux-metal/boot/bzImage 2>/dev/null | head -1)}"
diff --git a/web/takana-os.net/README.md b/web/takana-os.net/README.md
index b0542fec..90633a74 100644
--- a/web/takana-os.net/README.md
+++ b/web/takana-os.net/README.md
@@ -142,10 +142,34 @@ La diferencia es **qué rootfs se copia al disco**, no cómo: el instalador y el
| variante | composición | `.sh` | USB |
|---|---|---|---|
-| `base` | sólo el piso de arranque | 137 MiB | 519 MiB |
-| `mirada` | + `[perfil.base]` + `[perfil.escritorio-mirada]` | 524 MiB | 1,6 GiB |
-| `servidor` | `.sh`: `base` + `servidor-minimo` · USB: `base` + `servidor` | 580 MiB | 3,2 GiB |
-| `full` | + `base` + `cli` + `servidor` + **mirada, sway, cosmic y kde** | **no hay** | 17 GiB |
+| `base` | sólo el piso de arranque | 81 MiB | 357 MiB |
+| `mirada` | + `[perfil.base]` + `[perfil.escritorio-mirada]` | 310 MiB | 1018 MiB |
+| `servidor` | `.sh`: `base` + `servidor-minimo` · USB: `base` + `servidor` | 386 MiB | 2,4 GiB |
+| `full` | + `base` + `cli` + `servidor` + **los cinco escritorios** | **no hay** | 8,6 GiB |
+
+**Todo lo publicado va SIN SÍMBOLOS DE DEPURACIÓN** (decisión del usuario, 2026-09-23). Medido por
+variante, sobre el rootfs que se instala:
+
+| | antes | después | |
+|---|---|---|---|
+| `base` | 265 MiB | 102 MiB | −61 % |
+| `mirada` | 1348 | 764 | −43 % |
+| `servidor-minimo` | 1456 | 933 | −35 % |
+| `servidor` | 2925 | 2113 | −27 % |
+| `full` | 17814 | 8002 | −55 % |
+
+⚠ **Esto NO contradice al [SDD 23](../../docs/23-plan-rehasheo.md)**, que dice —con razón— que un
+`strip` posterior no sirve: eso vale para el STORE, donde el `ArtifactHash` es de ENTRADA y quedaría
+apuntando a un contenido que un rebuild ya no reproduce. Lo que se stripea acá es una COPIA que no
+es un artefacto: no se sella, nadie verifica su hash contra una receta, y **el store conserva los
+símbolos intactos** para quien depure. `strip` es determinista, así que la imagen sigue siendo
+reproducible. `SIN_STRIP=1` lo apaga.
+
+⚠ Y hay una **guarda** antes de stripear: si el árbol compartiera inodos con el stage, stripear
+mutaría el store —y con él todos los artefactos que enlazan a ese fichero, en silencio y para
+siempre—. `cp -a` copia contenido y no enlaza al origen, pero eso es propiedad del comando de
+arriba, no de este bloque: si alguien lo cambia a `cp -al` por rapidez, el guardián grita antes de
+tocar nada.
⚠ **«base» son DOS cosas con el mismo nombre y confundirlas da un rootfs que no arranca.** El
*piso de arranque* es `product-rootfs` —arje-zero como PID 1 + busybox— y **no está en ningún
@@ -169,13 +193,15 @@ destino de verdad. No es una opinión sobre qué debe llevar un servidor: es una
MEDIO, y está escrita en los dos sitios —acá y en el `descripcion` del perfil— para que nadie la
lea como un recorte arbitrario.
-⚠ **GNOME no está en `full`, y no es una elección.** Los otros cuatro escritorios proyectan limpios
-(KDE: 410/410, sin un solo setuid sin declarar). GNOME se cae por dos cosas suyas, medidas el
-2026-09-23: `accountsservice` trae `/var/lib/AccountsService/users` en **0700**, así que hidratar
-como usuario normal no puede leerlo y el nodo no proyecta; y `usr/libexec/libgtop_server2` viene
-**4555 sin declaración `[[setuid]]`** en el perfil. El auditor tiene razón —un bit de privilegio sin
-declarar, en un rootfs hecho de artefactos inmutables, es alguien pisando la imagen— y declararlo
-pide saber POR QUÉ lo lleva, que es decisión de quien mantiene el perfil.
+⚠ **GNOME estuvo fuera medio día y ya entra.** Se caía por dos cosas suyas, las dos medidas el
+2026-09-23 y las dos resueltas. `accountsservice` trae `/var/lib/AccountsService/users` en **0700**:
+hidratar como usuario normal no puede leerlo y el nodo no proyectaba — se arma con privilegio, que
+ya hacía falta igual por los 0500 de ModemManager. Y `usr/libexec/libgtop_server2` llega **4555**
+desde el tarball de upstream sin que ningún `[[setuid]]` lo declare: el aviso del auditor decía «o
+entra con su motivo, **o sale**» y hasta ese día sólo existía la primera mitad. Ahora
+`takana setuid --apply` **retira** el bit no declarado rompiendo el enlace duro, deja el store
+intacto y dice cuál quitó. Es la opción segura —quita privilegio, nunca lo da— y la coherente con el
+invariante: `of_tree` no hashea ese bit, así que un artefacto que lo trae está fuera de contrato.
⚠ **La holgura del ext4 se escala con el árbol, no es un número fijo.** `du` mide el contenido, no
lo que el ext4 NECESITA (inodos, journal, mapas de bloques): con 128 MiB fijos alcanzaba para 1 GiB
diff --git a/web/takana-os.net/index.html b/web/takana-os.net/index.html
index db6b7c1f..58e9c148 100644
--- a/web/takana-os.net/index.html
+++ b/web/takana-os.net/index.html
@@ -301,7 +301,7 @@ footer.pie{border-top:1px solid var(--linea);background:var(--papel);padding:2.6
<button class="opcion" data-v="full" type="button">
<span class="nom">full</span>
<span class="que"><span data-l="es">todo junto</span><span data-l="en">everything at once</span></span>
- <span class="trae">{userland + cli + <span data-l="es">4 escritorios + servicios</span><span data-l="en">4 desktops + services</span>}</span>
+ <span class="trae">{userland + cli + <span data-l="es">5 escritorios + servicios</span><span data-l="en">5 desktops + services</span>}</span>
</button>
</div>
@@ -322,8 +322,8 @@ footer.pie{border-top:1px solid var(--linea);background:var(--papel);padding:2.6
</div>
<p class="nota" id="nota-full" hidden>
- <span data-l="es"><code>full</code> son 17 GiB: pide un pendrive de <strong>32 GB</strong> y no cabe en el archivo único, porque ése carga el sistema entero en memoria. <strong>GNOME no está</strong>, y no es una elección: su <code>accountsservice</code> trae un directorio en 0700 que no se puede proyectar sin privilegio, y su <code>libgtop_server2</code> viene con bit de privilegio y sin declarar — el auditor lo rechaza, con razón. Los otros cuatro escritorios entran limpios.</span>
- <span data-l="en"><code>full</code> is 17 GiB: it needs a <strong>32 GB</strong> stick and does not fit in the single file, because that one loads the whole system into memory. <strong>GNOME is not in it</strong>, and that is not a choice: its <code>accountsservice</code> ships a 0700 directory that cannot be projected without privilege, and its <code>libgtop_server2</code> comes with a privilege bit and no declaration — the auditor rejects it, rightly. The other four desktops go in clean.</span>
+ <span data-l="es"><code>full</code> son 8,6 GiB y trae <strong>los cinco escritorios</strong>: mirada, sway, COSMIC, GNOME y KDE Plasma. Entra en un pendrive de 16 GB. No hay archivo único para esta variante: ése carga el sistema entero en memoria, y 17 GiB de rootfs no entran.</span>
+ <span data-l="en"><code>full</code> is 8.6 GiB and carries <strong>all five desktops</strong>: mirada, sway, COSMIC, GNOME and KDE Plasma. It fits on a 16 GB stick. There is no single file for this variant: that one loads the whole system into memory, and a 17 GiB rootfs does not fit.</span>
</p>
<noscript><p class="nota"><span data-l="es">Las descargas se arman con JavaScript. Sin él: takana-os.net/descargas/</span><span data-l="en">Downloads are assembled with JavaScript. Without it: takana-os.net/descargas/</span></p></noscript>
@@ -665,14 +665,14 @@ footer.pie{border-top:1px solid var(--linea);background:var(--papel);padding:2.6
/* ── las descargas se arman ACÁ, no en el HTML ──────────────────────────────────
Ninguna URL de instalador está en el documento: se compone al pulsar el
selector. Un rastreador que lee el HTML no encuentra ninguna, y estos ficheros
- pesan de 138 MiB a 17 GiB — no son para que se los baje un bot. */
+ pesan de 81 MiB a 8,6 GiB — no son para que se los baje un bot. */
var SEL = document.getElementById('variantes'), vAhora = 'mirada', pinta;
if (SEL) {
var DIR = '/de'+'scargas/', PRE = 'takana-'+'instalador-';
- var PESO = { base: {sh:144662539, img:544210944},
- mirada: {sh:549945194, img:1680867328},
- servidor: {sh:608553087, img:3334471680},
- full: {sh:0, img:18278776832} };
+ var PESO = { base: {sh:85317423, img:374341632},
+ mirada: {sh:325502854, img:1067450368},
+ servidor: {sh:405219154, img:2535456768},
+ full: {sh:0, img:9225371648} };
var notaFull=document.getElementById('nota-full');
var bSh=document.getElementById('bloque-sh'),
preSh=document.getElementById('cmd-sh'), preImg=document.getElementById('cmd-img'),