|
|
|
@@ -37,6 +37,9 @@ flowchart LR
|
|
|
|
|
SSH["Cliente SSH<br/>(laptop / tablet / lo que sea)"] -->|docker exec| C["Contenedor tmux-host<br/>--network host, --restart unless-stopped"]
|
|
|
|
|
C --> T["tmux server<br/>sesión 'lab'"]
|
|
|
|
|
T --> CC["proceso claude<br/>(Claude Code)"]
|
|
|
|
|
C --> HC["healthcheck.sh (background)<br/>cada 30 min"]
|
|
|
|
|
HC -.->|curl| NET["gitea.cruzcloud.net"]
|
|
|
|
|
HC -.->|recrea si falta| T
|
|
|
|
|
C -.->|bind mount| DATA["/DATA (host)<br/>repos y configs del lab"]
|
|
|
|
|
C -.->|bind mount| SOCK["/var/run/docker.sock (host)<br/>control de Docker/k3d"]
|
|
|
|
|
C -.->|bind mount| HOME["/DATA/AppData/k3d-lab-v3/claude-code-home (host)<br/>-> /root/.claude"]
|
|
|
|
@@ -49,7 +52,17 @@ reinicia.
|
|
|
|
|
|
|
|
|
|
## Contenedor: `tmux-host`
|
|
|
|
|
|
|
|
|
|
La imagen se construye desde `scripts/tmux-host/Dockerfile` (antes era
|
|
|
|
|
un `docker run ... alpine sh -c "apk add ..."` inline — mismo contenido,
|
|
|
|
|
pero ahora como imagen versionada en vez de reinstalar todo en cada
|
|
|
|
|
arranque). El Dockerfile fija `WORKDIR /DATA/AppData/k3d-lab-v3/lab-cruzcloud`
|
|
|
|
|
(la raíz del lab, con `CLAUDE.md`, `apps-registry/`, `platform-infra/` y
|
|
|
|
|
`scripts/`) y agrega `healthcheck.sh` (ver más abajo) como proceso en
|
|
|
|
|
background del contenedor.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
docker build -t tmux-host:local scripts/tmux-host
|
|
|
|
|
|
|
|
|
|
docker run -d \
|
|
|
|
|
--name tmux-host \
|
|
|
|
|
--restart unless-stopped \
|
|
|
|
@@ -59,9 +72,15 @@ docker run -d \
|
|
|
|
|
-v /DATA/AppData/k3d-lab-v3/claude-code-home:/root/.claude \
|
|
|
|
|
-v /DATA/AppData/k3d-lab-v3/claude-code-home.json:/root/.claude.json \
|
|
|
|
|
--network host \
|
|
|
|
|
alpine sh -c "apk add --no-cache tmux docker-cli bash curl git kubectl nodejs npm && npm install -g @anthropic-ai/claude-code && git config --global --add safe.directory '*' && tail -f /dev/null"
|
|
|
|
|
tmux-host:local
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`WORKDIR` hace que `docker exec` (y por lo tanto `lab-session.sh`)
|
|
|
|
|
arranquen ya posicionados en la raíz del lab sin tener que navegar a
|
|
|
|
|
mano — `lab-session.sh` además pasa la ruta explícita vía `tmux new -c`
|
|
|
|
|
por las dudas, para no depender de que `docker exec` herede el `WORKDIR`
|
|
|
|
|
de la imagen.
|
|
|
|
|
|
|
|
|
|
| Volumen | Destino | Por qué |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `/DATA` | `/DATA` | Acceso a los repos (`apps-registry`, `platform-infra`, `scripts`) y configs del lab, mismos paths que en el host |
|
|
|
|
@@ -195,13 +214,47 @@ Si la sesión `lab` existe, se adjunta a ella (mismo shell, mismo
|
|
|
|
|
ejemplo justo después de que el contenedor se recreó desde cero— la
|
|
|
|
|
crea. No hay que recordar cuál de los dos casos aplica.
|
|
|
|
|
|
|
|
|
|
## Chequeo de salud automático (cada 30 min)
|
|
|
|
|
|
|
|
|
|
`scripts/tmux-host/healthcheck.sh` corre en background dentro del
|
|
|
|
|
propio contenedor (lanzado por `entrypoint.sh`, el `ENTRYPOINT` de la
|
|
|
|
|
imagen) y cada `HEALTHCHECK_INTERVAL_SEC` (1800s por defecto) hace dos
|
|
|
|
|
chequeos independientes, con una respuesta distinta según el tipo de
|
|
|
|
|
falla:
|
|
|
|
|
|
|
|
|
|
- **Conectividad de red real** (`curl` a `https://gitea.cruzcloud.net/`):
|
|
|
|
|
si falla, **solo se registra** en el log y se notifica por Telegram —
|
|
|
|
|
el contenedor nunca intenta "arreglar" la red del host. Un problema de
|
|
|
|
|
red puede ser de hardware/BIOS (deuda técnica ya conocida, ver
|
|
|
|
|
`incidente-medusa-crashloop-2026-08.md`), fuera del alcance real de un
|
|
|
|
|
contenedor.
|
|
|
|
|
- **Existencia de la sesión tmux `lab`** (`tmux has-session`): si no
|
|
|
|
|
existe, **sí se recrea automáticamente** (`tmux new-session -d -s lab
|
|
|
|
|
-c <WORKDIR>`) — es solo recuperar el propio entorno de trabajo del
|
|
|
|
|
contenedor, no tocar infraestructura externa, así que es seguro
|
|
|
|
|
hacerlo sin intervención humana.
|
|
|
|
|
|
|
|
|
|
Todo evento (chequeo ok, falla de red, sesión recreada) queda en
|
|
|
|
|
`/DATA/AppData/k3d-lab-v3/tmux-host/logs/health.log` — persistente en
|
|
|
|
|
`/DATA`, no solo en el stdout del contenedor (que se pierde con
|
|
|
|
|
`docker logs` al recrearlo). Las notificaciones de Telegram reusan el
|
|
|
|
|
mismo bot/`chat_id` ya configurado para `scripts/lab-agent/`
|
|
|
|
|
(`lab-agent.env`), en vez de duplicar credenciales entre los dos
|
|
|
|
|
agentes del lab.
|
|
|
|
|
|
|
|
|
|
Para probar el intervalo sin esperar 30 minutos, se puede levantar el
|
|
|
|
|
contenedor con `-e HEALTHCHECK_INTERVAL_SEC=60` (solo para pruebas en un
|
|
|
|
|
contenedor descartable — nunca cambiar esto en el `tmux-host` real sin
|
|
|
|
|
volver a 1800 después).
|
|
|
|
|
|
|
|
|
|
## Qué sobrevive a qué
|
|
|
|
|
|
|
|
|
|
| Evento | ¿Sobrevive la sesión tmux (`lab`)? | ¿Sobrevive el login de Claude Code? |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| Corte de SSH / cerrar la terminal / cambiar de dispositivo | Sí — es exactamente el caso que este setup resuelve | Sí |
|
|
|
|
|
| `docker restart tmux-host` (reinicio del NAS) | **No** — el proceso `tmux server` muere con el contenedor; `lab-session.sh` crea una sesión nueva automáticamente | Sí, vía el volumen montado en `/root/.claude` |
|
|
|
|
|
| `docker rm` + recrear el contenedor desde cero | No | Sí, vía el mismo volumen — no hace falta volver a autenticar ni reconfirmar el diálogo de confianza del folder (ver el mount de `claude-code-home.json`) |
|
|
|
|
|
| `docker restart tmux-host` (reinicio del NAS) | **No al toque, pero se auto-recupera solo** — el proceso `tmux server` muere con el contenedor; `healthcheck.sh` la recrea en el próximo ciclo (máx. 30 min) sin intervención, o `lab-session.sh` la crea al instante si alguien se reconecta antes | Sí, vía el volumen montado en `/root/.claude` |
|
|
|
|
|
| `docker rm` + recrear el contenedor desde cero | No, pero igual se auto-recupera sola (mismo mecanismo de arriba) | Sí, vía el mismo volumen — no hace falta volver a autenticar ni reconfirmar el diálogo de confianza del folder (ver el mount de `claude-code-home.json`) |
|
|
|
|
|
| Falla de red real del host/NAS | N/A | N/A — `healthcheck.sh` la detecta y notifica, pero no la corrige (fuera de su alcance) |
|
|
|
|
|
|
|
|
|
|
## Validación en vivo
|
|
|
|
|
|
|
|
|
|