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:
nostrfy --config nostrfy.toml start=> nostrfy started (pid 12345)
Oppure eseguilo in primo piano nel terminale:
nostrfy --config nostrfy.toml start --foregroundArresta:
nostrfy --config nostrfy.toml stopVerifica che sia attivo:
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):
tail -f nostrfy.logIl livello di log è controllato dalla variabile d’ambiente RUST_LOG (ad esempio, RUST_LOG=debug).
Statistiche
Statistiche in tempo reale dalla CLI:
nostrfy statsOppure via HTTP:
curl http://127.0.0.1:8080/relay/statsMostra connessioni, eventi accettati/rifiutati, dimensione del database e altro.
Metriche Prometheus
curl http://127.0.0.1:8080/metricsRicaricamento a caldo (SIGHUP)
Dopo aver modificato il file di configurazione, ricaricalo senza riavvio:
kill -HUP $(cat nostrfy.pid)| Si applica alla ricarica | Richiede riavvio |
|---|---|
| Identità del relay, public_url | private_key |
| la maggior parte di [limits], reject_ephemeral, enabled_git, enabled_nip78_auth | api_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:
[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:
| Impostazione | Valore | Motivo |
|---|---|---|
ulimit -n / systemd LimitNOFILE | ≥ 2× le connessioni obiettivo (+1000) | ogni connessione occupa un fd |
net.core.somaxconn | ≥ 1024 | Coda di accept in attesa nei picchi di connessioni |
net.ipv4.tcp_fin_timeout | basso (ad esempio, 10) | Libera più rapidamente i socket TIME_WAIT |
vm.overcommit_memory | 1 o 2 | La 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:
| Impostazione | Motivo |
|---|---|
database.disabled_fsync = true | Commit nella page cache del SO (microsecondi); un’interruzione di corrente perde solo le scritture dall’ultimo flush — inizia da qui |
| Core CPU ≥ 8 vCPU | Il percorso EVENT in batch verifica le firme in parallelo sui core |
database.search_index = false | Elimina 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,authorsokinds; i valori dei tag#...usano un budget separato di 512 valori. I filtri più grandi vengono rifiutati (CLOSED invalid: ...). max_connections_per_sec_per_iptiene traccia di al massimo 10.000 IP di origine; quando è pieno, gli IP mai visti vengono rifiutati (con blocco in caso di saturazione).- Gli
idsdei 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
doltre il limite di dimensione delle chiavi LMDB) vengono saltate all’indicizzazione; l’evento viene comunque memorizzato.