Tu primer relay: instalación desde el código fuente
Tu primer relay: instalación desde el código fuente
En el capítulo 2 viste el mapa de crates y el
pipeline de eventos. Ahora toca ponerlo a correr. Este capítulo es la ruta que el propio README.md
llama “the developer / self-host path”: clonar, activar la toolchain, levantar la infraestructura y
comprobar que el relay responde.
Lo que vas a montar aquí es un entorno de desarrollo. El relay corre en tu host con cargo run,
no dentro de un contenedor. El despliegue real en un servidor usa otro bundle completamente distinto,
que se ve en el capítulo 5. El propio README lo
dice sin rodeos: “The root docker-compose.yml is for day-to-day development only.”
El mapa mental antes de teclear
flowchart TD
subgraph host["Tu maquina - procesos nativos"]
relay["buzz-relay<br/>cargo run<br/>puertos 3000 / 8080 / 9102"]
desktop["App desktop Tauri<br/>pnpm exec tauri dev"]
end
subgraph docker["docker-compose.yml - red buzz-net"]
pg["postgres:17-alpine<br/>5432"]
redis["redis:7-alpine<br/>6379"]
adminer["adminer<br/>8082"]
keycloak["keycloak 26.0<br/>8180"]
minio["minio<br/>9000 y 9001"]
prom["prometheus<br/>9090"]
end
desktop -->|WebSocket| relay
relay --> pg
relay --> redis
relay --> minio
prom -->|scrape| relay
Tres cosas importantes de este diagrama, todas verificables en docker-compose.yml:
- El relay no está en el Compose de desarrollo. No hay servicio
relayen ese archivo. Se compila y se ejecuta en tu máquina. - No hay contenedor de búsqueda. Aunque
.env.exampledeclaraTYPESENSE_API_KEYyTYPESENSE_URL=http://localhost:8108en su cabecera de puertos, no existe ningún servicio Typesense endocker-compose.yml. La búsqueda full-text de Buzz vive en Postgres: el cratebuzz-searchconsulta una columnasearch_tsv TSVECTOR GENERATED ALWAYScon índice GIN sobre la tablaevents. Esas dos variables son residuo histórico; no levantes nada en 8108. - Keycloak y Prometheus vienen incluidos aunque el flujo básico no los necesite: Keycloak para pruebas locales de OAuth, Prometheus para scrapear las métricas del relay en el host.
Requisitos previos
El README es explícito: “You’ll need Docker and Hermit (or Rust 1.88+, Node 24+, pnpm 10+, just).”
| Requisito | Para qué | Nota |
|---|---|---|
| Docker | Postgres, Redis, MinIO, Adminer, Keycloak, Prometheus | Obligatorio. just bootstrap aborta si docker no está en el PATH |
| Hermit | Descarga y fija todas las demás herramientas | Recomendado. Vive dentro del repo, en bin/ |
| Rust 1.88+ | Compilar el workspace | Solo si no usas Hermit |
| Node 24+ | Frontend desktop y web | Solo si no usas Hermit |
| pnpm 10+ | Gestor de paquetes JS | Solo si no usas Hermit |
just | Task runner del repo | Solo si no usas Hermit |
Qué es exactamente Hermit aquí
bin/ es un entorno Hermit: un directorio lleno de symlinks que
descargan e instalan sus paquetes la primera vez que los invocas. Las versiones están fijadas en los
propios nombres de los archivos .pkg:
| Herramienta | Pin | Herramienta | Pin |
|---|---|---|---|
| rustup | 1.28.2 | biome | 2.4.7 |
| node | 24.15.0 | lefthook | 2.1.3 |
| pnpm | 11.4.0 | cargo-deny | 0.19.0 |
| just | 1.46.0 | cmake | 4.3.1 |
| pgschema | 1.7.4 | flutter | 3.41.7 |
Fíjate en el desfase: el README pide “pnpm 10+”, pero el pin real es pnpm 11.4.0. Cuando activas Hermit obtienes exactamente esa versión, no la que tengas instalada globalmente. Ese es justamente el punto: nadie discute versiones.
Clonar y activar la toolchain
git clone https://github.com/block/buzz.git && cd buzz
. ./bin/activate-hermit
El punto inicial no es decorativo. El script arranca con una guarda que compara BASH_SOURCE con
$0: si lo ejecutas como ./bin/activate-hermit imprime You must source this script y sale con
código 33 sin hacer nada. Tiene que ser . ./bin/activate-hermit o
source ./bin/activate-hermit. Cuando funciona, imprime Hermit environment ... activated y añade
bin/ al frente de tu PATH. Para fish hay un script aparte, bin/activate-hermit.fish.
Cada terminal nueva necesita su propia activación. Es la razón por la que el README repite
. ./bin/activate-hermit en la sección “Every day”.
just setup: qué hace exactamente
just setup && just build
setup está definido en el Justfile en dos líneas: depende de la receta bootstrap y luego ejecuta
./scripts/dev-setup.sh. Vale la pena desglosar ambos porque concentran casi todos los problemas de
instalación.
flowchart TD
B1["bootstrap: cargo, node y pnpm --version en paralelo<br/>fuerza la descarga de la toolchain Hermit"]
B2["bootstrap: comprueba que docker exista, si no aborta"]
B3["bootstrap: cp .env.example .env solo si .env no existe"]
C1["dev-setup: preflight docker instalado y daemon corriendo"]
C2["dev-setup: carga .env y exporta DATABASE_URL, PG*, REDIS_URL"]
C3["dev-setup: limpia contenedores legacy sprout-*"]
C4["dev-setup: aborta si un Redis local ocupa el 6379"]
C5["_ensure-services: docker compose up -d y espera healthy"]
C6["dev-setup: espera a que Postgres acepte conexiones"]
C7["cargo run -p buzz-admin -- migrate"]
C8["scripts/seed-local-community.sh"]
C9["pnpm install en desktop/ y en web/"]
C10["lefthook install --force"]
B1 --> B2 --> B3 --> C1 --> C2 --> C3 --> C4 --> C5 --> C6 --> C7 --> C8 --> C9 --> C10
bootstrap en detalle
La receta invoca cargo --version, node --version y pnpm --version en paralelo. No es un chequeo
cosmético: los symlinks de bin/ solo descargan el binario cuando se invocan por primera vez, así que
esa línea es la que fuerza la descarga de la toolchain. Después comprueba Docker y, si falta,
imprime Error: Docker is required but not installed. y sale.
La copia de .env es condicional: if [[ ! -f .env ]]. Si ya tienes un .env con tus ajustes, no
lo pisa. Si quieres regenerarlo, bórralo y vuelve a correr just bootstrap. El mensaje que imprime al
crearlo — “Created .env from .env.example — review it before running just dev” — no es retórico: la
referencia completa de esas variables es el
capítulo 4.
bootstrap es dependencia de setup, relay, relay-web, admin y dev, así que se ejecuta solo
en casi cualquier flujo.
dev-setup.sh en detalle
Este script es donde ocurre lo interesante:
- Preflight doble: comprueba
command -v dockery ademásdocker info. El segundo detecta el caso “Docker instalado pero el daemon apagado”, con el mensajeDocker daemon is not running. Start Docker Desktop and try again. - Herencia del nombre antiguo: el proyecto se llamó sprout. El script reescribe los valores por
defecto
sproutde tu.enva los debuzz— solo los defaults, no los personalizados — y para y elimina cualquier contenedorsprout-*que esté ocupando los puertos estándar. Los volúmenes se preservan. - Guardia de Redis local: si
lsofdetecta un procesoredis-serescuchando en 6379 y no existe el contenedorbuzz-redis, el script falla con el pid concreto y la sugerenciabrew services stop redis. Es el fallo de instalación más común en máquinas de desarrollo. - Arranque de servicios: delega en
just _ensure-services. - Espera de Postgres: hasta 10 intentos con
pg_isreadydentro del contenedor, con 2 segundos entre intentos. - Migraciones:
cargo run -p buzz-admin -- migrate. Las migraciones SQL van embebidas en el binario. - Seed de comunidad local:
scripts/seed-local-community.sh. Esto es crítico y suele malinterpretarse — lo explico abajo. - Dependencias JS:
pnpm installendesktop/y enweb/. Sipnpmno está en el PATH, advierte y sigue en vez de fallar. - Hooks de git: fija
core.hooksPatha una ruta absoluta derivada degit rev-parse --path-format=absolute --git-common-diry correlefthook install --force. El uso de ruta absoluta es deliberado, para que los worktrees enlazados hereden los mismos hooks.
Al terminar imprime un resumen con las URLs de Postgres, Redis, Adminer (http://localhost:8082) y
Keycloak (http://localhost:8180, credenciales admin / admin).
Por qué existe seed-local-community.sh
El comentario del script lo explica textualmente:
El relay falla cerrado a propósito cuando el header
Hostde la petición no está encommunities. El desarrollo local usa hosts de loopback, así que el bootstrap debe crear esas filas después de las migraciones, antes de que las llamadas HTTP del puente de desktop/Tauri puedan funcionar.
Es el “row-zero host binding” que viste en el capítulo 2: la URL es autoritativa para la comunidad. El
script deriva los hosts a sembrar desde RELAY_URL (por defecto ws://localhost:3000). Si cambias
RELAY_URL y no vuelves a sembrar, el relay responderá 404 a las peticiones con el host viejo.
_ensure-services: la receta que casi todo invoca
_ensure-services:
# docker inspect buzz-postgres y buzz-redis -> .State.Health.Status
# si ambos == healthy -> exit 0
# si no -> docker compose up -d y esperar
for i in $(seq 1 40); do ... sleep 3; done
Si ambos contenedores ya están healthy, imprime Services already healthy y sale de inmediato. Si
no, hace docker compose up -d y sondea hasta 40 iteraciones de 3 segundos, es decir unos 120
segundos, antes de rendirse con timed out.
Encima de ella se apila _ensure-migrations:
_ensure-migrations: _ensure-services
cargo run -p buzz-admin -- migrate
./scripts/seed-local-community.sh
Y just migrate es simplemente un alias sin cuerpo que depende de _ensure-migrations. Por eso
just relay levanta Docker y migra sin que tengas que pedírselo.
just build
build es cargo build --workspace: compila todo en modo debug, y la primera vez es una compilación
grande. just build-release hace lo mismo con --release, y just check-compile corre
cargo check --workspace --all-targets si solo quieres verificar que compila sin producir binarios.
Arrancar: dos flujos
Flujo A — todo junto con just dev
. ./bin/activate-hermit
just dev
just dev depende de bootstrap, _ensure-sidecar-stubs y _ensure-migrations, y después hace algo
bastante más elaborado que un simple cargo run:
- Resuelve el puerto del relay desde
BUZZ_BIND_ADDR(default0.0.0.0:3000), el de salud desdeBUZZ_HEALTH_PORT(default8080) y el de métricas desdeBUZZ_METRICS_PORT(default9102). - Con
lsof, comprueba que los tres puertos estén libres. Si alguno está ocupado aborta conError: <nombre> port <n> is already in use; refusing to launch desktop against a stale relay.y te imprime el proceso culpable. - Compila explícitamente
buzz-acp,buzz-agent,buzz-backend-kubernetes,buzz-dev-mcp,buzz-cli,git-credential-nostrybuzz-relay. - Exporta
BUZZ_GIT_PROBE_WRITERS=8yBUZZ_GIT_PROBE_ROUNDS=2(los defaults del binario son 32 y 3). El comentario del Justfile explica por qué: “Docker Desktop’s forwarded MinIO port can stall under the deployment probe’s 32 concurrent writers.” - Lanza
./target/debug/buzz-relayen background y hace polling dehttp://127.0.0.1:${health_port}/_readinessdurante 120 intentos de 0,5 s, o sea 60 segundos. Si el relay muere durante el arranque, o no llega a healthy en ese plazo, aborta sin lanzar la app. - Carga
scripts/instance-env.shy arrancapnpm exec tauri dev.
instance-env.sh deriva el puerto de Vite haciendo un hash SHA-256 de la raíz del worktree
(10000 + h % 55000), de modo que cada worktree obtiene siempre el mismo puerto y varias instancias
de desarrollo pueden convivir. BUZZ_RELAY_PORT sí queda fijo en 3000.
Flujo B — terminales separadas
El README lo recomienda cuando quieres los logs del relay separados de la salida de Vite: en la
terminal 1, . ./bin/activate-hermit && just relay; en la terminal 2,
. ./bin/activate-hermit && just desktop-dev.
just relay=bootstrap+_ensure-migrations+cargo run -p buzz-relay. Nada más. Es el camino limpio para operar solo el relay.just desktop-devno depende de nada: entra endesktop/, correpnpm installsi faltanode_modules, cargainstance-env.shy lanzapnpm exec vite --port "${BUZZ_VITE_PORT}" --strictPort. Es solo el servidor de frontend, sin ventana nativa.
Existe además just relay-release (cargo run -p buzz-relay --release), que depende de
_ensure-migrations pero no de bootstrap.
Servicios y puertos del Compose de desarrollo
Con el proyecto Compose buzz y la red buzz-net:
| Servicio | Contenedor | Imagen | Puerto host:contenedor | Healthcheck | Límite de memoria |
|---|---|---|---|---|---|
| postgres | buzz-postgres | postgres:17-alpine | 5432:5432 | pg_isready -U buzz | 512m |
| redis | buzz-redis | redis:7-alpine | 6379:6379 | redis-cli ping | 128m |
| adminer | buzz-adminer | adminer:latest | 8082:8080 | — | 64m |
| keycloak | buzz-keycloak | quay.io/keycloak/keycloak:26.0 | 8180:8080 | /health/ready | 512m |
| minio | buzz-minio | minio/minio:latest | 9000:9000 y 9001:9001 | /minio/health/live | 256m |
| minio-init | buzz-minio-init | minio/mc:latest | — | one-shot, restart: "no" | — |
| prometheus | buzz-prometheus | prom/prometheus:latest | 9090:9090 | — | 128m |
Credenciales de desarrollo, tal como están escritas en el archivo: Postgres buzz / buzz_dev /
base buzz; MinIO buzz_dev / buzz_dev_secret; Keycloak admin / admin. Son valores de
desarrollo y solo de desarrollo.
minio-init es un contenedor efímero que crea el bucket con mc mb --ignore-existing local/buzz-media
y le aplica mc anonymous set none. Volúmenes con nombre: buzz-postgres-data, buzz-minio-data y
buzz-prometheus-data. Redis no tiene volumen: sus datos son efímeros por diseño en desarrollo.
Y los puertos que abre el relay, que corre fuera de Docker:
| Puerto | Qué sirve | Variable |
|---|---|---|
| 3000 | WebSocket NIP-01, REST, documento NIP-11 | BUZZ_BIND_ADDR |
| 8080 | /_liveness, /_readiness, /_status, /_mesh | BUZZ_HEALTH_PORT |
| 9102 | /metrics para Prometheus | BUZZ_METRICS_PORT |
Verificar que el relay responde
Con el relay corriendo, cuatro comprobaciones en orden creciente de exigencia.
1. Liveness. El handler devuelve texto plano ok sin tocar nada:
curl -i http://127.0.0.1:8080/_liveness
2. Readiness. Aquí sí se comprueban las dependencias: el handler hace db.ping() y pide una
conexión al pool de Redis en paralelo, con timeout de 2 segundos.
curl -s http://127.0.0.1:8080/_readiness
# sano: {"status": "ready"}
# con fallo: {"status": "not_ready", "postgres": false, "redis": true}
# apagandose (HTTP 503): {"status": "shutting_down"}
Ese desglose por dependencia es todo el valor del endpoint: te dice cuál de las dos falló.
3. Status. Nombre de servicio, versión del crate y uptime:
curl -s http://127.0.0.1:8080/_status
# {"service": "buzz-relay", "version": "...", "uptime_seconds": 42}
4. El documento NIP-11. Esta es la prueba de que el puerto principal habla Nostr:
curl -s -H "Accept: application/nostr+json" http://localhost:3000/
El handler / decide qué devolver según cabeceras: si el Accept contiene application/nostr+json
sirve el documento NIP-11; si es un upgrade de WebSocket válido, hace el binding de comunidad y abre
la conexión; si no es ninguna de las dos, cae de vuelta al documento NIP-11. También existe
GET /info, que sirve el mismo documento sin negociación de contenido.
Un detalle de seguridad que conviene entender ahora, porque explica errores confusos más adelante: el documento NIP-11 se sirve antes del binding de comunidad y falla abierto, precisamente para que no se pueda deducir qué hosts están mapeados. El upgrade a WebSocket, en cambio, falla cerrado:
HTTP 404
relay: no community is configured for this host
Ese mensaje genérico aparece cuando el header Host no tiene fila en communities. Si te sale en
local, el arreglo casi siempre es volver a ejecutar ./scripts/seed-local-community.sh con el
RELAY_URL correcto.
En el puerto 3000 también están disponibles /health, /_liveness y /_readiness; /_status y
/_mesh solo existen en el router de salud del 8080.
Catálogo de targets útiles del Justfile
just sin argumentos ejecuta la receta default, que es just --list. Estos son los que usarás a
diario como operador.
Entorno
| Target | Qué hace |
|---|---|
just bootstrap | Descarga la toolchain Hermit, verifica Docker, crea .env si falta |
just setup | bootstrap + scripts/dev-setup.sh |
just hooks | Configura core.hooksPath y lefthook install --force |
just ps | docker compose ps |
just logs *ARGS | docker compose logs -f {{ARGS}} |
just down | docker compose down, conserva los volúmenes |
just migrate | Alias de _ensure-migrations |
just clean | cargo clean en el workspace y en desktop/src-tauri |
Ejecución
| Target | Qué hace |
|---|---|
just relay | Relay en debug, con servicios y migraciones garantizados |
just relay-release | Relay en release |
just relay-web | Compila web/ y arranca el relay con BUZZ_WEB_DIR=./web/dist |
just dev | Relay en background + app desktop Tauri |
just desktop-dev | Solo el servidor Vite del frontend desktop |
just admin | Dashboard de administración de solo lectura, en admin.localhost:3000 |
just desktop-standalone | Solo la app desktop, sin relay, base de datos, Docker ni .env |
Verificación y tests
| Target | Qué hace | Necesita infra |
|---|---|---|
just check | fmt-check, clippy, desktop-check, checks de Tauri, web-check, mobile-check | No |
just fmt / just fmt-check | cargo fmt --all con y sin --check | No |
just clippy | cargo clippy --workspace --all-targets -- -D warnings | No |
just test-unit | Tests unitarios | No |
just test-integration | ./scripts/run-tests.sh integration | Sí |
just test | ./scripts/run-tests.sh all | Sí, los levanta si hace falta |
just ci | Todo lo que corre CI | No |
just test-unit tiene una particularidad: si encuentra cargo-nextest en el PATH, corre paquetes
enumerados uno por uno — buzz-core, buzz-auth, buzz-voice, buzz-cli, buzz-db --lib,
buzz-conformance, buzz-push-gateway, buzz-backend-kubernetes — y si no, cae a
./scripts/run-tests.sh unit. Los paquetes están enumerados explícitamente porque, según el propio
comentario del Justfile, “nothing in CI runs cargo test --workspace”: pertenecer al workspace te
compra clippy y check, no un solo test ejecutado.
just ci es la cadena completa sin infraestructura:
check test-unit desktop-test desktop-build desktop-tauri-check desktop-tauri-test web-build mobile-test.
Es lo que conviene correr antes de un push.
just reset: la receta destructiva
reset lleva el atributo
[confirm("This will DELETE all development data and preserve installed Buzz. Continue? (y/N)")], que
obliga a una confirmación interactiva antes de ejecutar ./scripts/dev-reset.sh --yes.
dev-reset.sh borra el
estado de desarrollo del desktop con scripts/reset-desktop-dev-state.sh, hace
docker compose down -v --remove-orphans — la -v borra todos los volúmenes: Postgres, MinIO y
Prometheus — y luego exec scripts/dev-setup.sh para recrear todo. Advertencia literal del script:
“This will DELETE all development data (desktop state, postgres, minio volumes). Installed Buzz app
state and its production keyring are preserved. Redis data is ephemeral and always wiped on restart.”
Traducido a la práctica: reset preserva tu Buzz instalado y su keyring de producción, pero se lleva
por delante toda la base de datos local. Si solo quieres parar los servicios sin perder datos, el
comando es just down.
Prerrequisitos de Windows
El README dedica una sección propia a esto. El motivo es concreto: la herramienta de shell del agente ejecuta comandos bajo bash. En macOS y Linux bash ya está; en Windows hay que traerlo.
La instalación de Git for Windows incluye Git Bash, que es lo que
Buzz resuelve en tiempo de ejecución. Con eso instalado, todo funciona igual que en las demás
plataformas. Si prefieres apuntar a otro shell compatible con bash, defines BUZZ_SHELL con su ruta
(por ejemplo BUZZ_SHELL=C:\path\to\bash.exe); la descripción de la herramienta que ve el agente se
actualiza automáticamente para reflejar el shell activo.
Un detalle del Justfile que también afecta a Windows: la receta _ensure-sidecar-stubs genera
binarios placeholder para buzz-acp, buzz-agent, buzz-dev-mcp, git-credential-nostr y buzz;
buzz-backend-kubernetes se añade a la lista solo cuando el target no es Windows.
Troubleshooting de instalación
Los tres fallos de arranque más frecuentes
| Mensaje | Origen | Qué hacer |
|---|---|---|
Error: Docker is required but not installed. | just bootstrap, check command -v docker | Instalar Docker, o arreglar el PATH si ya está |
Docker daemon is not running. Start Docker Desktop and try again. | dev-setup.sh, check docker info | Arrancar el daemon |
Local Redis is already listening on port 6379 (pid(s): ...) | dev-setup.sh | Parar el Redis nativo: brew services stop redis en macOS, sudo systemctl stop redis en Linux |
El check de Redis solo se dispara si lsof está disponible y si el contenedor buzz-redis no está ya
corriendo. Es el fallo de instalación más común en máquinas de desarrollo con Redis nativo.
El activate-hermit “no hace nada”
Lo ejecutaste en vez de sourcearlo. Sale con código 33. Usa el punto: . ./bin/activate-hermit.
_ensure-services termina en “timed out”
Los healthchecks de buzz-postgres y buzz-redis no llegaron a healthy en 120 segundos. Diagnostica
con:
docker compose ps
docker compose logs -f postgres
docker inspect --format '{{.State.Health.Status}}' buzz-postgres
La causa habitual es un volumen buzz-postgres-data corrupto o de una versión incompatible. just reset lo resuelve, a costa de borrar los datos.
”Postgres did not accept connections after 10 attempts”
El contenedor está healthy pero pg_isready dentro del contenedor sigue rechazando con el usuario y
la base concretos. Revisa que PGUSER, PGPASSWORD y PGDATABASE en tu .env coincidan con lo que
declara docker-compose.yml (buzz / buzz_dev / buzz).
just dev aborta con “port … is already in use”
Hay un relay viejo vivo. El propio error imprime la salida de lsof con el pid. Mátalo y repite. Es
un fallo deliberado: la receta se niega a lanzar el desktop contra un relay obsoleto.
”buzz-relay did not become healthy within 60 seconds”
El relay arrancó pero /_readiness nunca devolvió 200 en 60 segundos. Corre just relay a solas para
ver sus logs sin la interferencia de Tauri. Los sospechosos habituales son Postgres, Redis o la sonda
de conformidad de git.
El relay muere al arrancar mencionando la “conformance probe”
Antes de abrir el listener, el relay ejecuta una sonda de conformidad A3 contra el backend de almacenamiento de objetos, para admitir escrituras condicionales linealizables. El comentario del código es explícito: “Failure is fatal: a backend that cannot satisfy pointer CAS invalidates the manifest-pointer protocol.”
La sonda está activa por defecto: se lee BUZZ_GIT_CONFORMANCE_PROBE y cualquier valor distinto
de "false" la habilita. Sus defaults en el binario son 32 escritores concurrentes
(BUZZ_GIT_PROBE_WRITERS) y 3 rondas (BUZZ_GIT_PROBE_ROUNDS). Como el puerto MinIO reenviado por
Docker Desktop puede atascarse con esa concurrencia, just dev baja los valores a 8 y 2. Si arrancas
el relay a mano y la sonda falla, prueba el mismo perfil acotado:
BUZZ_GIT_PROBE_WRITERS=8 BUZZ_GIT_PROBE_ROUNDS=2 cargo run -p buzz-relay
Y comprueba antes que MinIO esté vivo: curl -f http://localhost:9000/minio/health/live.
404 “relay: no community is configured for this host”
El binding de comunidad falló cerrado. La fila del host no existe en communities. Vuelve a correr
./scripts/seed-local-community.sh, y verifica que tu RELAY_URL sea el mismo con el que sembraste.
”pnpm not found — skipping desktop dependency install”
dev-setup.sh advirtió y siguió. El script te da la receta exacta: . ./bin/activate-hermit para
obtener pnpm y luego just desktop-install.
Ventana en blanco o transparente al abrir la app en Linux
Esto no es del relay, pero se topa en el mismo primer arranque. docs/linux-rendering-troubleshooting.md
documenta tres casos:
| Síntoma | Causa probable | Arreglo |
|---|---|---|
Ventana en blanco o transparente y SIGABRT con colrv1_configure_skpaint | Fuente de emoji COLRv1, solo en AppImage | Actualizar al AppImage v0.5.2+ |
| Ventana en blanco al arrancar, sin crash | Incompatibilidad del renderer dmabuf, NVIDIA o AppImage | WEBKIT_DISABLE_DMABUF_RENDERER=1 o --safe-rendering |
| Ventana en blanco en cualquier hardware, sin crash | Combinación GPU/driver desconocida | --safe-rendering |
Desde v0.5.1, Buzz fija WEBKIT_DISABLE_DMABUF_RENDERER=1 por sí mismo cuando detecta una GPU NVIDIA
— vendor ID 0x10de en /sys/class/drm — o cuando corre como AppImage. El flag --safe-rendering
fuerza además WEBKIT_DISABLE_COMPOSITING_MODE=1 y aplica solo a ese lanzamiento; si defines tú una
variable de WebKit y además pasas el flag, Buzz se niega a arrancar e imprime cuál entra en conflicto.
Para AMD RDNA4 con driver radv el workaround verificado son tres variables: GDK_BACKEND=x11,
WEBKIT_DISABLE_DMABUF_RENDERER=1 y WEBKIT_SKIA_ENABLE_CPU_RENDERING=1.
Ojo con el piso de glibc del AppImage: hasta v0.5.1 era 2.35 (Ubuntu 22.04 LTS, Debian 12); desde
v0.5.2 es 2.39 (Ubuntu 24.04 LTS, Fedora 40+). En Ubuntu 22.04 o Debian 12, el documento recomienda
los paquetes nativos .deb o .rpm, que usan el WebKit del sistema.
Resumen
- El entorno de desarrollo separa dos mundos: la infraestructura corre en Docker
(
docker-compose.yml, proyectobuzz, redbuzz-net) y el relay corre nativo en tu host concargo run. No hay serviciorelayen el Compose de desarrollo. - Hermit fija toda la toolchain dentro del repo: rustup 1.28.2, node 24.15.0, pnpm 11.4.0, just
1.46.0, entre otros. Se activa con
. ./bin/activate-hermiten cada terminal; ejecutarlo en vez de sourcearlo sale con código 33. just setupesbootstrapmásscripts/dev-setup.sh: descarga toolchain, verifica Docker, copia.env.examplea.envsolo si falta, levanta y espera los servicios, migra conbuzz-admin migrate, siembra la comunidad local e instala dependencias JS y hooks.- Los puertos de desarrollo son Postgres 5432, Redis 6379, Adminer 8082, Keycloak 8180, MinIO 9000/9001, Prometheus 9090; y del relay, 3000 para WS y REST, 8080 para salud y 9102 para métricas.
- No existe contenedor de Typesense pese a que
.env.examplelo menciona: la búsqueda full-text vive en Postgres. - Verificas el relay con
/_livenessy/_readinessen el 8080 — este último te dice cuál dependencia falla — y con el documento NIP-11 pidiendoAccept: application/nostr+jsonen el 3000. - El binding de comunidad falla cerrado: un host sin fila en
communitiesrecibe un 404 genérico.seed-local-community.shes lo que crea esas filas en local. just downconserva los datos;just resetpide confirmación y borra todos los volúmenes locales.- En Windows hace falta Git Bash porque la herramienta de shell del agente ejecuta bajo bash;
BUZZ_SHELLpermite apuntar a otro shell compatible.
Siguiente: Configuración: referencia de variables de entorno