Référence de configuration

Référence complète pour nostrfy.toml : chaque clé, son type, sa valeur par défaut et exactement ce qu’elle fait — limites, base de données, démon, contrôle d’accès et Blossom.

Bases

La configuration est un fichier TOML, par défaut nommé nostrfy.toml. Créez-le avec init :

sh
nostrfy --config nostrfy.toml init

Validez-le (recommandé avant chaque démarrage) :

sh
nostrfy --config nostrfy.toml check

Chaque commande accepte --config <path> (par défaut nostrfy.toml).

Syntaxe générale :

toml
[section]
key = "string"
key = 8080
key = [1, 2]
key = true

Sections de configuration

SectionObjet
[relay]Identité, URLs et interrupteurs NIP
[server]Liaison réseau, séparation API, métriques
[rpc]RPC de gestion NIP-86 (auth, limite de corps)
[limits]Toutes les limites et protections contre la surcharge
[database]Stockage LMDB, index de recherche, plafonds de file
[daemon]Fichiers PID, journal et statistiques, et rotation
[access]Listes de contrôle d’accès initiales (modifiables à l’exécution)
[blossom]Serveur de fichiers Blossom (hébergement média)

Chaque clé est optionnelle ; une clé manquante utilise sa valeur par défaut.

Section [relay] — identité du relais

CléTypeDéfautDescription
namestring"nostrfy"Nom du relais affiché aux clients via NIP-11
descriptionstring"A minimal and stable Nostr relay"Description du relais (NIP-11)
pubkeystring (64 hex)""Clé publique de l’administrateur (champ pubkey NIP-11)
contactstring""URI de contact de l’administrateur (mailto: ou https://)
iconstring""URL de l’image d’icône du relais
post_policystring""URL pointant vers la politique de publication du relais
private_keystring (64 hex)""Clé secrète propre au relais ; requise pour les groupes NIP-29
public_urlstring""URL publique, p. ex. wss://relay.example.com
livekit_urlstring""URL du serveur LiveKit pour les salons audio/vidéo NIP-29
livekit_api_keystring""Clé API LiveKit
livekit_api_secretstring""Secret API LiveKit (utilisé pour signer les JWT)
livekit_participants_interval_secsinteger15Intervalle en secondes entre les rafraîchissements de la liste des participants LiveKit (l’événement 39004 de NIP-29)
enabled_nipsarray of integers[]Liste d’autorisation NIP explicite
disabled_nipsarray of integers[]NIPs à désactiver (ignoré quand enabled_nips est non vide)
reject_ephemeralbooleanfalseRejeter les événements éphémères NIP-01 (kinds 20000–29999)
enabled_gitbooleanfalseAccepter les événements git NIP-34 (kinds 1617–1633, 30617/30618)
require_powinteger0Preuve de travail requise en bits zéro initiaux
new_pubkey_min_age_secsinteger0Refuser les événements des pubkeys plus jeunes que cette valeur (secondes ; 0 = désactivé)
max_events_per_min_per_pubkeyinteger0Limite de débit de publication par pubkey (par minute ; 0 = sans limite)
max_groupsinteger1000Plafond du magasin de groupes NIP-29 en mémoire
require_authbooleanfalseExiger l’authentification NIP-42 pour REQ/EVENT/COUNT/NEG (les lectures via l’API REST exigent NIP-98)
send_auth_challengebooleantrueEnvoyer le défi AUTH à la connexion
enabled_nip78_authbooleantrueExiger AUTH NIP-42 avant d’accepter les événements kind 78/30078
enabled_command_eventsbooleanfalseExécuter les commandes opérateur kind:1 rédigées par la pubkey admin

Détails des clés

  • private_key — clé secrète propre au relais, utilisée pour signer les événements générés par le relais : métadonnées de groupes NIP-29 (39000–39005) et événements de rôles/membres NIP-43. Générez-la avec nostrfy genkey ; gardez-la secrète. Elle est lue une fois au démarrage, donc toute modification exige un redémarrage. Un redémarrage répare aussi les métadonnées de groupes stockées — les événements signés par l’ancienne clé sont supprimés et l’état actuel est republié sous la nouvelle clé (l’état des groupes lui-même est restauré tel quel, pas reconstruit). L’état des rôles NIP-43 (adhésions, rôles et codes d’invitation) est réparé de la même façon.
  • livekit_participants_interval_secs — fréquence (en secondes) à laquelle le relais rafraîchit les listes de participants NIP-29 kind:39004 en appelant l’API LiveKit Room Service (ListParticipants) avec les identifiants configurés. Les webhooks LiveKit envoyés à /.well-known/nip29/livekit/webhook rafraîchissent immédiatement la liste d’un groupe ; le sondage réconcilie les événements manqués. Doit être au moins 1. Figé au démarrage — exige un redémarrage.
  • public_url — utilisée pour valider les tags porteurs d’URL des clients : AUTH NIP-42, vanish NIP-62 et auth admin NIP-98. Quand elle est vide, le relais se replie sur host:port, qui ne correspond jamais à une vraie URL client lors de la liaison à 0.0.0.0 ou 127.0.0.1 (un avertissement est journalisé). Définissez-la toujours.
  • enabled_nips vs disabled_nips — la liste d’autorisation l’emporte : quand enabled_nips est non vide, seuls ses NIPs sont annoncés et disabled_nips est ignoré. Les deux exigent un redémarrage.
  • reject_ephemeral — les kinds 20000–29999 sont rejetés, mais les kinds exemptés que les NIPs exigent de relayer sont toujours transmis : 22242, 27235, 28934/28935/28936, 24133, 23194/23195, 24242 et 21059. S’applique sur SIGHUP.
  • enabled_git — opt-in NIP-34 : accepte les kinds 1617–1633 et 30617/30618 et annonce NIP-34. Désactivé par défaut car les charges de patch peuvent être volumineuses. S’applique sur SIGHUP.

Section [server] — paramètres serveur

CléTypeDéfautDescription
hoststring"127.0.0.1"Adresse de liaison ; 0.0.0.0 accepte les connexions de partout
portinteger8080Port (1–65535) ; le port 80 exige root
api_hoststring""Nom d’hôte dédié à l’API REST
metrics_enabledbooleantrueServir les métriques Prometheus sur /metrics
ws_pathsstring"root"Chemins des points de terminaison WebSocket : root, inbox-outbox ou all
inbox_write_policystring"any"Qui peut écrire sur /inbox : « any » ou « relay » (les événements doivent toujours porter un tag p)
outbox_write_policystring"any"Qui peut écrire sur /outbox : « any » (propres événements de la pubkey authentifiée NIP-42) ou « relay »
trusted_proxiesarray of strings[]Adresses/CIDRs de reverse-proxy dont le X-Forwarded-For est de confiance (vide = aucun proxy de confiance)
landing_page_filestring""Fichier HTML affiché à un navigateur ouvrant l’URL du relais, à la place de la page leurre intégrée (vide = leurre)
assets_dirstring""Répertoire servi sous /assets/<name> pour la page d’accueil (vide = pas de route /assets/)

Détails des clés

  • host — 0.0.0.0 lie toutes les interfaces IPv4 ; 127.0.0.1 est local uniquement.
  • port — 1–65535 ; le port 80 exige root. Ce port unique sert ensemble le relais WebSocket, le document NIP-11, l’API REST et le RPC NIP-86.
  • api_host — dédie l’API REST à un seul nom d’hôte pour que l’API et le relais puissent partager un port derrière un reverse-proxy. Figé au démarrage — exige un redémarrage.
  • ws_paths — root sert uniquement /, inbox-outbox sert uniquement /inbox et /outbox, all sert les deux. Figé au démarrage — exige un redémarrage.
  • trusted_proxies — listez uniquement les propres adresses du proxy (loopback pour nginx/Caddy sur le même hôte, plage source de l’équilibreur dans le cloud). Si défini, l’IP client est dérivée de la dernière entrée X-Forwarded-For non de confiance pour les plafonds par IP, la limite de débit, blockip et les logs. N’ajoutez jamais une adresse joignable directement par les clients — ils pourraient falsifier l’en-tête et contourner les limites par IP. Figé au démarrage — exige un redémarrage.
  • landing_page_file — par défaut, un navigateur ouvrant l’URL du relais reçoit une page leurre intégrée qui ne révèle rien sur le relais. Pointez ceci vers un fichier HTML pour servir votre propre page (règles du relais, contact, statistiques) ; le document NIP-11 et les connexions WebSocket ne sont pas affectés. Le fichier est lu à la demande et relu lorsqu’il change, donc une tâche externe peut le régénérer sans redémarrage. Il doit être un fichier régulier d’au plus 8 MiB (les liens symboliques ne sont pas suivis) ; s’il manque, la page leurre est servie. S’applique au SIGHUP.
  • assets_dir — répertoire dont les fichiers sont servis sous /assets/<name> (images, CSS, JS de la page d’accueil). Seuls des noms plats en ASCII (lettres, chiffres, ., _, -) sont servis (pas de fichiers cachés, sous-répertoires ni liens symboliques) ; les extensions inconnues sont envoyées en application/octet-stream. Les fichiers sont lus à chaque requête et peuvent donc être remplacés sur place. Figé au démarrage — exige un redémarrage.

Section [rpc] — gestion NIP-86

CléTypeDéfautDescription
management_tokenstring""Jeton Bearer pour les API de gestion
admin_pubkeystring (64 hex)""Pubkey administrateur pour l’auth de gestion NIP-98
max_admin_body_bytesinteger65536Limite de corps pour le RPC de gestion NIP-86

Le RPC NIP-86 est monté sur les routes publiques POST / du relais — il n’y a pas de port de gestion séparé. management_token et admin_pubkey apparaissent parfois sous [server] dans les anciens guides ; ces orthographes sont des alias historiques de ces clés [rpc].

Section [limits] — limites et protections

Connexions et messages

CléTypeDéfautDescription
max_connectionsinteger10000Connexions simultanées maximales
max_connections_per_ipinteger64Max. de connexions par IP source
max_ws_message_bytesinteger1048576Max. d’octets par message/frame WebSocket
socket_recv_buffer_kbinteger64Tampon de réception noyau par connexion (Kio)
max_out_queue_bytesinteger262144Plafond de file sortante par connexion (octets)
ws_idle_timeout_secsinteger300Fermer les connexions inactives après ce délai
http_read_timeout_secsinteger30Délai d’en-tête de requête HTTP (défense slow-loris)
max_connections_per_sec_per_ipinteger0Max. de nouvelles connexions par seconde par IP source

Abonnements et requêtes

CléTypeDéfautDescription
max_filtersinteger20Max. de filtres par REQ
max_subscriptionsinteger20Max. d’abonnements par connexion
max_limitinteger500Plafond pour la limite REQ
max_countinteger2000Plafond pour les résultats COUNT
max_sub_id_leninteger64Longueur max. d’id d’abonnement (caractères, pas octets)
max_sub_bytesinteger1048576Total d’octets de filtres d’abonnement par connexion
max_req_response_bytesinteger33554432 (32 Mo)Plafond du total d’octets qu’une réponse REQ peut envoyer ; les réponses qui tiennent dans la file sortante sont livrées en entier ; les pages de requête de l’API REST appliquent le même budget

Événements

CléTypeDéfautDescription
max_content_bytesinteger65536Longueur max. du contenu d’événement en caractères
max_tagsinteger2000Max. de tags par événement
max_tag_value_bytesinteger1024Max. d’octets par valeur de tag
max_created_at_future_secsinteger3600Écart futur toléré de created_at
group_late_publish_secsinteger3600Retard toléré pour les événements admin de groupes NIP-29 (secondes)
max_neg_itemsinteger100000Max. d’enregistrements par synchronisation negentropy NIP-77

Alias historiques : limits.require_pow, limits.new_pubkey_min_age_secs et limits.max_indexed_words sont toujours acceptés comme alias de relay.require_pow, relay.new_pubkey_min_age_secs et database.max_indexed_words.

API REST

CléTypeDéfautDescription
max_api_concurrentinteger8Max. de requêtes /api/v1 simultanées
max_api_limitinteger5000Plafond pour le paramètre limit de l’API
max_api_offsetinteger50000Plafond pour le paramètre offset de l’API
max_api_fetchinteger55001Fenêtre de sur-récupération max. pour les requêtes offset — doit couvrir max_api_offset + max_api_limit + 1 (0 = sans borne)
max_api_search_bytesinteger2048Max. d’octets du paramètre search de l’API

Diffusion live

CléTypeDéfautDescription
live_batch_interval_msinteger20Fréquence de vidage des événements live (ms)
live_batch_sizeinteger32Max. d’événements par lot live
live_bufferinteger65536Taille de la file de diffusion live ; au-delà de 10 000 000, refusé au check/démarrage ; au-delà de 1 000 000, avertissement

Section [database] — base de données

CléTypeDéfautDescription
pathstring"./data"Répertoire de la base de données (LMDB)
max_dbsinteger32Max. de bases nommées LMDB
max_readersinteger128Max. de lecteurs simultanés LMDB
map_sizeinteger1073741824 (1 Go)Plancher pour la taille du memory map (octets)
max_map_sizeinteger1099511627776 (1 TB)Plafond du memory-map (octets)
purge_interval_secsinteger300Intervalle de purge NIP-40 (secondes)
search_indexbooleantrueActiver l’index de mots NIP-50
reader_threadsinteger2Threads de scan dédiés
max_indexed_wordsinteger32Mots du contenu de chaque événement indexés pour la recherche
meta_indexbooleantrueÉcrire l’en-tête de métadonnées par événement utilisé par le préfiltre de scan
disabled_fsyncbooleanfalseIgnorer le vidage disque synchrone après chaque lot d’écriture
db_buffer_sizeinteger2048Tampon WebSocket initial par connexion (octets) ; doit rester sous la limite de tampon d’écriture dérivée de max_ws_message_bytes / max_neg_items (sinon refusé au check/démarrage)
db_request_timeout_secsinteger30Durée d’attente possible d’une requête base avant échec
max_db_queue_msgsinteger4096Max. de messages en attente avant échec rapide
max_db_queue_eventsinteger262144Max. d’événements dans les lots en attente avant échec rapide
max_db_queue_bytesinteger268435456 (256 MiB)Max. d’octets de requêtes base en file avant échec rapide (0 = sans plafond d’octets)

Détails des clés

  • map_size — le plancher pour le memory map : la map est toujours ouverte au moins à cette taille.
  • max_map_size — le plafond, ouvert comme réservation virtuelle éparse : le disque physique ne croît qu’avec les données réellement écrites. Augmentez-le en cas de database map is full.
  • search_index = false — la recherche fonctionne toujours (correspondance de mots entiers dans le contenu) mais les scans sont plus lents ; sur un petit VPS cela divise la base par deux. Recommandé sur les petites instances.
  • disabled_fsync — échange la durabilité contre le débit : les écritures sont validées dans le cache de pages OS et une coupure de courant peut perdre les écritures les plus récentes.

Section [daemon] — démon

CléTypeDéfautDescription
pid_filestring"./nostrfy.pid"Chemin du fichier PID
log_filestring"./nostrfy.log"Chemin du fichier de log ; créé accessible au propriétaire uniquement (0600) — il contient les IP et pubkeys des clients
stats_filestring"./nostrfy.stats.json"Chemin du fichier de statistiques ; l’instantané est réservé au propriétaire (0600) et un sous-ensemble public est servi sur /relay/stats
stats_interval_secsinteger5Intervalle d’écriture des statistiques (secondes)
max_log_size_bytesinteger52428800 (50 Mo)Taille de rotation des logs (0 = sans rotation)
max_log_filesinteger5Générations de logs pivotés à conserver

Les chemins sont résolus par rapport au répertoire du fichier de configuration, donc ils restent valides après que le démon change son répertoire de travail.

/relay/stats ne demande aucun jeton et est lisible en cross-origin, il sert donc une vue plus étroite que le fichier de statistiques : l’espace disque libre de l’hôte et l’indicateur de disque plein, les compteurs d’échecs (db_errors, accept_errors, rebuild_failures, log_errors) et la répartition des refus de connexion par motif sont omis — ensemble, ils constitueraient un oracle de capacité de stockage pour un sondeur anonyme. Ces clés restent dans le fichier de statistiques (nostrfy stats les affiche) et dans /metrics. Notez que /metrics n’est pas authentifié non plus : isolez-le (api_host ou reverse-proxy) si les chiffres de capacité doivent rester privés.

Section [access] — contrôle d’accès

CléTypeDéfautDescription
restrict_relaybooleanfalseSeules les pubkeys autorisées peuvent publier
blocked_kindsarray of integers[]Kinds à rejeter
allowed_kindsarray of integers[]Liste d’autorisation de kinds ; seuls ces kinds sont acceptés quand elle est non vide
blocked_ipsarray of strings[]Adresses IP refusées au moment de la connexion
method_grantstable: pubkey → array of strings{}Octrois de méthodes NIP-86 pour les pubkeys non-admin (gérés à l’exécution avec assignmethod)

Les listes d’autorisation/refus de pubkeys ne sont pas des clés de config — elles vivent dans la base du relais (LMDB) et sont gérées à l’exécution :

sh
nostrfy relay allow npub1...
nostrfy relay deny npub1...
nostrfy relay list
  • restrict_relay = true — seules les pubkeys autorisées peuvent publier, tandis que la lecture reste ouverte à tous (tout client peut toujours s’abonner et récupérer).
  • Une pubkey refusée est toujours rejetée à la publication et jamais servie à la lecture.
  • method_grants — octrois de méthodes NIP-86 pour les pubkeys non-admin (pubkey → noms de méthodes, p. ex. un modérateur autorisé avec banevent et listbannedevents). Initialisés depuis la config au premier lancement, puis gérés à l’exécution avec NIP-86 assignmethod/unassignmethod (inspectés avec listmethodassignees). Seules les méthodes de modération et de lecture sont octroyables — la gestion des permissions, rôles, revendications d’invitation et identité du relais reste réservée à l’admin, et une pubkey bannie est refusée même avec des octrois. Voir l' API de gestion.

Section [blossom] — serveur de fichiers Blossom

CléTypeDéfautDescription
hoststring""Nom d’hôte pour le serveur Blossom (vide = désactivé)
storagestring"local"Backend : « local » (local_path) ou « s3 » (bucket compatible S3)
local_pathstring"/var/lib/nostrfy/images"Racine de stockage local pour les fichiers média
max_upload_bytesinteger20971520 (20 Mo)Taille max. de fichier média
min_free_bytesinteger33554432 (32 Mo)Espace disque sous lequel les téléversements sont refusés
s3_endpointstring""Point de terminaison compatible S3 (p. ex. R2)
s3_regionstring""Région S3 (R2 utilise « auto »)
s3_bucketstring""Nom du bucket S3
s3_access_keystring""Clé d’accès S3
s3_secret_keystring""Clé secrète S3
restrict_uploadsbooleanfalseSeules les pubkeys autorisées peuvent téléverser

Rechargement à l’exécution (SIGHUP)

Modifier le fichier et envoyer kill -HUP $(cat nostrfy.pid) recharge la configuration sans redémarrage. La plupart des réglages prennent effet immédiatement ; quelques-uns sont figés au démarrage :

S’applique sur SIGHUPExige un redémarrage
relay.name, description, pubkey, contact, icon, post_policy, public_urlrelay.private_key
reject_ephemeral, enabled_git, enabled_nip78_authrelay.livekit_*, enabled_nips / disabled_nips
la plupart des limites, landing_page_fileapi_host, trusted_proxies, metrics_enabled, ws_paths, assets_dir, database.*, tailles du démon, plafonds de limites, blossom.*

[access] n’est pas appliqué par un rechargement — les listes sont initialisées une fois au démarrage puis gérées à l’exécution via NIP-86. Le log avertit quand un réglage exigeant un redémarrage a changé, et quelques réglages capturés au démarrage ne sont pas vérifiés par le rechargement.

Erreurs fréquentes
ErreurCorrectif
public_url non définidéfinissez wss://...
host laissé à 127.0.0.1les clients externes ne peuvent pas se connecter
private_key non définie avec NIP-29exécutez nostrfy genkey + redémarrage
restrict_relay true avec allowlist videtout le monde est verrouillé
clés exigeant un redémarrage modifiées avec seulement un SIGHUPutilisez nostrfy restart