gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 188Rust 55Shell 30Markdown 281211 Sutichaykuna

gitea: GOMEMLIMIT, porque no había techo de memoria en NINGÚN nivel

Llevaba 10 días con 4,29 GB de RSS en una caja de 7,7 GB (54 %), swap en 3,7 GB
y pico virtual de 12 GB.

El sospechoso habitual estaba descartado: REPO_INDEXER_ENABLED no está puesto,
así que el indexador de código —el que normalmente se come la RAM en gitea— está
apagado. Sólo hay un indexador de issues en bleve: 96 KB en disco.

Lo que había era ausencia de límite en los tres sitios posibles:
  · rlimits.mem_bytes = null en la card
  · el cgroup arje.slice/gitea declarado pero SIN crear en /sys/fs/cgroup
  · ni GOMEMLIMIT ni GOGC en el envp
Sin techo, el runtime de Go conserva mapeada la arena que ya liberó: el RSS se
queda en la marca de agua más alta y no vuelve.

⚠ Y la marca de agua la explica la CARGA, no un defecto de gitea. Medido sobre
los logs de un día: 621.000 peticiones desde 66.401 IPs distintas con
user-agents de navegador FALSOS, recorriendo combinatoriamente /src (274k),
/commits (102k), /blame (81k) y /raw (56k) de tawasuyu/tawasuyu. 600.000 con
status 200, o sea renderizadas — resaltado de sintaxis y blame, lo más caro que
gitea sabe hacer. Es scraping de forja, no tráfico.

GOMEMLIMIT es un límite BLANDO: el GC aprieta más y el proceso NO muere. Es
deliberadamente lo contrario de rlimits.mem_bytes, que sería duro y haría que
arje lo reiniciara en bucle cada vez que un blame grande tocara el techo — peor
que el problema. 2 GiB deja ~5,7 GB para el resto (los builds piden 2-3 GB en
pico).

Verificado en el anfitrión: GOMEMLIMIT=2GiB presente en el proceso (no en el
envoltorio sh -c, que ya hizo exec), RSS 3718 MB → 338 MB, y la caja pasó de
1,8 GB disponibles a 5,67 GB.

⚠ Detalle de arje que importa: `arjectl restart` reutiliza la MISMA Card en
memoria y no habría releído el cambio. Lo que lee del disco es `start`, así que
la secuencia correcta es stop + start.

⚠ Esto trata el SÍNTOMA. La causa es el saqueo y su sitio es el proxy (hoy
saywa): limitar o cortar /blame, /commits y /raw a anónimos. Eso es política del
sitio, no de esta receta.

452ce4215d02244aadbdf78ee793a780147d5d1c · ruwaq Sergio · (1 p'unchaw ñawpaq) · tayta 894b2d679 · kay commitpi sach'ata qhaway

Semántico sayk'uy

Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.

1 qillqakuna · +29 −1

diff --git a/recipes/gitea.toml b/recipes/gitea.toml
index a92973d7..d96b57f7 100644
--- a/recipes/gitea.toml
+++ b/recipes/gitea.toml
@@ -138,7 +138,35 @@ label      = "gitea"
 id         = "01M2EKDA00NKYGE2BB5DFH1EFF"
 exec       = "/bin/busybox"
 argv = ["sh", "-c", "test -f /etc/gitea/app.ini || { echo 'gitea: falta /etc/gitea/app.ini — es config del SITIO, viene con los datos' >&2; exit 78; }; /bin/grep -q '^gitea:' /etc/passwd || { echo 'gitea: no existe el usuario `gitea` en /etc/passwd y gitea NO corre como root' >&2; exit 78; }; cd /var/lib/gitea || exit 78; exec /usr/bin/setuidgid gitea /usr/bin/gitea web --config /etc/gitea/app.ini"]
-envp       = [["PATH", "/usr/bin:/bin"], ["HOME", "/var/lib/gitea"], ["GITEA_WORK_DIR", "/var/lib/gitea"], ["USER", "gitea"]]
+# ⚠ **`GOMEMLIMIT` — medido el 2026-10-20, y la causa NO era un leak.**
+# gitea llevaba 10 días corriendo con **4,29 GB de RSS** en una caja de 7,7 GB (54 %), con el swap
+# en 3,7 GB y un pico virtual de 12 GB. El sospechoso habitual estaba descartado:
+# `REPO_INDEXER_ENABLED` NO está puesto, así que el indexador de código —el que normalmente se come
+# la RAM en gitea— está apagado.
+#
+# Lo que había era **ningún techo de memoria en ningún nivel**: `rlimits.mem_bytes` a `null`, el
+# cgroup `arje.slice/gitea` declarado pero SIN crear en `/sys/fs/cgroup`, y ni `GOMEMLIMIT` ni
+# `GOGC` en este `envp`. Sin límite, el runtime de Go conserva mapeada la arena que ya liberó: el
+# RSS se queda en la marca de agua más alta que tocó y no vuelve.
+#
+# ⚠ Y la marca de agua la explica la CARGA, no un defecto de gitea: medido sobre los logs de un día,
+# **621.000 peticiones desde 66.401 IPs distintas** con user-agents de navegador falsos, recorriendo
+# combinatoriamente `/src` (274k), `/commits` (102k), `/blame` (81k) y `/raw` (56k) de
+# `tawasuyu/tawasuyu`. 600.000 de ellas con status 200, o sea renderizadas: resaltado de sintaxis y
+# `blame`, que es lo más caro que gitea sabe hacer. Es scraping de forja, no tráfico.
+#
+# ⇒ `GOMEMLIMIT` es un límite **BLANDO**: el GC aprieta más para no pasarse, y el proceso **no
+# muere**. Es deliberadamente lo contrario de `rlimits.mem_bytes`, que sería duro y haría que arje
+# la reiniciara en bucle cada vez que un `blame` grande tocara el techo — peor que el problema.
+#
+# 2 GiB deja ~5,7 GB para el resto (los builds del corpus piden 2-3 GB en pico). El coste es más CPU
+# en GC bajo esta carga; es el intercambio correcto en una caja que, llena, **no se degrada: se cae
+# entera**.
+#
+# ⚠ Esto trata el SÍNTOMA. La causa es el saqueo, y su sitio es el proxy (hoy `saywa`): limitar o
+# cortar `/blame`, `/commits` y `/raw` a anónimos. Eso es decisión de política del sitio, no de esta
+# receta.
+envp       = [["PATH", "/usr/bin:/bin"], ["HOME", "/var/lib/gitea"], ["GITEA_WORK_DIR", "/var/lib/gitea"], ["USER", "gitea"], ["GOMEMLIMIT", "2GiB"]]
 networking = "full"
 cgroup     = "arje.slice/gitea"
 restart    = { initial_ms = 1000, max_ms = 30000 }