la mudanza sin terceros: las fuentes de tawasuyu por HTTPS público, y el orden del cutover

Tres cosas, y las tres quitan vueltas.

1. NO HACE FALTA NINGUNA CREDENCIAL EN EL WORKER, Y TAMPOCO UN USUARIO NUEVO

`tawasuyu/tawasuyu` y `sergio/takana` son repos PÚBLICOS en el gitea. Las 23 recetas que apuntaban a
`gitea@git.tawasuyu.net` (SSH, que exige la clave que es el SSH de todo) pasan a
`https://git.tawasuyu.net/…`. La URL es locator y NO entra en `hash_inputs` (ADR 0013): hecho con
control antes/después, **ningún ArtifactHash se movió**. Medido en el worker: `git clone --mirror
--filter=blob:none` + `git archive` extrae el árbol (155 M) **sin una sola credencial**.

Un usuario propio en gitea sólo haría falta para un repo PRIVADO; hoy ninguna receta usa uno. Si
mañana hace falta, es una cuenta de máquina con acceso al repo que toque — nunca la clave personal.

De paso, tres recetas decían «HUB-ONLY: el worker secretless recibe Connection refused». Ya no es
cierto y el comentario decía lo contrario de lo que pasa: corregido en las tres.

2. LA COPIA FUERA LA DA LA MUDANZA, NO GITHUB (decisión del usuario)

El «paso 1: espejar los 26 repos» deja de ser el paso 1. En cuanto el gitea vive en la caja nueva,
esos repos dejan de existir sólo en la máquina que se borra — que es lo que el paso pedía. El
objetivo es dejar de pagar dos máquinas, no sumar una dependencia. `espejar-repos.sh` queda como
herramienta disponible.

3. EL §9 REESCRITO: qué está hecho, qué falta y en qué orden

Hecho y cerrado: la caja arranca takana puro · store/grafos/granja/respaldo · repo firmado · la
imagen del perfil servidor con gitea sirviendo 200 supervisado por arje · `arjectl` · y el ensayo con
los datos REALES de gioser corriendo sobre takana.

Falta, en orden: actualizar la caja a la imagen nueva (`upgrade`, no `dd`) → mudar los datos del
gitea (`.backup` + rsync, con el origen parado en el corte) → caddy con los 6 dominios vivos → DNS →
verificar desde fuera con un clone real → el resto de servicios del censo → borrar gioser con las 8
puertas en verde.

Bloqueantes con su tamaño: `git` sellado sin `remote-http` (afecta a clonar DESDE una caja takana,
no al gitea que sirve; re-sella una raíz de `base`) y la puerta 5, que no bloquea la mudanza.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
This commit is contained in:
Sergio
2026-09-14 18:59:31 +00:00
co-authored by Claude Opus 5
parent 5b98d1b2bf
commit 4d77d232d3
25 changed files with 93 additions and 43 deletions
+49 -12
View File
@@ -1174,16 +1174,53 @@ del store a propósito. Queda anotado para que se **decida**, no para que se des
## 9. Estado y orden
| paso | estado |
|---|---|
| **0.** `perfil.servidor` + este documento + el renombre `hammer-*` de los instaladores | ✅ **2026-09-09** |
| **1a.** caja de sacrificio creada — `cx33` (no había `cx53`), hel1, §3.5 | ✅ **2026-09-10** |
| **1b.** imagen del `perfil.servidor` + rescue → `dd` → arranca takana puro (§3) | ✅ **2026-09-10** — puerta 1 pasada, §3.8 |
| **2a.** clave estable + receta de `takana` + repo firmado servido por la caja (§5.1) | ✅ **2026-09-10** |
| **2b.** que el host se actualice DESDE su propio repo (§5.4) | 🚧 bloqueado por la decisión de [SDD 27 §4](27-perfiles-instalables-y-el-instalador.md): `install` reproduce, y eso exige el lab entero |
| **3.** mudanza con las 8 puertas del §6, y recetas nuevas del §6.2 | pendiente |
| **4.** la utilidad de absorción (§4), estrenándose con esta migración | pendiente |
| **5.** `churay` como instalador centralizado (§8) | ADR propio, sin decidir |
**Decisión del usuario (2026-09-14): la mudanza NO pasa por terceros.** Nada de espejar a GitHub
para «tener copia fuera»: la copia fuera **la da la propia mudanza** — en cuanto el gitea vive en la
caja nueva, los 26 repos dejan de existir sólo en la máquina que se borra. El objetivo es dejar de
pagar dos máquinas, no montar una dependencia más. `scripts/mudanza/espejar-repos.sh` queda como
herramienta disponible, no como paso del plan.
**El volumen del store NO se engancha a la caja nueva hasta que pase la puerta 1.** Una caja de
sacrificio con el store dentro deja de ser de sacrificio.
**Y el worker no necesita credenciales: las fuentes de tawasuyu se sirven por HTTPS público.**
Las 23 recetas que apuntaban a `gitea@git.tawasuyu.net` (SSH) pasaron a `https://git.tawasuyu.net/…`
— la URL es locator y no entra en `hash_inputs` (ADR 0013), así que se cambió **con control y sin
mover un solo ArtifactHash**. Medido en el worker: clona y `git archive` extrae el árbol (155 M) sin
ninguna clave. Un usuario propio en gitea sólo haría falta para un repo PRIVADO, y hoy ninguna
receta usa uno.
### Lo que YA está, y no hay que volver a tocar
| | |
|---|---|
| la caja `takana` (`2.29.29.217`) | arranca takana puro, PID 1 `arje-zero` — §3.8 |
| store, grafos, granja, respaldo | puertas 2, 3, 4 y 7 — §6.3, §6.7, §6.8, §6.10 |
| repo firmado servido por la caja | §5.1 |
| **la imagen del perfil `servidor` con gitea** | **arranca y sirve 200, supervisado por arje** — §6.11 |
| **`arjectl` para operar sin reiniciar** | §6.12 |
| **el gitea de gioser corriendo sobre takana, con sus datos** | ensayo completo — §6.13 |
### Lo que falta para el cutover, en este orden
1. **Actualizar la caja a la imagen nueva** (gitea + `arjectl` + las cuentas de `[[user]]`).
`takana upgrade` está probado (§6.13 del SDD 27 y §5.4 acá); el `dd` es para provisionar, no para
actualizar — sobrescribe el disco local y re-etiqueta la partición.
2. **Mudar los datos del gitea**: `sqlite3 … ".backup"` (1,5 s, consistente con el servidor vivo) +
`rsync -aH` de `/var/lib/gitea` y `/etc/gitea`. El corte final se hace con el gitea del origen
**parado**, para que el último snapshot no pierda escrituras.
3. **Caddy en la caja**: los **6 dominios vivos** del §6.9, con su TLS. Los otros 13 no se mudan.
4. **DNS**: apuntar esos 6 a la IP nueva. El resto de los clones y remotos no se toca — siguen
resolviendo al mismo nombre.
5. **Verificar desde fuera**: cada dominio vivo responde 200 contra la IP nueva **y** un `git clone`
real contra el gitea mudado.
6. **El resto de servicios vivos** del censo (qdrant, squid, act-runner, php-fpm…), por el plan que
`planear.py` ya emite.
7. **Borrar gioser** — sólo con las 8 puertas en verde, a mano, nunca por automatización (§6).
### Bloqueantes conocidos, con su tamaño
- **`git` sellado sin `remote-http`** (§6.13): afecta a clonar POR HTTPS *desde* una caja takana, no
al gitea que sirve. Re-sella `git`, raíz de `perfil.base` ⇒ unidad propia.
- **Puerta 5** sigue a medias: la caja sirve su repo pero no se instala de él (`install` reproduce y
eso exige el lab entero). No bloquea la mudanza; bloquea «el servidor se sirve a sí mismo».
**El volumen del store NO se engancha a la caja hasta que pase la puerta 1** — ya pasó, y el store
local de 68,7 G alcanza, así que la mudanza no depende de mover el volumen de gioser.
+9
View File
@@ -303,6 +303,15 @@ Ninguno de los tres es un log de lo que se hizo: los tres son entradas que se vu
### 4.0 quindecies · ⚠ 26 repositorios existen SÓLO en la máquina que se va a borrar
> **Corrección de rumbo (2026-09-14, decisión del usuario): la copia fuera NO se consigue espejando
> a un tercero, se consigue MUDANDO.** En cuanto el gitea vive en la caja nueva, esos 26 repos dejan
> de existir sólo en la máquina que se borra — que es exactamente lo que este paso pide. El objetivo
> del frente es dejar de pagar dos máquinas, y montar una dependencia con GitHub va en contra.
> `espejar-repos.sh` sigue en el repo como herramienta (redundancia extra el día que se quiera), pero
> **no es el paso 1 del plan**: el paso 1 es mudar el gitea, y el criterio de verificación es el
> mismo de siempre — clonar de verdad desde el destino antes de apagar nada.
Es el hallazgo más grave de este frente, y va por delante de todo lo demás en el plan. Buscando cómo
escribir la receta de `tawasuyu` apareció que **su único remoto es el gitea de gioser**
(`ssh://gitea@git.tawasuyu.net:2345/…`, y `git.tawasuyu.net` resuelve a `204.168.193.248`, que es
+1 -1
View File
@@ -11,7 +11,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+1 -1
View File
@@ -10,7 +10,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+1 -1
View File
@@ -10,7 +10,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+1 -1
View File
@@ -14,7 +14,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+5 -4
View File
@@ -20,16 +20,17 @@
# crates dispersos de `compat/`. `-p arje-compat --bin arje-logind-compat` compila SÓLO este daemon.
# Estático zig-cc (zbus sobre socket unix + tokio + nix; sin loader del host, como todo arje).
#
# HUB-ONLY: fuente `gitea@git.tawasuyu.net` puerto 22 ⇒ el worker secretless recibe Connection
# refused (la gitea escucha en :2345). Se muele en el hub, no en un worker efímero. Ver
# [[rootfs-laptop-worker-divergen]] y el gotcha de recetas tawasuyu en [[frente-gnome]].
# YA NO ES HUB-ONLY (2026-09-14): la fuente pasó a `https://git.tawasuyu.net/…`, que el gitea sirve
# PÚBLICO y sin credencial. Antes apuntaba a `gitea@git.tawasuyu.net` por SSH y el worker —que no
# tiene ni debe tener esa clave— moría con «access rights». La URL es locator y NO entra en
# `hash_inputs` (ADR 0013): el cambio se hizo con control y NINGÚN ArtifactHash se movió.
name = "arje-logind-compat"
version = "0.0.1"
license = "MIT"
[source]
# El `commit` es el identificador inmutable (la URL es sólo locator, no entra al hash).
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "2445fa31c1b3d8b7da037d2434ace976e2444df4"
# El monorepo COMMITEA su propio `vendor/` — `[patch.crates-io] smithay = { path = "vendor/smithay" }`,
# una copia parcheada de smithay que mirada necesita para el tearing. `cargo vendor` de takana escribe
+1 -1
View File
@@ -10,7 +10,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+1 -1
View File
@@ -17,7 +17,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "06184e43a8b3179e41905dc56ba07ec569df1ebb"
[build]
+5 -4
View File
@@ -29,9 +29,10 @@
# un token al grafo y devuelva el resultado. Mientras eso no exista, **cualquier cliente de polkit en
# esta distro está autorizado**, y quien lea esta receta tiene que saberlo.
#
# HUB-ONLY, como toda receta con fuente tawasuyu: el clone va a `gitea@git.tawasuyu.net` por el puerto
# 22 y la gitea escucha en :2345; el worker efímero es secretless por diseño y recibe
# `Connection refused`. Se muele en el hub. Ver [[rootfs-laptop-worker-divergen]].
# YA NO ES HUB-ONLY (2026-09-14): la fuente pasó a `https://git.tawasuyu.net/…`, que el gitea sirve
# PÚBLICO y sin credencial. Antes apuntaba a `gitea@git.tawasuyu.net` por SSH y el worker —que no
# tiene ni debe tener esa clave— moría con «access rights». La URL es locator y NO entra en
# `hash_inputs` (ADR 0013): el cambio se hizo con control y NINGÚN ArtifactHash se movió.
name = "arje-polkit-compat"
version = "0.0.1"
license = "MIT"
@@ -39,7 +40,7 @@ license = "MIT"
[source]
# Mismo commit y misma rama que arje-logind-compat: `selfhost/arje-zero-attest-lockfile` es la única
# que versiona el `Cargo.lock` de la raíz, sin el cual el vendoreo `--locked` no es reproducible.
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "98db584fd28d9ff2bf34c9cf7d7db2e1de0b3fd0"
# El monorepo commitea su propio `vendor/` (la copia parcheada de smithay que mirada necesita) y el
# `cargo vendor` de takana lo pisaría. Ver [[takana-cargo-vendor-clobbers-project-vendor]].
+1 -1
View File
@@ -18,7 +18,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "06184e43a8b3179e41905dc56ba07ec569df1ebb"
[build]
+1 -1
View File
@@ -40,7 +40,7 @@ license = "MIT"
# El `commit` es el identificador inmutable (la URL es sólo locator, no entra al hash). Sin el
# `Cargo.lock` del workspace el monorepo lo gitignora, el fetch vendorea SIN --locked ⇒ las deps
# derivan en el tiempo y arje-zero (y of_tree(stage1)) deja de ser reproducible.
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "98db584fd28d9ff2bf34c9cf7d7db2e1de0b3fd0"
# Este árbol COMMITEA su propio `vendor/` (la copia parcheada de smithay que mirada necesita) y el
# `cargo vendor` de takana lo pisaría. Ver [[takana-cargo-vendor-clobbers-project-vendor]].
+1 -1
View File
@@ -27,7 +27,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "98db584fd28d9ff2bf34c9cf7d7db2e1de0b3fd0"
# Este árbol COMMITEA su propio `vendor/` y el `cargo vendor` de takana lo pisaría — igual que en
# `arje-zero.toml`. Ver [[takana-cargo-vendor-clobbers-project-vendor]].
+1 -1
View File
@@ -11,7 +11,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+1 -1
View File
@@ -14,7 +14,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]
+1 -1
View File
@@ -13,7 +13,7 @@ license = "MIT"
[source]
# El repo del propio takana: el `commit` es el identificador inmutable (la URL es sólo locator y
# no entra al hash de la receta). Subir el commit cuando hammerd avance.
repo = "ssh://gitea@git.gioser.net:2345/sergio/takana.git"
repo = "https://git.gioser.net/sergio/takana.git"
commit = "e9b055121322d3ef8aef8e75738052d5aff0693a"
[build]
+5 -3
View File
@@ -26,8 +26,10 @@
# C-ABI sd-login… los escritorios consultan login1 en RUNTIME por D-Bus»): es cierto para los
# clientes D-Bus y FALSO para mutter, que la enlaza.
#
# HUB-ONLY, como toda receta de fuente tawasuyu: la gitea escucha en :2345 y el worker efímero es
# secretless ⇒ recibe Connection refused en :22. Se muele en el hub.
# YA NO ES HUB-ONLY (2026-09-14): la fuente pasó a `https://git.tawasuyu.net/…`, que el gitea sirve
# PÚBLICO y sin credencial. Antes apuntaba al SSH de la gitea (puerto 2345) y el worker —que no
# tiene ni debe tener esa clave— no podía construirla. La URL es locator y NO entra en
# `hash_inputs` (ADR 0013): se cambió con control y NINGÚN ArtifactHash se movió.
name = "libelogind"
version = "0.0.1"
license = "MIT"
@@ -37,7 +39,7 @@ license = "MIT"
# Rama `selfhost/arje-zero-attest-lockfile`, igual que arje-logind-compat, porque es la única que
# versiona el `Cargo.lock` de la raíz: sin él, el vendoreo `--locked` del fetch no es reproducible
# (el monorepo lo gitignora en main).
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "749edfe41766e098d3eb18561c6a396610c5cd8e"
# El monorepo COMMITEA su propio `vendor/` (`[patch.crates-io] smithay = { path = "vendor/smithay" }`,
# la copia parcheada que mirada necesita para el tearing) y el `cargo vendor` de takana escribe ahí
+1 -1
View File
@@ -17,7 +17,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9a17fefcbf63ba74f45cfabc4e608e391e397b17"
[build]
+1 -1
View File
@@ -11,7 +11,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9a17fefcbf63ba74f45cfabc4e608e391e397b17"
[build]
+1 -1
View File
@@ -16,7 +16,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9a17fefcbf63ba74f45cfabc4e608e391e397b17"
[build]
+1 -1
View File
@@ -14,7 +14,7 @@ license = "MIT"
[source]
# Repo del propio takana (origin). El commit es el identificador inmutable; subirlo cuando netup avance.
repo = "ssh://gitea@git.tawasuyu.net:2345/sergio/takana.git"
repo = "https://git.tawasuyu.net/sergio/takana.git"
commit = "c0545ea40cbf530c9b80fc9a76a20551163574cd"
[build]
+1 -1
View File
@@ -28,7 +28,7 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "3bd1440dcb96cfac085cdc669f1cd9c65b5142e5"
# Obligatorio para cualquier receta desde este monorepo: tawasuyu commitea su propio `vendor/` con
# un `smithay` parcheado por RUTA, y el `cargo vendor` de takana convertiría ese directorio en uno
+1 -1
View File
@@ -42,7 +42,7 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "e19bb0e50bf303d56da3c4cf028439a92551b120"
# ⚠ SIN ESTO EL BUILD MUERE EN UN SITIO QUE NO NOMBRA LA CAUSA — medido acá el 2026-09-10.
# tawasuyu COMMITEA su propio `vendor/`: adentro tiene un `smithay` parcheado a mano (tearing/flip
+1 -1
View File
@@ -34,7 +34,7 @@ license = "MIT"
[source]
# El repo del propio takana: el `commit` es el identificador inmutable; la URL es sólo locator y no
# entra en `hash_inputs` (ADR 0013 §1). Subirlo cuando el CLI avance.
repo = "ssh://gitea@git.gioser.net:2345/sergio/takana.git"
repo = "https://git.gioser.net/sergio/takana.git"
commit = "68d052136c06b74f858a8a33d1963f45cf244fa0"
[build]
+1 -1
View File
@@ -10,7 +10,7 @@ version = "0.0.1"
license = "MIT"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
commit = "9967b02cf597df6d065edbad8d6669b5653d4928"
[build]