diff --git a/docs/28-servidor-de-produccion.md b/docs/28-servidor-de-produccion.md
index e0f7e7c9..93f14b73 100644
--- a/docs/28-servidor-de-produccion.md
+++ b/docs/28-servidor-de-produccion.md
@@ -994,6 +994,54 @@ el mismo día. Es la diferencia entre una receta «sellada» y una receta *usada
---
+### 6.11 🗄️ La imagen del perfil, con gitea, ARRANCA y SIRVE *(2026-09-14)*
+
+`servidor-image.sh` + QEMU: **PID 1 = `arje-zero`, gitea encarnado por él (`ppid=1`), corriendo como
+`uid=916`, escuchando en :3000 y devolviendo `200` con `
takana git`**, con su
+`gitea.db` creada por él mismo. Es el primer servicio de PAQUETE que arranca en una imagen de takana:
+los que había venían horneados en el bootstrap.
+
+La cadena entera, eslabón por eslabón: `[[user]]` → `/etc/passwd` de la imagen · `[[service]]` →
+`takana service-cards` → `genesis` de la seed → arje lo encarna → `setuidgid` → sirve.
+
+#### Los tres fallos que sólo aparecieron AL PROBAR LA IMAGEN
+
+Los tres pasan el sellado, el `hash`, el resolutor de servicios y el armado. Ninguno se ve sin
+arrancar la imagen.
+
+1. **⚠⚠ Escribir en el rootfs hidratado es escribir DENTRO del store.** `takana users --merge` hacía
+ `fs::write` sobre `/etc/passwd`, y ese fichero y el del artefacto `product-rootfs` son
+ **el mismo inode** (medido: 1225824, `2 links`, modo `444`) — el rootfs se arma con hardlinks.
+ Habría mutado un artefacto sellado, y toda imagen futura habría salido con la cuenta metida dentro
+ del producto. Se salvó porque el store es de sólo lectura y salió `Permission denied`: confiar en
+ eso es confiar en un permiso. Ahora escribe por temporal + `rename`, con un control que comprueba
+ que el fichero del store conserva su contenido y baja a 1 link.
+
+2. **La imagen traía el binario, la cuenta… y nadie lo arrancaba.** El `genesis` sólo tenía lo que
+ hornea `takana-bootstrap` (`sshd`, `console-getty`, `hammerd`): `servidor-image.sh` **no inyectaba
+ las Cards** — eso sólo existía en el camino de las imágenes de escritorio. Y ninguna métrica lo
+ dice: `targets.py --services` responde que el perfil lo habilita, y lo habilita; lo que faltaba era
+ el paso que lleva esa declaración a la imagen.
+
+3. **⚡ `trap invalid opcode`: el binario sólo corría en la CPU que lo compiló.** Con la card ya en el
+ genesis, gitea moría al instante dentro de QEMU-TCG. El sandbox exporta `CC` apuntando a un wrapper
+ con `-mcpu=baseline` (y su comentario ya avisaba: «de paso cierra el SIGILL de AVX en qemu64»), y
+ **la fase Go del propio builder lo pisaba** con `CC="zig cc"` a secas, que es `-mcpu=native`. No
+ falla al compilar ni al sellar: falla al ejecutar en otra CPU. Y el `ArtifactHash` no puede
+ cazarlo, porque la CPU del builder no entra en `hash_inputs` — **dos workers distintos sellan bytes
+ distintos bajo la misma dirección**. Arreglado en el builder y en la receta; re-hashea las cinco
+ recetas `cgo = true` (`gitea`, `usql`, `sq`, `gocryptfs`, `naabu`).
+
+#### Lo que NO está probado, y falta para la mudanza
+
+El `app.ini`, el usuario del sitio y los datos se pusieron **a mano** dentro de la VM para llegar al
+200. Eso es exactamente lo que el plan de mudanza tiene que traer de gioser — `/etc/gitea` ya está en
+`scripts/mudanza/rutas-fuera-de-git.txt`.
+
+Y **la imagen no trae `arjectl`**: tras poner la config hubo que REINICIAR para que arje volviera a
+intentarlo. El backoff de `restart` se agota y no hay forma de pedirle a PID 1 que relance un ente en
+caliente. Para una caja de producción eso es una pieza que falta, no una comodidad.
+
## 7. Reusar los scripts que ya existen, y no escribir de nuevo
Pedido explícito del usuario. El inventario de lo que ya hace el trabajo: