Gestire il relay

Per il tuo relay nostrfy: avvio e arresto, log e statistiche, ricaricamento a caldo della configurazione, istanze multiple e ottimizzazione su larga scala.

Avvio e arresto

Avvia il relay come demone in background:

sh
nostrfy --config nostrfy.toml start

=> nostrfy started (pid 12345)

Oppure eseguilo in primo piano nel terminale:

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

Arresta:

sh
nostrfy --config nostrfy.toml stop

Verifica che sia attivo:

sh
curl http://127.0.0.1:8080/health

=> {"status":"ok"}

Log e statistiche

Il demone scrive in daemon.log_file. Quando il file supera max_log_size_bytes viene ruotato automaticamente (nostrfy.log.1, .2…fino a max_log_files generazioni):

sh
tail -f nostrfy.log

Il livello di log è controllato dalla variabile d’ambiente RUST_LOG (ad esempio, RUST_LOG=debug).

Statistiche

Statistiche in tempo reale dalla CLI:

sh
nostrfy stats

Oppure via HTTP:

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

Mostra connessioni, eventi accettati/rifiutati, dimensione del database e altro.

Metriche Prometheus

sh
curl http://127.0.0.1:8080/metrics

Ricaricamento a caldo (SIGHUP)

Dopo aver modificato il file di configurazione, ricaricalo senza riavvio:

sh
kill -HUP $(cat nostrfy.pid)
Si applica alla ricaricaRichiede riavvio
Identità del relay, public_urlprivate_key
la maggior parte di [limits], reject_ephemeral, enabled_git, enabled_nip78_authapi_host, metrics_enabled, impostazioni LiveKit
—enabled_nips / disabled_nips, server.host / port / ws_paths
—database.* (incluso search_index), blossom.*

Il log avverte quando cambia un’impostazione che richiede il riavvio.

Eseguire più istanze

nostrfy supporta più relay indipendenti su un solo server (porte diverse). Ogni istanza necessita di propri server.port, propri pid_file/log_file/stats_file della sezione [daemon] (valori condivisi fanno sì che la seconda istanza rifiuti l’avvio con already running), database.path, nonché (se usati) i propri 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"

Ogni istanza è gestita con la propria configurazione: nostrfy --config /etc/nostrfy/a.toml start ecc.

Distribuzioni su larga scala

Il relay è progettato per scalare a centinaia di migliaia di connessioni su un singolo host — la consegna live risveglia solo gli abbonati che possono corrispondere a un evento e la memoria per connessione resta contenuta. Per milioni serve una messa a punto a livello di host:

ImpostazioneValoreMotivo
ulimit -n / systemd LimitNOFILE≥ 2× le connessioni obiettivo (+1000)ogni connessione occupa un fd
net.core.somaxconn≥ 1024Coda di accept in attesa nei picchi di connessioni
net.ipv4.tcp_fin_timeoutbasso (ad esempio, 10)Libera più rapidamente i socket TIME_WAIT
vm.overcommit_memory1 o 2La mappa LMDB è una grande prenotazione virtuale sparsa

Su FreeBSD i parametri corrispondenti sono kern.maxfiles / kern.maxfilesperproc più ulimit -n, nonché kern.ipc.somaxconn sostituisce net.core.somaxconn. La memoria kernel per connessione è di circa 80 KiB, quella utente di circa 10 KiB, quindi un milione di connessioni richiede circa 90 GiB di memoria kernel e utente oltre al database.

Throughput (eventi al secondo)

La scrittura degli eventi è limitata da due costi: la verifica della firma Schnorr (circa 30–50 µs per evento) e il flush sincrono su disco che lo scrittore LMDB esegue dopo ogni batch di commit. Entrambi si regolano nel file nostrfy.toml:

ImpostazioneMotivo
database.disabled_fsync = trueCommit nella page cache del SO (microsecondi); un’interruzione di corrente perde solo le scritture dall’ultimo flush — inizia da qui
Core CPU ≥ 8 vCPUIl percorso EVENT in batch verifica le firme in parallelo sui core
database.search_index = falseElimina la scrittura dell’indice parole NIP-50 per evento nelle istanze a scrittura intensa

La verifica parallela delle firme convalida tutte le firme di un batch in attesa in una volta sola, su un pool di thread (massimo 8; i batch con meno di 16 eventi sono verificati inline). I controlli economici di ogni evento restano i primi, quindi il testo di rifiuto è identico al percorso sequenziale — solo il lavoro Schnorr è distribuito tra i core. Una build single-thread resta sequenziale.

Limiti anti-abuso fissi

Alcuni limiti rigidi sono fissi (non configurabili) per mantenere il relay reattivo sotto abusi:

  • Un filtro contiene al massimo 512 voci tra ids, authors o kinds; i valori dei tag #... usano un budget separato di 512 valori. I filtri più grandi vengono rifiutati (CLOSED invalid: ...).
  • max_connections_per_sec_per_ip tiene traccia di al massimo 10.000 IP di origine; quando è pieno, gli IP mai visti vengono rifiutati (con blocco in caso di saturazione).
  • Gli ids dei filtri possono essere prefissi, ma corrispondono solo a id completi di 32 byte e a prefissi di lunghezza pari (le voci dispari o vuote sono ignorate sia nella cronologia sia nella consegna live).
  • Chiavi di indice troppo lunghe (valori dei tag, parole del contenuto, tag d oltre il limite di dimensione delle chiavi LMDB) vengono saltate all’indicizzazione; l’evento viene comunque memorizzato.