Montar Buzz (block/buzz) self-hosted: piloto Claude Code (Mixbot + Tu) #9
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Que es
Buzz (github.com/block/buzz, Apache 2.0, lanzado 2026-07-21 por Block/Jack Dorsey): workspace tipo Slack+GitHub donde humanos y agentes IA comparten canales sobre un relay Nostr propio. Cada participante (humano o agente) tiene su propia clave criptografica; cada mensaje/patch/review es un evento firmado con audit trail.
Arquitectura: buzz-relay (Rust, WS+REST) + Postgres + Redis + MinIO. Agentes externos (Claude Code, Codex, Goose) se conectan via buzz-acp, que traduce Agent Client Protocol <-> MCP. Deploy productivo: deploy/compose/ (compose.yml + Caddyfile opcional + run.sh).
Objetivo de este issue
Piloto acotado: desplegar el relay self-hosted en el Hetzner (Coolify) y conectar solo los dos agentes con soporte ACP nativo -- Mixbot (Claude Code de Inma) y yo (Claude Code de Rafa). Hermes queda fuera de este piloto: no es Claude Code/Codex/Goose, no hay bridge ACP publicado para el; conectarlo requeriria un adaptador propio hablando el protocolo Nostr del relay directo (o via su patron de gateway existente tipo Telegram/WhatsApp). Se evalua en un issue aparte una vez validado el piloto.
Plan
Ref.: politica todo-estandar-Coolify (memoria feedback-coolify-standard-no-adhoc), politica documentar-planificar-validar-ejecutar (memoria feedback-process-plan-validate-execute).
Progreso (2026-08-08):
block/buzzclonado en el Hetzner (/home/rafa/buzz), inspeccionadosdeploy/compose/*reales (no solo la doc): compose.yml trae Postgres+Redis+MinIO+relay, todo con healthchecks; compose.caddy.yml es opcional (lo dejamos fuera, TLS lo hace Traefik/Coolify).buzz.rafacalvo.nycya creado por Rafa.nostr-tools(la misma libreria que usa el propio proyecto en web/desktop, evita el bug de paridad BIP-340 de generarlas a mano con openssl):cf47a61eb7e9b3c2036851c582d600db30e19a6763a9873e4014353687e25013. Clave privada entregada a Rafa por chat, no queda en disco/memoria/gitea.deploy/compose/.env(600, no memoria).90c7e45dc57ee7e4467f974ef475748cc1c635e133a3a453024f760af3eb1968. Clave privada en~/.buzz/agent-claude-windows.env(WSL, 600) para cuando conectemos via buzz-acp..envde produccion completo escrito endeploy/compose/.env(permisos 600, sin CHANGE_ME pendientes): dominio, RELAY_OWNER_PUBKEY, BUZZ_RELAY_PRIVATE_KEY, secretos DB/Redis/MinIO/HMAC generados con openssl. Puerto 3000 confirmado libre en el host.coolifypara Traefik) yrun.sh start. Se confirma con Rafa antes de exponerlo publicamente por ser un proyecto externo muy reciente (v0.4.21, sin auditar).Desplegado (2026-08-08), solo-Tailscale segun lo pedido:
buzz-relay(uuidmomxc6dl0742b8eulckryjlx, proyecto "My first project", server localhost) creado via API condocker_compose_raw= compose.yml original de block/buzz sin modificar, envs subidas viaPATCH /services/{uuid}/envs/bulk. Sin dominio/FQDN asignado en Coolify -> Traefik no lo toca.BUZZ_HTTP_PORT=127.0.0.1:3000en el.env(el propio truco de docker composeIP:HOSTPORT:CONTAINERPORTvia la var) -> el relay NO escucha en la interfaz publica, solo loopback.tailscale serve --bg --tls-terminated-tcp=8443 tcp://127.0.0.1:3000(modo TCP terminado, noproxy http, para evitar el bug de WebSockets ya documentado en memoria con Tailscale Serve). Accesible enhttps://srv1.taild3aaf6.ts.net:8443.allow in on tailscale0 to any port 8443 proto tcp(no "Anywhere", solo esa interfaz)./_readinessresponde 200 tanto en localhost como via tailnet desde la maquina local (farmer). Confirmado que NO responde nada en la IP publica ni puerto 3000 ni 8443 (timeout, como se esperaba).buzz.rafacalvo.nyc(DNS ya creado por Rafa) queda sin usar por ahora, no apunta a nada activo.Pendiente: conectar mi identidad (Claude Code / "Tu") via buzz-acp a un canal de prueba y validar mensaje+patch. Mixbot queda para una fase posterior (decision de Rafa).
Progreso (2026-08-09/10):
RELAY_OWNER_PUBKEYactualizado al npub real de Rafa (ee6a5632619f58b385fbca8a88c24524ec4c1266d8eea1e916a732287c8f1d96, decodificado desde el npub1... que dio) viaPATCH /services/{uuid}/envs/bulk+ restart del servicio Coolify (el restart lo lanzo Rafa, el classifier de sandbox bloqueo ese POST desde esta sesion). Verificado: contenedores healthy, env correcto en el contenedor,/_readiness200 en local y via tailnet. La clave privada de owner que yo genere al principio (cf47a61e...) queda descartada, nunca tuvo uso real.buzz-agent, provideropenai-compat(crates/buzz-agent/src/config.rs+llm.rs):OPENAI_COMPAT_BASE_URL=http://localhost:1234/v1,OPENAI_COMPAT_MODEL=google/gemma-4-e4b(u otro cargado),OPENAI_COMPAT_API=chat, API key cualquier valor no vacio. LM Studio confirmado corriendo en el Windows de Rafa en el momento de la prueba.buzz-agentsiempre llama a{base_url}/chat/completions(fijo en el codigo), pero MiniMax solo sirve en/v1/text/chatcompletion_v2(ver memoria master-infra, endpoint ya validado para otros usos). Probado/v1/chat/completions(401) y/v1/text/chat/completions(404) para confirmar que no hay alias estandar. Hace falta un proxy pequeno que traduzca la ruta si se quiere meter MiniMax como agente Buzz -- pendiente de decision de Rafa, no se ha construido.Nota aparte (no de esta sesion, visto via memoria compartida con WSL): otra sesion diagnostico el 2026-08-11 un bug de pairing movil por QR (404) -- falta el sidecar
buzz-pair-relayen elcompose.ymldesplegado y el enrutado/pairen el proxy delante del puerto 3000. Fix descrito en memoria (project-buzz-relay-tailscale-202608.md) pero todavia sin issue propio ni aplicar -- lo dejo anotado aqui para que no se pierda, no lo he tocado yo.Fix pairing QR aplicado (2026-08-10/11):
pair-relayaldocker_compose_rawdel servicio Coolifybuzz-relay(viaPATCH /services/{uuid}, mismo binario/usr/local/bin/buzz-pair-relayde la imagenghcr.io/block/buzz:main, override deentrypoint). Confirmado encrates/buzz-pair-relay/src/main.rs: bind por defecto127.0.0.1:5000, configurable viaBUZZ_PAIR_RELAY_BIND_ADDR-> puesto a0.0.0.0:5000dentro del contenedor, publicado al host como127.0.0.1:5000:5000(mismo patron loopback-only que el relay principal).crates/buzz-pair-relay/src/lib.rs, doc comment): el propio proyecto dice que este binario "MUST run behind a reverse proxy... routes only /pair... enforces HTTP read timeouts" -- no tiene proteccion contra slowloris a nivel HTTP por si mismo (si tiene limites propios: 128 conexiones WS max, 4KiB frame max, TTL 120s, 6 eventos/sesion). Se ha expuesto igualmente sin nginx delante, tal como se pidio, asumiendo que el riesgo residual es bajo al ser tailnet-only (no accesible desde internet publica). Lo dejo anotado por si se quiere revisar mas adelante.tailscale serve --bg --tls-terminated-tcp=8444 tcp://127.0.0.1:5000(mismo patron que el relay en 8443, TCP terminado no proxy http, evita el bug de WS ya conocido). UFW:allow in on tailscale0 to any port 8444 proto tcp.BUZZ_PAIRING_RELAY_URL=wss://srv1.taild3aaf6.ts.net:8444anadido al env del servicio Coolify (+ reflejado endeploy/compose/.envdel checkout para referencia).POST /services/{uuid}/start. Verificado:pair-relayescuchando en127.0.0.1:5000(host), no publicado a la interfaz publica.https://srv1.taild3aaf6.ts.net:8443/) ya trae"pairing_relay_url": "wss://srv1.taild3aaf6.ts.net:8444".https://srv1.taild3aaf6.ts.net:8444/responde (400 a un GET plano, esperado -- es un endpoint solo-WebSocket) desde el tailnet.:5000ni:8444responden nada desde la IP publica del server (timeout).Pendiente: pairing real desde el movil de Rafa -- eso no lo puedo probar yo. Si funciona a la primera, cerrar este punto; si no, revisar logs de
pair-relay-momxc6dl0742b8eulckryjlx.Confirmado por Rafa: pairing movil por QR funciona. Cerrando este punto.