# `takana-os.net` — el sitio del proyecto Una sola página, autocontenida, en dos idiomas y dos temas. **No le pide nada a terceros:** las tipografías de la marca (Chivo e IBM Plex, las dos SIL OFL) viajan acá en `fuentes/`, subconjuntos `latin` y `latin-ext`, 154 KB en total. Un sitio sobre no depender de binarios ajenos que cargara las fuentes de Google en cada visita sería una contradicción barata. | | | |---|---| | `index.html` | la página entera: CSS y JS adentro, el símbolo como `` SVG inline | | `fuentes.css` + `fuentes/` | las ocho caras `@font-face`, servidas de acá | | `simbolo.svg` | el favicon — el martillo tocapu 7×7, derivado de `docs/marca/simbolo-fondo-claro.svg` | ## La sección «las decisiones» Diez fichas, cada una con tres lecturas de lo mismo: contra qué se decide, qué implica por dentro, y qué quiere decir sin jerga. **No son opinión: cada una sale de un ADR o de una decisión ya tomada en `docs/`** — fuentes clavadas (ADR 0006), `zig cc` (0003), `arje` de init (0007) y el arranque por grafo (0010), multi-origen con índice firmado (0014), imágenes ajenas enjauladas (0015), y las de Wayland-only y PipeWire, que viven en los frentes de escritorio y audio. ⚠ **Si una decisión cambia, esta página miente hasta que alguien la toque.** Es el precio de explicar el diseño en una landing y no en un doc generado: se gana claridad y se paga en mantenimiento. Las fichas se armaron con un guion de un solo uso — la página es la fuente, no hay generador que mantener. La paleta y la tipografía salen de **`docs/marca/README.md`** y no se inventan acá. La única desviación, deliberada: en tema claro el texto de acento usa un brasa oscurecido (`#9E3F16`), porque el `#DF6B2A` de la marca sobre alpaca da 2,9:1 y no se lee. Las combinaciones de la página están medidas: ninguna baja de 4,5:1. ## El instalador: `/descargas/` vive FUERA del repo `https://takana-os.net/descargas/takana-instalador.run` es **un fichero que trae todo adentro**: cabecera `sh` + un `tar.gz` pegado detrás con el binario `takana`, el instalador que corre en RAM, su kernel y el censo del terreno. Se baja, se le da permiso y se corre; no baja nada más. ⚠ **No está en el repo, y no puede estarlo.** Son 137 MiB: en git serían 137 MiB para siempre en cada clon, y además **el espejo de GitHub rechaza cualquier fichero de más de 100 MiB** — o sea que el `push` se rompería y nadie relacionaría la causa con el sitio. Vive en `/work/sergio/descargas`, que está en `sdc` (255 G) y no en la raíz de 5,8 G, que se llena y tira la caja entera. ```sh scripts/instalador-paquete.sh # arma el paquete (y comprueba su coherencia) scripts/instalador-autoextraible.sh # lo convierte en UN fichero, y lo desempaqueta para probarlo cp work/takana-instalador.run /work/sergio/descargas/ ( cd /work/sergio/descargas && sha256sum takana-instalador.run > takana-instalador.run.sha256 ) ``` El `.sha256` que se publica al lado es **el del fichero entero**, para comprobar la descarga (`sha256sum -c takana-instalador.run.sha256`). Es distinto del que el `.run` lleva adentro, que es el **del payload** y lo verifica él solo antes de desempaquetar (`./takana-instalador.run --sha256` lo imprime). ⚠ **El hash NO se escribe en `index.html`, y es deliberado.** La primera versión lo traía pegado en la página y habría empezado a mentir en el primer rebuild — que es el modo de fallo que este mismo README ya avisa para la sección «las decisiones». La página muestra el comando; el número lo sirve el fichero de al lado, que se regenera junto al `.run`. ⚠ `/descargas` queda **fuera del `encode`** del vhost: el `.run` ya viene comprimido, y volver a comprimirlo por HTTP gasta CPU en cada descarga sin ahorrar un byte. ### La imagen USB, para cuando el salto no se puede `takana-instalador-usb.img` (519 MiB) es **el mismo instalador por otro camino**: mismo árbol, mismo censo, mismas guardas. Se graba con `dd` y arranca por la ruta de medios removibles del firmware. ⚠ **No lleva el instalador en la ESP, y no es un capricho:** el cuelgue del primer viaje a metal fue un initrd de ~100 MiB cargado por el EFI-stub ([ADR 0010](../../docs/adr/0010-arranque-grafo-mirada.md) paso 2), y el del instalador son ~122 MiB. El USB usa el patrón que **sí** está probado —el de un disco instalado—: la ESP lleva el kernel y un pivote de 736 KiB, y el pivote encuentra la ext4 por `LABEL=takana-medio` y hace `switch_root`. La etiqueta NO es `hammer-root` a propósito: si el medio se llamara igual que la raíz de un sistema instalado, el pivote podría montar el disco del usuario en vez del USB, y el que pierde es el disco. ```sh scripts/instalador-usb.sh # arma work/takana-instalador-usb.img scripts/instalador-usb-test.sh --instalar # lo arranca en OVMF y lo contesta por el serial cp work/takana-instalador-usb.img /work/sergio/descargas/ ( cd /work/sergio/descargas && sha256sum takana-instalador-usb.img > takana-instalador-usb.img.sha256 ) ``` **Está probado de punta a punta, no sólo servido:** `VIA_RUN=1 scripts/metal-salto-test.sh` mete el fichero publicado en una VM con `linux-metal-kexec`, lo corre, y comprueba sobre el DISCO que se verificó solo, se desempaquetó, saltó e instaló — 13 comprobaciones, con el `bootmgfw.efi` del vecino byte a byte igual y la tabla de particiones sin cambiar. Y el USB, `scripts/instalador-usb-test.sh --instalar`: **arranca por firmware de verdad** (OVMF por `pflash`, sin `-kernel`, que es la única forma de probar la tabla, la ESP, el stub y el nombre `\initramfs.cpio.gz` que el cmdline horneado exige), **contesta el menú tecleando por el serial** y comprueba el disco destino. 12 en verde. ⚠ El arnés corre con `-vga none`, y eso decide qué rama del código se prueba: sin pantalla el instalador detecta el `vtconsole` `dummy` y se va al serial. **Con** pantalla —el caso del usuario— la pregunta sale por `tty0`. Las dos ramas existen porque el cmdline HORNEADO del kernel pone `tty0` primero y `ttyS0` último, o sea que `/dev/console` es el serial: en un portátil sin puerto serie, sin esta detección, el censo y la pregunta se irían a un sitio que no existe y el arranque parecería colgado. ## Las dos direcciones que publica - **código** → `https://git.gioser.net/sergio/takana` (público; `git clone` por HTTPS) - **paquetes** → `https://takana-os.net/repo/`, que es el MISMO `/srv/repo` firmado que sirve `repo.gioser.net`. Comprobado: `takana install age --repo https://repo.gioser.net --trust ./trust` responde `release: trusted (by release)`. Y **desde el 2026-09-21 se puede mirar el repo sin construir nada**, que antes no se podía: `repo list` y `repo verify` aceptan la misma lista de orígenes que `install`. Hasta ese día sólo miraban directorios locales y ante una URL respondían «repo vacío» **con salida 0** — 173 paquetes leídos como ninguno. ```sh takana repo list --repo https://takana-os.net/repo # 173 paquete(s) takana repo verify --repo https://takana-os.net/repo --trust ./trust # release: trusted ``` ## Cómo se sirve Caddy, en la caja `takana`, vhost `takana-os.net, www.takana-os.net`. La raíz es **`/work/sergio/takana/web/takana-os.net`**, el árbol de trabajo vivo: *publicar es guardar el fichero*. No lo refresca `publicar-webs.sh` a propósito — un `pull` sobre el árbol compartido mueve HEAD bajo los pies de otro agente (CLAUDE.md §2 ter). Este README **no se sirve**: son notas de operación, y el matcher del vhost las 404ea. Los bloques, por si hay que rehacer la caja (`caddy validate` → `arjectl restart caddy`, **nunca** `caddy reload`: el Caddyfile lleva `admin off`, SDD 28 §6.14): ```caddyfile takana-os.net, www.takana-os.net { import acceso @comprimible not path /descargas/* encode @comprimible gzip zstd redir /descargas /descargas/ permanent handle_path /descargas/* { root * /work/sergio/descargas file_server browse } redir /repo /repo/ permanent handle_path /repo/* { root * /srv/repo file_server browse } handle { root * /work/sergio/takana/web/takana-os.net @oculto path /.* */.* /README.md respond @oculto 404 file_server } } git.takana-os.net { import acceso redir https://git.gioser.net{uri} permanent } takana.gioser.net { import acceso redir https://takana-os.net{uri} permanent } ``` `scripts/servidor/publicar-webs.sh` comprueba los cuatro: los dos que sirven ficheros por sha contra el disco, y los dos que redirigen por destino. ## Los nombres | nombre | qué hace | estado | |---|---|---| | `takana-os.net`, `www` | el sitio | ✅ con certificado de Let's Encrypt (2026-09-21) | | `takana-os.net/repo/` | el repo de paquetes, el mismo `/srv/repo` | ✅ | | `takana-os.net/descargas/` | el instalador en UN fichero, y la imagen USB (`/work/sergio/descargas`) | ✅ (2026-09-23) | | `takana.gioser.net` | **301 → `takana-os.net`** | ✅ | | `git.takana-os.net` | **301 → `git.gioser.net`** | ⏳ vhost puesto, **falta el registro A** | `git.takana-os.net` sólo redirige, y es deliberado: gitea tiene UN `ROOT_URL` con el que arma cada enlace y cada URL de clon que muestra, así que colgarlo de un segundo nombre daría un sitio que se contradice —entrás por uno y te ofrece clonar del otro— y moverlo de verdad rompe los clones y el CI que ya apuntan al viejo. Los registros van a `2.29.29.217`, la IP de la caja: ``` takana-os.net. A 2.29.29.217 ✅ puesto www.takana-os.net. A 2.29.29.217 ✅ puesto git.takana-os.net. A 2.29.29.217 ⏳ falta ``` El certificado sale solo en la primera petición tras el DNS — y **tarda unos segundos más que el primer `curl`**: si da error, reintentar antes de ir a mirar logs (SDD 28 §6.14). Si el nombre ya resolvía cuando Caddy arrancó pero el certificado no llegó, **reiniciar caddy fuerza el reintento** sin esperar el backoff: fue lo que hizo falta acá.