From 0bb40af496534d6f982a170368cfad1b07b0cacd Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 17 Sep 2026 19:36:03 +0000 Subject: [PATCH] la caja trae fuentes git por SSH: el arreglo, en un guion idempotente MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lo que hasta ahora era estado a mano en la caja queda reproducible. Hace las cinco piezas medidas: reescritura de URLs con url.insteadOf, la clave del host reexpresada SIN puerto (cargo la busca así), la huella de github.com PINEADA contra la publicada —si no coincide, sale con error en vez de aceptarla—, la IdentityFile por host, y `net.git-fetch-with-cli = true` para que cargo delegue en el git de verdad. Además mueve CARGO_HOME fuera de la raíz de 5,9 G, que es lo que tiró la caja. No mueve ningún hash: la URL es un localizador y no entra en hash_inputs (ADR 0013). Termina con un control que CLONA de los dos orígenes; si alguno no llega, sale distinto de cero. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/servidor/fuentes-por-ssh.sh | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 scripts/servidor/fuentes-por-ssh.sh diff --git a/scripts/servidor/fuentes-por-ssh.sh b/scripts/servidor/fuentes-por-ssh.sh new file mode 100755 index 00000000..625fa119 --- /dev/null +++ b/scripts/servidor/fuentes-por-ssh.sh @@ -0,0 +1,76 @@ +#!/bin/sh +# Deja la caja de producción capaz de TRAER FUENTES GIT — que hoy no puede por HTTPS. +# +# ── POR QUÉ (2026-09-17) ──────────────────────────────────────────────────────────────────────── +# El `git` sellado del corpus no trae `git-remote-http` (falta libcurl): en la caja, cualquier receta +# que clone muere con +# +# git: 'remote-https' is not a git command +# +# y eso son 36 recetas de tawasuyu y ~90 de GitHub — o sea, casi todo lo propio. La salida es traer +# por SSH. **No cuesta ningún hash**: la URL es un LOCALIZADOR y no entra en `hash_inputs` +# (ADR 0013), así que el mismo commit por otro transporte sella el MISMO artefacto. Por eso esto no +# toca ninguna receta: el worker sigue clonando por HTTPS, que es lo que él sí puede. +# +# Idempotente. Se corre EN LA CAJA, como root. +set -eu + +CONF_SSH=/root/.ssh/config +CONF_GIT=/root/.gitconfig +CONF_CARGO=/root/.cargo/config.toml +KH=/root/.ssh/known_hosts + +# ── 1. reescritura de URLs ─────────────────────────────────────────────────────────────────────── +git config --global url."ssh://gitea@git.gioser.net:2345/".insteadOf "https://git.tawasuyu.net/" +git config --global url."ssh://git@github.com/".insteadOf "https://github.com/" + +# ── 2. la clave del host, SIN el puerto ────────────────────────────────────────────────────────── +# cargo tiene su propio cliente SSH y busca `git.gioser.net` pelado; con la entrada sólo como +# `[git.gioser.net]:2345` se planta con «This host key was found, but is associated with a different +# host». Es la MISMA clave, reexpresada — no es aceptar nada nuevo. +if ! grep -q "^git.gioser.net ssh-" "$KH" 2>/dev/null; then + grep "^\[git.gioser.net\]:2345 " "$KH" | sed "s|^\[git.gioser.net\]:2345 |git.gioser.net |" >> "$KH" +fi + +# ── 3. github.com: la huella se PINEA contra la publicada, no se acepta a ciegas ───────────────── +GH_FP="SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU" +if ! grep -q "^github.com ssh-ed25519" "$KH" 2>/dev/null; then + ssh-keyscan -t ed25519 github.com > /tmp/gh.keys 2>/dev/null + fp=$(ssh-keygen -lf /tmp/gh.keys | awk '{print $2}') + [ "$fp" = "$GH_FP" ] || { echo "github.com anuncia $fp y NO la publicada $GH_FP — no la acepto" >&2; exit 1; } + cat /tmp/gh.keys >> "$KH"; rm -f /tmp/gh.keys +fi + +# ── 4. qué clave usa cada host ─────────────────────────────────────────────────────────────────── +grep -q "^Host github.com" "$CONF_SSH" 2>/dev/null || cat >> "$CONF_SSH" <<'SSHEOF' + +Host github.com + HostName github.com + User git + IdentityFile /root/.ssh/github5 + IdentitiesOnly yes +SSHEOF +chmod 600 "$CONF_SSH" + +# ── 5. cargo delega en el git de verdad ────────────────────────────────────────────────────────── +# Sin esto, `cargo vendor` usa libgit2 y ni lee `IdentityFile` de ~/.ssh/config: +# «no authentication methods succeeded». Es fetch, no build: no toca ningún hash. +mkdir -p "$(dirname "$CONF_CARGO")" +grep -q "git-fetch-with-cli" "$CONF_CARGO" 2>/dev/null || printf '[net]\ngit-fetch-with-cli = true\n' >> "$CONF_CARGO" + +# ── 6. CARGO_HOME NO puede vivir en la raíz ────────────────────────────────────────────────────── +# Son 5,9 G. El vendor del monorepo bajó 2,7 G, la raíz llegó al 100 % y la caja se CAYÓ ENTERA +# —sin HTTP, sin SSH y sin responder al ping— con Hetzner informando `running` (SDD 28 §6.50 quinquies). +if [ ! -L /root/.cargo ]; then + mkdir -p /work/cargo-home + [ -d /root/.cargo ] && cp -a /root/.cargo/. /work/cargo-home/ && rm -rf /root/.cargo + ln -s /work/cargo-home /root/.cargo +fi + +# ── control: que de verdad LLEGUE, no que el fichero exista ───────────────────────────────────── +fallos=0 +for u in "https://git.tawasuyu.net/tawasuyu/tawasuyu.git" "https://github.com/uutils/coreutils.git"; do + if timeout 45 git ls-remote "$u" >/dev/null 2>&1; then echo " ✓ $u"; else echo " ✗ $u"; fallos=$((fallos+1)); fi +done +[ "$fallos" -eq 0 ] || { echo "NO llega a $fallos origen(es)" >&2; exit 1; } +echo "la caja trae fuentes git por SSH"