CreaRack-SL

ADR s52 — Migrar Help Widget a Tailscale + Django (eliminar CF Tunnel llama-help público)

Contexto

El Help Widget de CreaRack Pro utilizaba un Cloudflare Tunnel (llama-help.crearack.com) para exponer el llama-server self-hosted al proxy Django. Al cierre de la sesión 52 se detectó que este tunnel exponía públicamente la web UI built-in de llama.cpp — ver [[incident—20260507—llama-help-exposicion-publica]].

Decisión aprobada por Edu al cierre de s52: eliminar el subdominio público entero y migrar la cadena del Help a través del proxy Django de PROD usando Tailscale como transporte privado.

Decisión

Plan B — Tailscale + Django directo al llama-server via tailnet.

Arquitectura resultante:

Browser usuario
    ↓
workspace.crearack.com  (frontend Help Widget, sin cambios)
    ↓  POST /api/help/ask
crearack.com / Django  (crearack-prod, Hetzner CCX)
    ↓  HTTP + LLAMA_API_KEY  [via Tailscale]
100.80.142.60:8081  (llama-server-e2b, LXC 100, pve-epyc-02)
    ↓
Respuesta de síntesis al usuario

Eliminado: Cloudflare Tunnel llama-help + CNAME llama-help.crearack.com.

Alternativas consideradas

OpciónDescripciónEstado
A — Status quo con CF AccessAñadir CF Access al tunnel existente para bloquear la UIDescartada — no elimina la superficie de exposición
B — Tailscale + Django ✅Eliminar el tunnel; Django llama al llama-server via tailnetAPROBADA

Decisión técnica pendiente (3a vs 3b) — confirmar al arrancar s53

Dentro del Plan B, hay una bifurcación sobre quién hace el embedding + retrieval de chunks para la RAG del Help:

Opción 3a — Mover embedding+retrieval a Django (Workers AI desde Python)

  • Django llama a Workers AI REST para el embedding de la pregunta.
  • Django busca chunks en Vectorize directamente (o vía REST).
  • Django llama al llama-server para la síntesis.
  • Pro: workspace queda ajeno al Help. Un solo salto Django → llama-server.
  • Con: duplica lógica que ya existe en el workspace (acceso a Vectorize + D1).

Opción 3b — Django llama al workspace para los chunks, después a llama-server

  • Django llama al workspace para bib_search_semantic (que tiene acceso a Vectorize + D1).
  • Django llama al llama-server con los chunks recuperados para la síntesis.
  • Pro: reutiliza la wiki indexada y Vectorize existente en el workspace.
  • Con: dos saltos en la cadena; workspace sigue acoplado al Help.

Criterio de elección: la opción (b) es probablemente la correcta — el workspace tiene la wiki indexada y Vectorize es de CF. Confirmar con Edu al arrancar s53 antes de programar.

Plan de ejecución — 10 pasos (s53 AM)

  1. Instalar Tailscale en crearack-prod (root@crearack.com):

    curl -fsSL https://tailscale.com/install.sh | sh && tailscale up

    Autenticar con la cuenta del equipo.

  2. Verificar conectividad tailnet:

    curl -H "Authorization: Bearer $LLAMA_API_KEY" http://100.80.142.60:8081/props
  3. Decidir 3a vs 3b con Edu — ver sección anterior.

  4. Modificar core/api_help.py en CreaRack-Pro:

    • Añadir env vars LLAMA_HELP_URL=http://100.80.142.60:8081/v1/chat/completions y LLAMA_HELP_API_KEY.
    • Hacer fetch directo desde Python con requests (sin pasar por MCP bib_ask).
  5. Eliminar flujo bib_ask del workspace si se elige 3a:

    • Revertir o eliminar archivo-core.ts:synthesizeAnswer si no tiene otros consumidores.
  6. Eliminar Cloudflare Tunnel desde LXC 100:

    cloudflared service uninstall
    cloudflared tunnel delete llama-help

    Eliminar CNAME llama-help.crearack.com desde CF Dashboard.

  7. Cambiar bind del llama-server-e2b de 127.0.0.1:8081 a 0.0.0.0:8081 para ser accesible vía tailnet.

  8. Verificar UFW en pve-epyc-02:

    • Puerto 8081/tcp abierto solo en tailscale0, no en eth0.
    ufw allow in on tailscale0 to any port 8081
    ufw deny in on eth0 to any port 8081
  9. Test end-to-end: pregunta desde el panel Help debe responder con latencia similar (~15s).

  10. Confirmar resolución del incidente y actualizar [[incident—20260507—llama-help-exposicion-publica]] a resolved.

Consecuencias

  • Positivas: elimina completamente la superficie de exposición pública del llama-server. Arquitectura más simple (sin CF Tunnel intermedio).
  • Negativas: Django en crearack-prod pasa a depender de Tailscale — si el tailnet tiene problemas, el Help Widget falla. Mitigación: timeout + fallback de error claro al usuario.
  • Deuda técnica: PR2 Direcciones del plan workspace tools queda desplazado a s54 para priorizar esta migración de seguridad.

Estado

PENDIENTE DE EJECUCIÓN — Plan aprobado en s52, ejecución prevista en s53 AM. Actualizar status: active y añadir fecha de resolución real una vez ejecutado.

Véase también

  • [[incident—20260507—llama-help-exposicion-publica]]