puerta 5 cerrada: repo.gioser.net sirve el repo FIRMADO, y el guion aprende cómo se recarga esta caja
`takana install zsh --repo https://repo.gioser.net --trust ./trust --require-signed` ⇒ `release: trusted (by release)`, 1331 ficheros en 0,286 s, zsh 5.9 corriendo. 173 paquetes anclados, 0 sin ancla, certificado CN=repo.gioser.net de Let's Encrypt. Tres cosas que sólo se supieron al poder entrar como root, y que el guion ahora sabe: · `caddy reload` NO funciona acá: el Caddyfile lleva `admin off` y el reload habla por ese admin (de ahí que el :2019 estuviera siempre cerrado). La recarga real es `arjectl restart caddy` — caddy es un Ente de arje con Restart{1000,30000}, no un proceso suelto. · Un restart levanta los 19 dominios o ninguno, así que el guion saca un TESTIGO de la config previa (acá gitea.gioser.net), espera a que responda, y si no vuelve restaura y revierte. Comprobado después: los 8 dominios vivos siguen en pie. · El certificado tarda más que la comprobación: el guion dio «todavía no responde» y la misma URL daba 200 segundos después. El mensaje ahora manda reintentar antes de ir a leer logs. Y dos fallos míos, medidos: backticks dentro de comillas y de un heredoc sin entrecomillar se EJECUTAN (salió un `journalctl: not found` en mitad de un mensaje de ayuda), y `[ -n "$X" ] && echo` como última orden mata el guion entero bajo `set -e`. El espejo provisional sin firmar de takana.gioser.net/repo se borró: con el firmado en pie, un origen sin firma no es un origen.
This commit is contained in:
@@ -563,12 +563,12 @@ curl -H "Authorization: Bearer $TOKEN" https://api.hetzner.cloud/v1/zones
|
||||
curl -H "Authorization: Bearer $TOKEN" https://api.hetzner.cloud/v1/zones/986350/rrsets
|
||||
```
|
||||
|
||||
Hoy el nombre resuelve y **no sirve nada**: `http://repo.gioser.net` da el 308 global de Caddy y el
|
||||
HTTPS muere en el handshake (`tlsv1 alert internal error`) porque no hay site block ⇒ no hay
|
||||
certificado. Falta el vhost, que es root y va a mano: `scripts/servidor/publicar-repo.sh` publica y
|
||||
firma en `/srv/repo`, comprueba el lazo y **imprime el bloque sin tocar el Caddyfile** — en esta
|
||||
caja Caddy sirve 19 dominios y su config ya acumula 20 `.bak`; un guion que la reescribe a ciegas es
|
||||
cómo se tiran 19 sitios para levantar uno.
|
||||
Durante unas horas el nombre resolvió y **no sirvió nada** —`http://` daba el 308 global de Caddy y
|
||||
el HTTPS moría en el handshake (`tlsv1 alert internal error`) porque sin site block no hay
|
||||
certificado—, hasta que se pudo entrar como root a la caja. **Cerrado el 2026-09-21** con
|
||||
`scripts/servidor/publicar-repo.sh --install-vhost`, que publica y firma en `/srv/repo`, añade el
|
||||
bloque y lo aplica; por defecto **imprime el bloque sin tocar el Caddyfile**, porque en esta caja
|
||||
Caddy sirve 19 dominios y su config ya acumula 20 `.bak`.
|
||||
|
||||
⚠ **Publicar no es construir, y `repo-perfil.sh` no lo acotaba.** `pack --build` es instantáneo con
|
||||
cache-hit y una **compilación entera** si el artefacto no está sellado. Medido al ensayar el guion:
|
||||
@@ -630,33 +630,50 @@ disfraza de «al día»: lo dice, sale ≠ 0 y **conserva el último estado buen
|
||||
lab. El aviso llega a cualquiera; el `install` que lo resuelve sigue siendo reproducir desde fuente
|
||||
(§5.4). Por eso `outdated` **no actualiza**: instalar es verificar, y eso no se cuelga de un cron.
|
||||
|
||||
### 5.8 El espejo provisional en `takana.gioser.net/repo` — y por qué va SIN FIRMAR *(2026-09-21)*
|
||||
### 5.8 Puerta 5, de verdad: `repo.gioser.net` sirve el repo firmado *(2026-09-21)*
|
||||
|
||||
Mientras `repo.gioser.net` espera su vhost (root, §5.7), el catálogo está servido bajo el sitio que
|
||||
Caddy ya atiende: `/work/sergio/gioser-web/takana/repo`, que es un árbol **escribible sin root** y
|
||||
con certificado válido. 173 paquetes, y `install zsh` desde la URL pública tarda **0,22 s** (1331
|
||||
ficheros) y el binario corre.
|
||||
```
|
||||
$ takana install zsh --repo https://repo.gioser.net --trust ./trust --require-signed
|
||||
release: trusted (by release)
|
||||
repo: bajados 6 .swm de https://repo.gioser.net
|
||||
caché: artefacto ya en el store hash=b3:0be3630d… name=zsh
|
||||
→ hidratados 1331 archivo(s) real 0m0,286s
|
||||
```
|
||||
|
||||
**El índice va sin firma a propósito, y eso es lo único honesto que se podía hacer.** La clave de
|
||||
release vive en `/root/.config/takana/keys` de la caja y desde la jaula no se alcanza. Firmarlo con
|
||||
otra clave habría sido *peor* que no firmarlo: una autoría inventada se lee igual que una real, y es
|
||||
exactamente la «firma sin gestión de claves» que `repo-perfil.sh` se niega a hacer (SDD 19 §3.2). Se
|
||||
le quitó al índice la firma de la clave de prueba con la que se había ensayado. Control:
|
||||
`--require-signed` lo **rechaza** — `Error: el repo no tiene firma de release`.
|
||||
**173 paquetes anclados, 0 sin ancla**, índice firmado con la clave de release de la caja y
|
||||
certificado `CN=repo.gioser.net` de Let's Encrypt. Los 2 que faltan (`os-release`, `rust`) no
|
||||
estaban sellados y el `SKIP_UNSEALED` los saltó en vez de ponerse a compilar.
|
||||
|
||||
Lo que sí conserva su valor: cada entrada lleva su `expected_hash` anclado, así que `install`
|
||||
reconstruye desde fuente y **compara**. Lo que no se puede verificar acá es *quién* armó el
|
||||
catálogo, no si el binario sale de la fuente que dice.
|
||||
**Lo que había que descubrir para poder aplicarlo, y no estaba escrito en ningún sitio:**
|
||||
|
||||
Dos cuidados que lleva puestos, porque vive dentro del clon de git de otra web:
|
||||
- **`caddy reload` NO sirve en esta caja.** El Caddyfile lleva `admin off` (por eso el `:2019`
|
||||
siempre estuvo cerrado) y el `reload` de Caddy habla justamente por ese admin. La recarga real es
|
||||
**`arjectl restart caddy`**: caddy es un Ente de arje (`/etc/arje/cards.d/caddy.json`,
|
||||
`Restart{initial:1000,max:30000}`), no un proceso suelto.
|
||||
- **Un restart no es un reload: levanta los 19 dominios o ninguno.** Por eso el guion saca un
|
||||
**testigo** de la config PREVIA —el primer dominio con nombre propio, acá `gitea.gioser.net`— y
|
||||
espera a que vuelva a responder; si no vuelve, restaura la copia y revierte. Comprobado después:
|
||||
los 8 dominios vivos siguen en pie (`gitea` 301 a `git`, el resto 200).
|
||||
- **El certificado tarda más que la comprobación.** El guion dio `✗ todavía no responde` y la misma
|
||||
URL respondía **200 unos segundos después**: Caddy pide el certificado en la primera petición.
|
||||
El mensaje ahora dice «reintentá el curl antes de buscar nada» en vez de mandar a leer logs.
|
||||
|
||||
- **`repo/.gitignore` con `*`**: el directorio se ignora a sí mismo. Un `git add -A` en `gioser-web`
|
||||
no se lleva 173 `.tkn` por delante. Comprobado: `git status` del clon sigue limpio.
|
||||
- **`hermanas.py` no lo borra**: sólo escribe `takana/index.html` y `hifas/index.html`, no arrasa el
|
||||
directorio, así que el espejo sobrevive a `publicar-webs.sh`.
|
||||
**El espejo provisional se quitó.** Mientras no hubo root, el catálogo estuvo servido **sin firmar**
|
||||
bajo `takana.gioser.net/repo` (un árbol escribible sin root, con certificado válido). Funcionó
|
||||
—`install zsh` en 0,22 s— y sirvió para probar el mecanismo, pero un origen sin firma no es un
|
||||
origen: con `repo.gioser.net` firmado en pie, se borró. Lo que quedó de aquello vale la pena
|
||||
recordarlo: **firmar con una clave que no es la de release habría sido peor que no firmar**, porque
|
||||
una autoría inventada se lee igual que una real; se publicó sin firma y con `--require-signed`
|
||||
rechazándolo, que es lo único honesto que se podía hacer sin la clave.
|
||||
|
||||
Se quita con `rm -rf /work/sergio/gioser-web/takana/repo` el día que `repo.gioser.net` sirva el
|
||||
firmado. **No es un espejo del ADR 0014**: un origen sin firma no cuenta como origen alternativo.
|
||||
⚠ **Sigue siendo un solo origen** (ADR 0014). La caja se sirve a sí misma; la lista de `--repo` de
|
||||
los clientes debería llevar también el Storage Box. El primer origen roto, si es el único, es el
|
||||
último.
|
||||
|
||||
⚠ **Y el aviso periódico no está cableado en la caja a propósito**: `/var/lib/hammer/installed.json`
|
||||
no existe ahí —ningún paquete se instaló por `takana install`, el sistema viene de imágenes—, así
|
||||
que `avisar-actualizaciones.sh` sólo diría «nada instalado» cada 30 minutos. Se enchufa el día que
|
||||
la caja consuma su propio repo, que es el §6.46 visto desde el otro lado.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user