Fehlerbehebung
Die Fehler, denen Sie am wahrscheinlichsten begegnen — Ports, Berechtigungen, TLS, fehlende NIPs, Veröffentlichen und Timeouts — mit Schritt-für-Schritt-Lösungen.
Drei Dinge zuerst prüfen:
nostrfy checkvalidiert Ihre Konfiguration (die meisten Fehler sind Konfigurationsfehler).tail -f nostrfy.logzeigt das Protokoll — die Ursache steht fast immer dort.nostrfy restartstartet den Daemon sauber neu.
Startet nicht
error: cannot bind to 0.0.0.0:80: Permission denied
Ursache: Port 80 kann nur von root gebunden werden.
Lösung: Mit sudo ausführen oder den Port z. B. auf 8080 ändern.
# port = 8080 in der Konfigurationsdatei ändern, dann:
nostrfy --config nostrfy.toml starterror: cannot bind to ...: Address already in use
Ursache: Ein anderer Prozess (ein altes nostrfy oder ein anderer Server) verwendet den Port bereits.
Lösung:
ss -tlnp | grep :8080# Wenn nostrfy läuft, neu starten
nostrfy --config nostrfy.toml restartalready running (pid 1234); use 'nostrfy stop' or 'nostrfy restart'
Ursache: nostrfy läuft bereits; start verweigert den Start einer zweiten Instanz.
Lösung: nostrfy restart verwenden oder einfach die laufende Instanz nutzen.
nostrfy stop hängt / did not stop in time
Ursache: Der Daemon hängt fest oder antwortet nicht.
Lösung:
ps aux | grep nostrfy
kill -9 <PID>
# Veraltete Pid-Datei entfernen, falls vorhanden
rm -f nostrfy.piderror: invalid nostrfy.toml: TOML parse error
Ursache: Die Konfigurationsdatei ist kein gültiges TOML. Typische Fehler: vergessene Anführungszeichen um einen String oder derselbe Schlüssel doppelt geschrieben.
Lösung: Die Fehlermeldung enthält eine Zeilennummer. Diese Zeile prüfen und korrigieren.
# Korrekte Beispiele
name = "my relay" # Strings werden mit " zitiert
port = 8080 # Zahlen stehen ohne Anführungszeichen
enabled_nips = [1, 50] # Listen stehen in [ ]error: cannot read nostrfy.toml: No such file or directory
Ursache: Die Konfigurationsdatei existiert nicht.
Lösung:
nostrfy --config nostrfy.toml initerror: relay.private_key is not a valid secp256k1 secret key
Ursache: relay.private_key ist kein gültiger 64-stelliger Hex-Schlüssel.
Lösung: nostrfy genkey ausführen, um einen korrekten Schlüssel zu erzeugen (oder private_key = "" setzen).
Viele Warnungen im Protokoll beim Start
[WARN]-Zeilen weisen auf Konfigurationsprobleme hin. Die wichtigsten:
| Warnung | Bedeutung und Lösung |
|---|---|
relay.public_url is empty and server.host is "0.0.0.0"... | public_url ist nicht gesetzt — NIP-42-Auth, NIP-62-Vanish und NIP-98-Admin-Auth funktionieren nicht. wss://your-public-url setzen. |
relay.private_key is empty while NIP-29 is enabled... | Gruppen brauchen einen geheimen Schlüssel. nostrfy genkey ausführen. |
unknown config key [relay].software is ignored | Ein ungenutzter Legacy-Schlüssel (oder Tippfehler) in der Konfiguration. Schlüsselnamen prüfen. |
unknown config section [serve] is ignored | Tippfehler in einem Abschnittsnamen (z. B. [serve] statt [server]). Korrigieren. |
relay.require_auth is true but relay.send_auth_challenge is false... | Diese Kombination sperrt alle aus. Einen der beiden Werte ändern. |
relay.require_pow = 64 ... practically unmineable | Die PoW-Anforderung ist so hoch, dass niemand posten kann. require_pow senken. |
Kann nicht verbinden oder verhält sich seltsam
Client erhält connection refused
Ursache: Das Relay läuft nicht oder eine Firewall blockiert den Port.
Lösung:
curl http://127.0.0.1:8080/health
# Von außen (mit IP/Port des Servers)
curl http://YOUR_SERVER_IP:8080/health
# Firewall prüfen (Beispiel: ufw)
sudo ufw status
# Port bei Bedarf öffnen
sudo ufw allow 8080Externe Clients können nicht verbinden, lokale schon
Ursache: server.host steht noch auf 127.0.0.1 (Standard) und akzeptiert nur lokale Verbindungen.
Lösung: In der Konfiguration host = "0.0.0.0" setzen und neu starten.
Keine Verbindung über einen Cloudflare-Tunnel
Bei Verwendung von Cloudflare Tunnel:
- Das Relay läuft mit plain HTTP; Cloudflare terminiert TLS, daher verwenden Clients
wss://. Auf dem Relaypublic_url = "wss://..."setzen (damit funktioniert NIP-42-Auth). - Cloudflare fügt einen
X-Forwarded-Proto-Header hinzu. nostrfy behandelt die Wertews/wss/http/httpsgleich, daher ist normalerweise keine zusätzliche Konfiguration nötig.
error: message too large, und die Verbindung schließt sich
Ursache: Eine einzelne Nachricht überschreitet max_ws_message_bytes (Standard 1 MB).
Lösung: limits.max_ws_message_bytes erhöhen, wenn größere Events nötig sind — aber auch die Limits des Clients prüfen.
Fehler too many subscriptions / too many filters
Ursache: Die Caps pro Verbindung wurden erreicht (Subscriptions Standard 20, Filter Standard 20).
Lösung: limits.max_subscriptions / limits.max_filters erhöhen (und die Client-Einstellungen prüfen).
Neue Verbindungen werden unter Last abgewiesen
Ursache: max_connections (Standard 10000) wurde erreicht, das Cap pro IP
(max_connections_per_ip, Standard 64) hat gegriffen, oder das Verbindungsratenlimit pro Sekunde und IP
(max_connections_per_sec_per_ip) hat den Burst abgewiesen. Die Caps gelten für jede Verbindung — WebSocket wie plain HTTP.
Lösung: Die Einstellungen prüfen und anpassen. max_connections_per_ip = 0 deaktiviert das Cap pro IP; max_connections_per_sec_per_ip = 0 deaktiviert das Ratenlimit. Diese drei Einstellungen erfordern einen Neustart.
Verbindungen brechen nach einer Weile ab
Ursache: Wenn ws_idle_timeout_secs gesetzt ist, werden untätige Verbindungen geschlossen. Gesunde Clients beantworten das PING des Relays mit PONG und bleiben verbunden; nur tote Peers werden entfernt.
Lösung: Das ist beabsichtigt — Standard sind 300 Sekunden. Mit ws_idle_timeout_secs = 0 ganz deaktivieren.
Eine Subscription endet mit CLOSED ... response too large
Ursache: Die gespeicherten Events eines REQ haben max_req_response_bytes überschritten (Standard 32 MiB). Passiert nur bei sehr großen Events oder sehr breiten Filtern.
Lösung: Den Filter einengen (strengeres since / until, kleineres limit) oder max_req_response_bytes erhöhen (0 deaktiviert das Budget).
Ein NIP fehlt in der NIP-11-Liste supported_nips
Ursache: Die annoncierte Liste ist dynamisch — ein NIP wird ausgeblendet, wenn alle von ihm definierten Kinds abgelehnt werden: alle stehen in blocked_kinds, keiner steht in allowed_kinds, oder es sind ephemere Kinds, die per reject_ephemeral abgelehnt werden.
NIP-29/43/66 erfordern zusätzlich relay.private_key, und NIP-86 erfordert rpc.management_token oder rpc.admin_pubkey.
Lösung: Die aktiven Zugriffslisten prüfen — NIP-86-listallowedkinds zeigt die Kind-Allowlist, und GET / zeigt sofort die effektiven supported_nips.
Den blockierenden Kind oder die reject_ephemeral-Einstellung entfernen.
Fehler beim Veröffentlichen
Wenn das Veröffentlichen fehlschlägt, erklärt das 4. Element der OK-Nachricht den Grund. Die häufigsten:
| Fehler | Bedeutung und Lösung |
|---|---|
invalid: signature verification failed | Die Event-Signatur ist ungültig (möglicherweise ein defekter Client-Schlüssel). |
invalid: content too large | Der Inhalt überschreitet max_content_bytes (Standard 64K Zeichen). Kürzen oder das Limit erhöhen. |
invalid: too many tags | Mehr Tags als max_tags (Standard 2000). |
invalid: event creation date is in the future | Zeitstempel liegt zu weit in der Zukunft (jenseits von max_created_at_future_secs). |
mute: event contains secret key material | Inhalt oder Tags enthalten einen nsec-artigen String. Niemals geheime Schlüssel posten. Den String entfernen, dann wird das Event akzeptiert. |
duplicate: event already stored | Dasselbe Event ist bereits gespeichert (normal). |
blocked: pubkey not allowed | Der Pubkey ist gebannt (banpubkey) oder außerhalb der Allowlist. |
blocked: kind not allowed | Dieser Kind ist nicht erlaubt. |
rate-limited: too many events | Der Pubkey hat max_events_per_min_per_pubkey überschritten (gleitendes 60-Sekunden-Fenster). Eine Minute warten und erneut versuchen oder das Limit erhöhen/deaktivieren. |
blocked: event has been banned | Die Event-ID ist gebannt. |
blocked: event has been deleted | Erneutes Veröffentlichen eines gelöschten Events. |
auth-required: ... | Authentifizierung ist erforderlich (wenn relay.require_auth aktiv ist). |
restricted: your account is too new | Das Konto wurde innerhalb von new_pubkey_min_age_secs erstellt. Warten und erneut versuchen. |
restricted: unknown group | Die Gruppe existiert nicht (zuerst erstellen). |
restricted: this group is closed | Die Gruppe ist closed; Beitrittsanfragen ohne Einladungscode werden nicht honoriert. |
Blossom-Dateiserver
Upload schlägt mit 401 fehl
Das Upload-Autorisierungs-Event (Kind 24242) wurde abgelehnt. Prüfen, ob:
- der
expiration-Tag des Tokens vorhanden ist und auf einen Unix-Zeitstempel in der Zukunft gesetzt ist, - für upload/media/delete das Token einen
x-Tag mit dem sha256 des Blobs trägt, - der
server-Tag (falls vorhanden) genau den konfiguriertenblossom.hostnennt (nur Hostname, ohne Schema/Pfad), - das Token innerhalb der letzten 10 Minuten signiert wurde (Frische-Fenster gegen Replay),
- und der Signierschlüssel dem Uploader selbst gehört.
Upload schlägt mit 403 fehl
blossom.restrict_uploads = true ist gesetzt und der Pubkey steht nicht auf der Allowlist — mit nostrfy blossom allow npub1... hinzufügen (der Daemon lädt automatisch neu). Wenn die Liste falsch aussieht, zeigt nostrfy blossom list sie an.
Upload schlägt mit 409 fehl
Der Client hat einen X-SHA-256-Header gesendet, der nicht zum tatsächlichen Request-Body passt (der deklarierte Hash wurde über andere Bytes berechnet — z. B. hat sich die Datei zwischen Hashing und Senden geändert).
Clients können den Header ganz weglassen.
GET / auf dem Media-Host liefert das NIP-11-Dokument
Die Anfrage hat das Relay nicht mit dem Blossom-Host-Header erreicht. media.example.com (oder was als blossom.host gesetzt ist) im Reverse-Proxy auf denselben Port zeigen lassen, dann nostrfy restart.
Ein Blob gibt direkt nach dem Upload 404
Die Datei ist per SHA-256 inhaltsadressiert: sie über den exakten Hash aus der Upload-Antwort abrufen (/<sha256> oder /<sha256>.<ext>). Eine Abweichung bedeutet,
dass der Client einen anderen Hash angefordert hat als die gesendeten Bytes.
Suche, Gruppen und Auth
Suche liefert 0 Ergebnisse / unerwartete Ergebnisse
Die nostrfy-Suche trifft ganze Wörter. Beachten, dass:
search = "rust"Events mit dem Wort „rust“ trifft, aber"ru"trifft „rust“ NICHT als Substring.- Nur Wörter im Event-Inhalt werden durchsucht.
- Falls
search_index = false, funktioniert die Suche trotzdem, ist aber langsamer. - Falls NIP-50 deaktiviert ist (
disabled_nips = [50]), wirdsearchignoriert (es wird ein NOTICE gesendet).
Gruppen-Metadaten (39000-39005) werden nicht erzeugt
Ursache: relay.private_key ist nicht gesetzt. Gruppen-Snapshots werden mit dem eigenen Schlüssel des Relays signiert, ohne ihn wird nichts erzeugt.
Lösung:
nostrfy --config nostrfy.toml genkey
nostrfy --config nostrfy.toml restartrestricted: unknown group weist Gruppen-Events ab
Ursache: Die Gruppe existiert nicht. In NIP-29 können Moderations-Events und Beitrittsanfragen (9021) keine Gruppe adressieren, bevor sie per Kind 9007 erstellt wurde.
Lösung: Zuerst die Gruppe mit einem 9007-Event erstellen.
restricted: you are not an admin of this group
Ursache: Moderation (Mitglieder hinzufügen usw.) erfordert einen Admin (ein Mitglied mit Rolle). Der Ersteller ist Admin.
Lösung: Einen Admin um eine Rolle bitten oder eine eigene Gruppe erstellen.
restricted: this group is closed
Ursache: Die Gruppe ist closed; Beitrittsanfragen ohne Einladungscode werden nicht automatisch genehmigt.
Lösung: Einen Admin um einen Einladungscode (9009) bitten und mit einem code-Tag beitreten.
Versehentlich eine Gruppe verlassen, oder die Gruppe hat keine Admins
Ursache: NIP-29-Austrittsanfragen (Kind 9022) werden für jedes Mitglied honoriert — auch für den letzten Admin der Gruppe, der keine Admins hinterlässt. Ohne Admin kann niemand mehr Moderations-Events (9000/9001/9002/9008) senden.
Lösung: Ein Moderations-Event mit dem eigenen Schlüssel des Relays signieren (relay.private_key,
der Pubkey, der als NIP-11-self annonciert wird). Per NIP-29 dürfen Moderations-Events vom „Relay-Master-Key oder … Gruppen-Admins“ kommen, daher akzeptiert das Relay Gruppenmoderation, die mit seinem eigenen Schlüssel signiert ist, selbst wenn die Gruppe keine Admins hat. Zum Beispiel einen Admin mit kind:9000 wiederherstellen:
{
"kind": 9000,
"pubkey": "<relay self pubkey>",
"tags": [["h", "<group-id>"], ["p", "<member-hex>", "admin"]]
}Mit dem Relay-Schlüssel signieren und veröffentlichen. Alternativ die Gruppe mit Relay-signiertem kind:9008 löschen (ihre gespeicherten Events werden gelöscht) und mit kind:9007 neu erstellen.
Diese Wiederherstellung braucht ein konfiguriertes relay.private_key.
Geschützte Events werden mit auth-required abgewiesen
Ursache: Geschützte NIP-70-Events (mit --Tag) dürfen nur vom authentifizierten Autor auf derselben Verbindung veröffentlicht werden.
Lösung: Vor dem Veröffentlichen NIP-42-Auth im Client aktivieren.
AUTH (NIP-42) gibt false zurück
Häufige Ursachen:
relay.public_urlist nicht gesetzt oder falsch — derrelay-Tag des AUTH-Events passt nicht zur Relay-URL.wss://...setzen und neu starten.- Veraltete Challenge — AUTH wurde auf einer anderen Verbindung gesendet oder eine alte Challenge wiederverwendet.
- Die Client-Uhr geht falsch —
created_atdes AUTH-Events muss innerhalb von ±10 Minuten um jetzt liegen.
NIP-86-Verwaltungs-API gibt 401 unauthorized zurück
Ursache: Fehlende oder falsche Credentials.
Lösung:
management_tokensetzen undAuthorization: Bearer <token>senden.- Oder
admin_pubkeysetzen und ein NIP-98-Auth-Event senden (deru-Tag muss exakt zur Relay-URL passen; einpayload-Tag ist erforderlich). - Falls beides nicht gesetzt ist, ist die Verwaltungs-API ganz deaktiviert.
NIP-98-Auth-Events werden wegen anderem Schema oder Port abgewiesen
Die NIP-98-Spezifikation sagt, der u-Tag muss exakt derselbe wie die absolute Request-URL sein, daher leitet nostrfy die erwartete URL aus relay.public_url ab: ihren Authority-Teil plus das HTTP-Schema, abgebildet aus dem WebSocket-Schema (wss:// → https://, ws:// → http://, nostr+-Präfix entfernt). Ohne public_url erwartet das Relay das plain http://host:port, das es bedient. Ein Tag mit anderem Schema, anderem/weggelassenem Port oder anderem Pfad bzw. Query wird abgewiesen — relay.public_url auf die öffentliche Adresse setzen, die Clients signieren. Jedes Auth-Event ist außerdem einmalig verwendbar: das Wiederholen desselben Authorization-Headers innerhalb seines 60-Sekunden-Gültigkeitsfensters wird abgewiesen.
Datenbank und Festplatte
database map is full: increase database.max_map_size
Ursache: Die LMDB-Memory-Map-Obergrenze (Standard 1 TB virtueller Adressraum; die tatsächliche Plattennutzung wächst mit den Daten) wurde erreicht — die Datenbank ist faktisch voll.
Lösung: database.max_map_size erhöhen und neu starten.
disk is full: refusing to commit N events
Ursache: Weniger als 32 MB freier Plattenplatz. Schreibvorgänge stoppen (zum Schutz der Daten); Lesevorgänge laufen weiter.
Lösung: Plattenplatz freigeben. Schreibvorgänge werden automatisch fortgesetzt, sobald Platz verfügbar ist.
(df -h /path/to/data)
nostrfy check meldet map_size must not exceed max_map_size
Ursache: database.map_size ist größer als max_map_size.
Lösung: map_size auf oder unter max_map_size setzen (die Standards sind in Ordnung).
Datenbankgröße prüfen
curl http://127.0.0.1:8080/relay/stats
# => "db_size_bytes" in BytesDatenbank sichern / umziehen
Alle Daten liegen im Verzeichnis database.path. Das Relay vor dem Kopieren stoppen (das Kopieren einer Live-Datenbank kann sie korrumpieren).
nostrfy --config nostrfy.toml stop
cp -a ./data ./data-backup
# Auch [blossom].local_path sichern, bei lokalem Blossom-Speicher.
nostrfy --config nostrfy.toml startDaemon-Betrieb
nostrfy stats sagt nostrfy is not running (no stats file)
Ursache: Die Stats-Datei existiert nicht — der Daemon läuft nicht oder ist erst vor wenigen Sekunden gestartet.
Lösung: nostrfy start ausführen, ein paar Sekunden warten und erneut versuchen.
Das Protokoll wächst unbegrenzt
Ursache: max_log_size_bytes ist 0 (Rotation deaktiviert).
Lösung: max_log_size_bytes = 52428800 (50 MB) und max_log_files = 5 setzen. Die Rotation ist automatisch.
Änderungen an der Konfiguration wirken nach Reload nicht
Ursache: Sie haben (per SIGHUP) Einstellungen neu geladen, die beim Start fixiert sind: private_key, api_host, metrics_enabled, LiveKit-Einstellungen und die NIP-Aktivierungs-/Deaktivierungslisten.
Lösung: nostrfy restart verwenden. Das Protokoll enthält in diesem Fall eine Warnung „a restart is required“.
Das Relay stirbt von selbst
Ursache: Die Maschine wurde neu gestartet oder dem Relay ging der Speicher aus (OOM).
Lösung:
- Ende des Protokolls prüfen:
tail -50 nostrfy.log. - Prüfen, ob die Maschine neu gestartet wurde:
uptime(eine sehr kurze Uptime bedeutet einen Neustart). - Speicher prüfen:
free -h. - Das Relay erneut starten:
nostrfy start.
systemd kann das Relay auf Port 80 nicht starten
Ein als root laufender systemd-Service kann Port 80 binden. Wenn User= auf einen regulären Benutzer gesetzt ist,
entweder einen höheren Port (z. B. 8080) verwenden oder AmbientCapabilities=CAP_NET_BIND_SERVICE zur Unit hinzufügen.
Immer noch nicht gelöst?
- Protokoll prüfen:
tail -100 nostrfy.log— es nennt meist die direkte Ursache. - Konfiguration erneut validieren:
nostrfy check— zeigt Warnungen und Fehler. - Reproduktionsdetails sammeln: was getan wurde, welcher Client, welcher exakte Fehler.
- Im Projekt-Repository fragen: https://github.com/iqbqioza/nostrfy — beim Erstellen eines Issues Reproduktionsschritte und Protokoll beifügen.