servidor: repo.gioser.net existe (A → 2.29.29.217) y el guion que lo publica sin tocar el Caddyfile

El nombre está dado de alta en la zona de Hetzner con la convención de la zona (A, ttl 60, la misma
IP que takana/git/gitea/www). Resuelve — comprobado contra Cloudflare; el resolutor de Google aún
servía el NXDOMAIN cacheado, que es negativo de 1 h por el `minimum` del SOA y no un fallo del alta.

⚠ La API vieja de DNS de Hetzner (dns.hetzner.com/api/v1) ya no es la buena y devuelve HTML de la
consola web, que es lo peor que puede devolver: no falla, contesta. Las zonas están hoy en la API de
cloud y las lee el MISMO token de ~/.config/hcloud/cli.toml (gioser.net = zona 986350).

Hoy el nombre resuelve y no sirve nada: falta el vhost, que es root. `publicar-repo.sh` hace la
parte publicable —repo firmado en /srv/repo + verificación contra trust/— y para imprimiendo el
bloque de Caddy en vez de editarlo: esta caja sirve 19 dominios y su Caddyfile ya lleva 20 `.bak`.

Y aborta antes de publicar si el takana de la caja es anterior al arreglo del SDD 28 §5.5 (se
detecta porque no conoce `outdated`): con uno viejo el repo sale con las 16 recetas multi-parche
irreproducibles y 8 paquetes prometiendo un binario que no existe.
This commit is contained in:
Sergio
2026-09-21 18:41:32 +00:00
parent 7be17b5a2a
commit 0d6599ac14
2 changed files with 108 additions and 0 deletions
+29
View File
@@ -546,6 +546,35 @@ habría hidratado y muerto al final. Comprobado después del arreglo, contra el
por HTTP: `parted` (6 parches **y** binario en `/usr/sbin`) instala en 0,17 s y responde
`parted (GNU parted) 3.7`; `bash` instala y responde `5.3.0(1)-release`.
### 5.7 El nombre ya existe: `repo.gioser.net` *(2026-09-21)*
Dado de alta en la zona de Hetzner (la DNS de `gioser.net` está ahí: `helium`/`hydrogen`/`oxygen`),
con la convención que ya usaban `takana`, `git`, `gitea`, `sergio` y `www`: **`repo` A →
2.29.29.217, ttl 60**. Resuelve *(comprobado contra Cloudflare; el resolutor de Google todavía
servía el NXDOMAIN cacheado — negativo de 1 h por el `minimum` del SOA, no es un fallo del alta)*.
**La API vieja de DNS de Hetzner ya no es la buena.** `dns.hetzner.com/api/v1/zones` con
`Auth-API-Token` devuelve **HTML de la consola web** (301 → 200 de una SPA), que es lo peor que
puede devolver: no falla, contesta. Las zonas viven hoy en la **API de cloud** y las lee el MISMO
token de `~/.config/hcloud/cli.toml`:
```sh
curl -H "Authorization: Bearer $TOKEN" https://api.hetzner.cloud/v1/zones # gioser.net = 986350
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.
**Y trae su propia guarda contra el error más fácil de cometer:** si el `takana` de la caja es
anterior al §5.5 (se detecta porque no conoce `outdated`), **aborta antes de publicar**. Con uno
viejo el repo sale con las 16 recetas multi-parche irreproducibles y 8 paquetes prometiendo un
binario que no existe — y eso no se nota hasta que alguien instala.
**Lo que queda vivo y no se tocó:** un `install <librería>` DIRECTO sigue fallando tras hidratar,
porque el `.swm` exige que el `target_bin` exista y para una librería no hay respuesta buena. Hacer
`target_bin` opcional toca el formato ([SDD 06](06-swm-format.md)) y es su propia unidad de trabajo.
+79
View File
@@ -0,0 +1,79 @@
#!/bin/sh
# publicar-repo.sh — deja el repo FIRMADO servido en `repo.gioser.net`. Se corre EN LA CAJA, como
# root (la clave privada de release vive en `/root/.config/takana/keys/`, SDD 28 §2116).
#
# ── QUÉ HACE ────────────────────────────────────────────────────────────────────────────────────
# 1. publica la clausura del perfil en `/srv/repo` con `repo-perfil.sh` (que ABORTA si no está la
# clave: un índice firmado con una efímera que nadie conoce no lo verifica nadie),
# 2. comprueba que el índice verifica contra `trust/`,
# 3. dice si Caddy ya sirve el nombre, y **si no, imprime el bloque y para**.
#
# ── POR QUÉ NO EDITA EL CADDYFILE ───────────────────────────────────────────────────────────────
# En esta caja Caddy sirve 19 dominios y su Caddyfile ya acumula 20 `.bak` (SDD 28 §1). Un guion que
# lo reescribe a ciegas es cómo se tiran 19 sitios para levantar uno. El bloque va a mano, una vez:
#
# repo.gioser.net {
# root * /srv/repo
# file_server browse
# }
#
# y después `caddy reload --config /etc/caddy/Caddyfile`. El DNS ya está: `repo` A → 2.29.29.217,
# ttl 60, en la zona de Hetzner (dado de alta el 2026-09-21).
#
# ⚠ **Un solo origen es exactamente lo que el ADR 0014 existe para no tener.** Esta caja sirviéndose
# a sí misma está bien como camino normal, pero el `--repo` de los clientes debería llevar también
# el Storage Box: el primer origen roto, si es el único, es el último.
#
# Uso: sudo scripts/servidor/publicar-repo.sh [perfil]
# Env: PERFIL (def servidor) · STORE (def /store) · DESTINO (def /srv/repo)
# NOMBRE (def repo.gioser.net) · TRUST (def ./trust)
set -eu
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
PERFIL="${1:-${PERFIL:-servidor}}"
STORE="${STORE:-/store}"
DESTINO="${DESTINO:-/srv/repo}"
NOMBRE="${NOMBRE:-repo.gioser.net}"
TRUST="${TRUST:-$ROOT/trust}"
TAKANA="${TAKANA:-$ROOT/target/release/takana}"
[ "$(id -u)" = "0" ] || { echo "!! corré esto como root: la clave de release está en /root/.config/takana/keys/" >&2; exit 2; }
[ -x "$TAKANA" ] || { echo "!! falta $TAKANA (cargo build --release)" >&2; exit 2; }
# ⚠ El binario TIENE que traer el arreglo de los parches múltiples y del target_bin (SDD 28 §5.5):
# con uno anterior, las 16 recetas con ≥2 parches se publican irreproducibles y 8 paquetes más
# (bash, sed, tar, parted, dhcpcd, squid, wpa_supplicant, zsh) prometen un binario que no existe.
"$TAKANA" outdated --help >/dev/null 2>&1 || {
echo "!! este $TAKANA es anterior al arreglo del SDD 28 §5.5 (no conoce 'outdated')." >&2
echo " Reconstruilo —cargo build --release— antes de publicar, o el repo sale roto." >&2
exit 2
}
echo "==> publicando el perfil '$PERFIL' en $DESTINO"
install -d -m 755 "$DESTINO"
PERFIL="$PERFIL" STORE="$STORE" REPO="$DESTINO" TRUST="$TRUST" "$ROOT/scripts/repo-perfil.sh" "$PERFIL"
echo
echo "==> ¿lo sirve Caddy?"
if curl -fsS -m 10 "https://$NOMBRE/index.json" -o /dev/null 2>/dev/null; then
echo " ✓ https://$NOMBRE/index.json responde"
echo
echo " probalo desde cualquier hub (necesita el lab: install reproduce desde fuente):"
echo " takana install zsh --repo https://$NOMBRE --trust ./trust --require-signed"
echo " y el aviso periódico:"
echo " REPO=https://$NOMBRE scripts/servidor/avisar-actualizaciones.sh"
else
cat <<EOF
✗ https://$NOMBRE todavía no responde. El repo YA está publicado y firmado en $DESTINO;
lo que falta es el vhost. Añadí a /etc/caddy/Caddyfile:
$NOMBRE {
root * $DESTINO
file_server browse
}
y recargá: caddy reload --config /etc/caddy/Caddyfile
Después volvé a correr este guion: comprueba el lazo entero en vez de darlo por hecho.
EOF
exit 1
fi