Ejecutar el relé

Para tu relé nostrfy: arranque y parada, registros y estadísticas, recarga en caliente de la configuración, múltiples instancias y ajuste a gran escala.

Arranque y parada

Arranca el relé como demonio en segundo plano:

sh
nostrfy --config nostrfy.toml start

=> nostrfy started (pid 12345)

O ejecútalo en primer plano en la terminal:

sh
nostrfy --config nostrfy.toml start --foreground

Detener:

sh
nostrfy --config nostrfy.toml stop

Verifica que esté activo:

sh
curl http://127.0.0.1:8080/health

=> {"status":"ok"}

Registros y estadísticas

El demonio escribe en daemon.log_file. Cuando el archivo supera max_log_size_bytes se rota automáticamente (nostrfy.log.1, .2…hasta max_log_files generaciones):

sh
tail -f nostrfy.log

El nivel de registro lo controla la variable de entorno RUST_LOG (por ejemplo, RUST_LOG=debug).

Estadísticas

Estadísticas en vivo desde la CLI:

sh
nostrfy stats

O por HTTP:

sh
curl http://127.0.0.1:8080/relay/stats

Muestra conexiones, eventos aceptados/rechazados, tamaño de la base y más.

Métricas de Prometheus

sh
curl http://127.0.0.1:8080/metrics

Recarga en caliente (SIGHUP)

Tras editar el archivo de configuración, recárgalo sin reiniciar:

sh
kill -HUP $(cat nostrfy.pid)
Se aplica al recargarRequiere reinicio
Identidad del relé, public_urlprivate_key
la mayoría de [limits], reject_ephemeral, enabled_git, enabled_nip78_authapi_host, metrics_enabled, ajustes de LiveKit
—enabled_nips / disabled_nips, server.host / port / ws_paths
—database.* (incluido search_index), blossom.*

El registro avisa cuando cambia un ajuste que requiere reinicio.

Ejecutar varias instancias

nostrfy admite varios relés independientes en un mismo servidor (puertos distintos). Cada instancia necesita su propio server.port, [daemon] pid_file/log_file/stats_file (valores compartidos hacen que la segunda instancia rechace el arranque con already running), database.path y — cuando se usen — sus propios api_host / blossom.host:

toml
[server]
port = 8080

[database]
path = "/var/lib/nostrfy-a"

[daemon]
pid_file = "/var/run/nostrfy-a.pid"
log_file = "/var/log/nostrfy-a.log"
stats_file = "/var/lib/nostrfy-a/stats.json"

[server]
port = 8081

[database]
path = "/var/lib/nostrfy-b"

[daemon]
pid_file = "/var/run/nostrfy-b.pid"
log_file = "/var/log/nostrfy-b.log"
stats_file = "/var/lib/nostrfy-b/stats.json"

Cada instancia se gestiona con su propia configuración: nostrfy --config /etc/nostrfy/a.toml start y más.

Despliegues a gran escala

El relé está diseñado para escalar a cientos de miles de conexiones en un solo host — la entrega en vivo solo despierta a los suscriptores que pueden coincidir con un evento y la memoria por conexión es pequeña. Para llegar al millón hace falta ajuste a nivel de host:

AjusteValorMotivo
ulimit -n / systemd LimitNOFILE≥ 2× las conexiones objetivo (+1000)cada conexión ocupa un fd
net.core.somaxconn≥ 1024Cola de accept pendiente ante picos de conexiones
net.ipv4.tcp_fin_timeoutbajo (por ejemplo, 10)Libera antes los sockets TIME_WAIT
vm.overcommit_memory1 o 2El mapa LMDB es una gran reserva virtual dispersa

En FreeBSD, los parámetros correspondientes son kern.maxfiles / kern.maxfilesperproc más ulimit -n, así como kern.ipc.somaxconn sustituye a net.core.somaxconn. La memoria de kernel por conexión es de unos 80 KiB y la de usuario unos 10 KiB, así que un millón de conexiones necesita unos 90 GiB de memoria de kernel y usuario además de la base de datos.

Rendimiento (eventos por segundo)

La escritura de eventos está limitada por dos costes: la verificación de firma Schnorr (unos 30-50 µs por evento) y el volcado síncrono a disco que el escritor LMDB realiza tras cada lote de commits. Ambos se ajustan en el archivo nostrfy.toml:

AjusteMotivo
database.disabled_fsync = trueCommit en la caché de páginas del SO (microsegundos); un corte de luz solo pierde las escrituras desde el último volcado — empieza por aquí
Núcleos de CPU ≥ 8 vCPUEl camino EVENT por lotes verifica firmas en paralelo entre núcleos
database.search_index = falseElimina la escritura del índice de palabras NIP-50 por evento para instancias con mucha escritura

La verificación paralela de firmas valida todas las firmas de un lote pendiente a la vez en un pool de hilos (máximo 8; los lotes de menos de 16 eventos se verifican en línea). Las comprobaciones baratas de cada evento siguen ejecutándose primero, así que el texto de rechazo es idéntico al camino secuencial — solo el trabajo Schnorr se reparte entre núcleos. Una compilación mono-hilo sigue siendo secuencial.

Límites antiabuso fijos

Algunos límites duros son fijos (no configurables) para que el relé siga respondiendo bajo abuso:

  • Un filtro contiene como máximo 512 ids, authors o kinds entradas; #... Los valores de etiquetas usan un presupuesto aparte de 512 valores. Los filtros más grandes se rechazan (CLOSED invalid: ...).
  • max_connections_per_sec_per_ip rastrea como máximo 10.000 IP de origen; cuando se llena, las IP no vistas se rechazan (fail closed).
  • ids de los filtros pueden ser prefijos, pero solo coinciden ids completos de 32 bytes y prefijos de longitud par (las entradas impares o vacías se ignoran tanto en el historial como en la entrega en vivo).
  • Las claves de índice demasiado largas (valores de etiquetas, palabras del contenido, etiquetas d más allá del límite de tamaño de clave de LMDB) se omiten al indexar; el evento se guarda igualmente.