Solução de problemas
Os erros mais prováveis — portas, permissões, TLS, NIP ausentes, publicação e tempos de espera — com correções passo a passo.
Três coisas para verificar primeiro:
nostrfy checkvalida sua configuração (a maioria dos erros são erros de configuração).tail -f nostrfy.logmostra o log — a causa está quase sempre lá.nostrfy restartreinicia o daemon de forma limpa.
Não é possível iniciar
error: cannot bind to 0.0.0.0:80: Permission denied
Causa: A porta 80 só pode ser vinculada pelo root.
Correção: Execute com sudo ou mude a porta para algo como 8080.
# Troque port = 8080 no arquivo de configuração, depois:
nostrfy --config nostrfy.toml starterror: cannot bind to ...: Address already in use
Causa: Outro processo (um nostrfy antigo ou um servidor diferente) já está usando a porta.
Correção:
ss -tlnp | grep :8080# Se o nostrfy já está rodando, reinicie
nostrfy --config nostrfy.toml restartalready running (pid 1234); use 'nostrfy stop' or 'nostrfy restart'
Causa: o nostrfy já está em execução; start se recusa a iniciar uma
segunda instância.
Correção: Use nostrfy restart ou apenas use a instância em execução.
nostrfy stop trava / did not stop in time
Causa: O daemon está travado ou não está respondendo.
Correção:
ps aux | grep nostrfy
kill -9 <PID>
# Remova o arquivo pid obsoleto, se existir
rm -f nostrfy.piderror: invalid nostrfy.toml: TOML parse error
Causa: O arquivo de configuração não é um TOML válido. Erros comuns: esquecer aspas em uma string ou escrever a mesma chave duas vezes.
Correção: A mensagem de erro inclui um número de linha. Verifique e corrija essa linha.
# Exemplos corretos
name = "my relay" # strings usam aspas duplas
port = 8080 # números vão sem aspas
enabled_nips = [1, 50] # listas ficam entre [ ]error: cannot read nostrfy.toml: No such file or directory
Causa: O arquivo de configuração não existe.
Correção:
nostrfy --config nostrfy.toml initerror: relay.private_key is not a valid secp256k1 secret key
Causa: relay.private_key não é uma chave hexadecimal válida de 64
caracteres.
Correção: Execute nostrfy genkey para gerar uma chave correta (ou defina private_key = "").
Muitos avisos no log ao iniciar
Linhas de log [WARN] indicam problemas de configuração. As principais:
| Aviso | Significado e correção |
|---|---|
relay.public_url is empty and server.host is "0.0.0.0"... | public_url não está definido — autenticação NIP-42, vanish NIP-62 e autenticação
admin NIP-98 não funcionarão. Defina wss://your-public-url. |
relay.private_key is empty while NIP-29 is enabled... | Grupos precisam de uma chave secreta. Execute nostrfy genkey. |
unknown config key [relay].software is ignored | Uma chave legada não utilizada (ou um erro de digitação) na configuração. Verifique o nome da chave. |
unknown config section [serve] is ignored | Um erro de digitação no nome de uma seção (por ex. [serve] em vez de [server]).
Corrija. |
relay.require_auth is true but relay.send_auth_challenge is false... | Esta combinação bloqueia todo mundo. Altere uma das duas. |
relay.require_pow = 64 ... practically unmineable | O requisito de PoW é tão alto que ninguém consegue publicar. Reduza require_pow. |
Não conecta ou se comporta de forma estranha
O cliente recebe connection refused
Causa: O relay não está em execução ou um firewall está bloqueando a porta.
Correção:
curl http://127.0.0.1:8080/health
# De fora (usando o IP/porta do servidor)
curl http://YOUR_SERVER_IP:8080/health
# Verifique o firewall (exemplo: ufw)
sudo ufw status
# Abra a porta se preciso
sudo ufw allow 8080Clientes externos não conectam, os locais conectam
Causa: server.host ainda é 127.0.0.1 (o padrão),
que aceita apenas conexões locais.
Correção: Defina host = "0.0.0.0" na configuração e reinicie.
Não é possível conectar através de um túnel Cloudflare
Ao usar o Cloudflare Tunnel:
- O relay executa HTTP simples; a Cloudflare termina o TLS, então os clientes usam
wss://. Definapublic_url = "wss://..."no relay (isso faz a autenticação NIP-42 funcionar). - A Cloudflare adiciona um cabeçalho
X-Forwarded-Proto. O nostrfy trata valoresws/wss/http/httpsda mesma forma, então normalmente nenhuma configuração extra é necessária.
error: message too large e a conexão é fechada
Causa: Uma única mensagem excede max_ws_message_bytes (padrão 1 MB).
Correção: Aumente limits.max_ws_message_bytes se precisar de eventos maiores — mas
verifique também os limites do próprio cliente.
Erros too many subscriptions / too many filters
Causa: Os limites por conexão foram atingidos (assinaturas padrão 20, filtros padrão 20).
Correção: Aumente limits.max_subscriptions / limits.max_filters (e verifique as configurações do cliente).
Novas conexões são recusadas sob carga
Causa: max_connections (padrão 10000) foi atingido, o limite por IP
(max_connections_per_ip, padrão 64) foi acionado, ou o limite de taxa de conexão por segundo
(max_connections_per_sec_per_ip) recusou o pico. Os limites se aplicam a todas as conexões —
WebSocket e HTTP simples igualmente.
Correção: Revise e ajuste as configurações. max_connections_per_ip = 0 desativa
o limite por IP; max_connections_per_sec_per_ip = 0 desativa o limite de taxa. Essas três
configurações exigem reinicialização.
Conexões caem depois de um tempo
Causa: Se ws_idle_timeout_secs estiver definido, conexões ociosas são fechadas.
Clientes saudáveis respondem ao PING do relay com um PONG e permanecem conectados; apenas pares mortos são removidos.
Correção: Isso é intencional — o padrão é 300 segundos. Defina ws_idle_timeout_secs = 0 para desativar completamente.
Uma assinatura termina com CLOSED ... response too large
Causa: Os eventos armazenados de um REQ excederam max_req_response_bytes (padrão 32 MiB). Só acontece com eventos muito grandes ou filtros muito amplos.
Correção: Restrinja o filtro (since/until mais apertados, um limit menor) ou aumente max_req_response_bytes (0 desativa o orçamento).
Um NIP está ausente da lista NIP-11 supported_nips
Causa: A lista anunciada é dinâmica — um NIP fica oculto quando todos os kinds que ele
define são rejeitados: todos estão em blocked_kinds, nenhum deles está em allowed_kinds, ou são kinds efêmeros rejeitados por reject_ephemeral.
NIP-29/43/66 exigem adicionalmente relay.private_key e NIP-86 exige rpc.management_token ou rpc.admin_pubkey.
Correção: Verifique as listas de acesso ativas — NIP-86 listallowedkinds mostra a
lista de kinds permitidos, e GET / mostra o supported_nips efetivo imediatamente.
Remova o kind bloqueador ou a configuração reject_ephemeral.
Erros ao publicar
Quando a publicação falha, o 4º elemento da mensagem OK explica o motivo. Os comuns:
| Erro | Significado e correção |
|---|---|
invalid: signature verification failed | A assinatura do evento é inválida (possivelmente uma chave de cliente quebrada). |
invalid: content too large | O conteúdo excede max_content_bytes (padrão 64K caracteres). Encurte-o ou
aumente o limite. |
invalid: too many tags | Mais tags do que max_tags (padrão 2000). |
invalid: event creation date is in the future | Timestamp muito no futuro (além de max_created_at_future_secs). |
mute: event contains secret key material | O conteúdo ou as tags contêm uma string com aparência de nsec. Nunca publique chaves secretas. Remova a string e o evento será aceito. |
duplicate: event already stored | O mesmo evento já está armazenado (normal). |
blocked: pubkey not allowed | A pubkey está banida (banpubkey) ou fora da lista de permissão. |
blocked: kind not allowed | Este kind não é permitido. |
rate-limited: too many events | A pubkey excedeu max_events_per_min_per_pubkey (janela deslizante de 60
segundos). Aguarde um minuto e tente novamente, ou aumente/desative o limite. |
blocked: event has been banned | O id do evento está banido. |
blocked: event has been deleted | Republicação de um evento excluído. |
auth-required: ... | Autenticação é necessária (quando relay.require_auth está ativado). |
restricted: your account is too new | A conta foi criada dentro de new_pubkey_min_age_secs. Aguarde e tente novamente. |
restricted: unknown group | O grupo não existe (crie-o primeiro). |
restricted: this group is closed | O grupo é closed; solicitações de participação sem código de convite não são atendidas. |
Servidor de arquivos Blossom
Upload falha com 401
O evento de autorização de upload (kind 24242) foi rejeitado. Verifique se:
- a tag
expirationdo token está presente e definida como um timestamp unix no futuro, - para upload/media/delete o token carrega uma tag
xcom o sha256 do blob, - a tag
server(quando presente) nomeia exatamente oblossom.hostconfigurado (somente hostname, sem esquema/caminho), - o token foi assinado nos últimos 10 minutos (uma janela de frescor contra replay),
- e a chave de assinatura é do próprio uploader.
Upload falha com 403
blossom.restrict_uploads = true está definido e a pubkey não está na lista de permissão — adicione-a
com nostrfy blossom allow npub1... (o daemon recarrega automaticamente). Se a lista parecer
errada, nostrfy blossom list a mostra.
Upload falha com 409
O cliente enviou um cabeçalho X-SHA-256 que não corresponde ao corpo real da requisição (o
hash declarado foi calculado sobre bytes diferentes — por ex. o arquivo mudou entre o cálculo do hash e o envio).
Os clientes podem omitir o cabeçalho completamente.
GET / no host de mídia serve o documento NIP-11
A requisição não chegou ao relay com o cabeçalho Blossom Host. Aponte media.example.com (ou qualquer que seja o blossom.host definido) para a mesma porta no proxy reverso, então nostrfy restart.
Um blob retorna 404 logo após o upload
O arquivo é endereçado pelo conteúdo via seu SHA-256: busque-o pelo hash exato retornado na resposta
do upload (/<sha256> ou /<sha256>.<ext>). Uma incompatibilidade significa
que o cliente solicitou um hash diferente dos bytes que enviou.
Busca, grupos e autenticação
A busca retorna 0 resultados / resultados inesperados
A busca do nostrfy corresponde a palavras inteiras. Observe que:
search = "rust"corresponde a eventos contendo a palavra "rust", mas"ru"NÃO corresponde a "rust" como substring.- Apenas palavras no conteúdo do evento são pesquisadas.
- Se
search_index = false, a busca ainda funciona, mas é mais lenta. - Se o NIP-50 estiver desativado (
disabled_nips = [50]),searché ignorado (um NOTICE é enviado).
Metadados de grupo (39000-39005) não são gerados
Causa: relay.private_key não está definido. Os snapshots de grupo são assinados pela
própria chave do relay, então sem ela nada é gerado.
Correção:
nostrfy --config nostrfy.toml genkey
nostrfy --config nostrfy.toml restartrestricted: unknown group rejeita eventos de grupo
Causa: O grupo não existe. No NIP-29, eventos de moderação e solicitações de participação (9021) não podem visar um grupo antes que ele seja criado (kind 9007).
Correção: Crie o grupo primeiro com um evento 9007.
restricted: you are not an admin of this group
Causa: A moderação (adicionar membros, etc.) exige um admin (um membro com uma função). O criador é um admin.
Correção: Peça a um admin para conceder uma função a você ou crie seu próprio grupo.
restricted: this group is closed
Causa: O grupo é closed; solicitações de participação sem código de convite não
são aprovadas automaticamente.
Correção: Peça a um admin um código de convite (9009) e participe com uma tag code.
Saiu acidentalmente de um grupo, ou o grupo não tem admins
Causa: Solicitações de saída NIP-29 (kind 9022) são atendidas para qualquer membro — incluindo o último admin do grupo, que não deixa admins para trás. Sem admin, ninguém pode enviar eventos de moderação (9000/9001/9002/9008) mais.
Correção: Assine um evento de moderação com a própria chave do relay (relay.private_key,
a pubkey anunciada como self do NIP-11). Pelo NIP-29, eventos de moderação podem vir da "chave
mestra do relay ou ... dos admins do grupo", então o relay aceita moderação de grupo assinada pela própria chave mesmo
quando o grupo não tem admins. Por exemplo, restaure um admin com um kind:9000:
{
"kind": 9000,
"pubkey": "<relay self pubkey>",
"tags": [["h", "<group-id>"], ["p", "<member-hex>", "admin"]]
}Assine e publique com a chave do relay. Alternativamente, exclua o grupo com um kind:9008 assinado pelo relay (seus eventos armazenados são purgados) e recrie-o com kind:9007.
Esta recuperação precisa que relay.private_key esteja configurado.
Eventos protegidos são rejeitados com auth-required
Causa: Eventos protegidos NIP-70 (com tag -) só podem ser publicados pelo
autor autenticado na mesma conexão.
Correção: Ative a autenticação NIP-42 no cliente antes de publicar.
AUTH (NIP-42) retorna false
Causas comuns:
relay.public_urlnão definido ou errado — a tagrelaydo evento AUTH não corresponde à URL do relay. Definawss://...e reinicie.- Challenge expirado — você enviou AUTH em uma conexão diferente ou reutilizou um challenge antigo.
- O relógio do cliente está errado — o
created_atdo evento AUTH deve estar dentro de ±10 minutos de agora.
API de gerenciamento NIP-86 retorna 401 unauthorized
Causa: Credenciais ausentes ou erradas.
Correção:
- Defina
management_tokene envieAuthorization: Bearer <token>. - Ou defina
admin_pubkeye envie um evento de autenticação NIP-98 (a tagudeve corresponder exatamente à URL do relay; uma tagpayloadé necessária). - Se nenhum estiver definido, a API de gerenciamento está totalmente desativada.
Eventos de autenticação NIP-98 são rejeitados por esquema ou porta diferentes
A especificação NIP-98 diz que a tag u deve ser exatamente igual à URL absoluta da
requisição, então o nostrfy deriva a URL esperada de relay.public_url: sua autoridade mais o
esquema HTTP mapeado do esquema WebSocket (wss:// → https://, ws:// → http://, nostr+ removido). Sem public_url o relay espera o simples http://host:port que serve. Uma tag com
outro esquema, uma porta diferente/omitida, ou um caminho ou query diferente é rejeitada — defina relay.public_url para o endereço público que os clientes assinam. Cada evento de autenticação também é de uso único: repetir o mesmo cabeçalho Authorization dentro de sua janela de validade de 60
segundos é recusado.
Banco de dados e disco
database map is full: increase database.max_map_size
Causa: O teto do memory-map do LMDB (padrão 1 TB de espaço de endereço virtual; o uso real de disco cresce com os dados) foi atingido — efetivamente, o banco de dados está cheio.
Correção: Aumente database.max_map_size e reinicie.
disk is full: refusing to commit N events
Causa: Menos de 32 MB de espaço livre em disco. As escritas param (para proteger os dados); as leituras continuam.
Correção: Libere espaço em disco. As escritas são retomadas automaticamente quando houver espaço disponível.
(df -h /path/to/data)
nostrfy check relata map_size must not exceed max_map_size
Causa: database.map_size é maior que max_map_size.
Correção: Defina map_size igual ou abaixo de max_map_size (os padrões
estão bons).
Verificando o tamanho do banco de dados
curl http://127.0.0.1:8080/relay/stats
# => "db_size_bytes" em bytesFazer backup / mover o banco de dados
Todos os dados ficam no diretório database.path. Pare o relay antes de copiar (copiar um banco de dados ativo pode corrompê-lo).
nostrfy --config nostrfy.toml stop
cp -a ./data ./data-backup
# Faça também backup de [blossom].local_path ao usar Blossom local.
nostrfy --config nostrfy.toml startOperação do daemon
nostrfy stats diz nostrfy is not running (no stats file)
Causa: O arquivo de stats não existe — o daemon não está em execução ou iniciou há menos de alguns segundos.
Correção: Execute nostrfy start, aguarde alguns segundos e tente novamente.
O log cresce sem parar
Causa: max_log_size_bytes é 0 (rotação desativada).
Correção: Defina max_log_size_bytes = 52428800 (50 MB) e max_log_files = 5. A rotação é automática.
Mudanças na configuração não têm efeito após recarregar
Causa: Você recarregou (SIGHUP) configurações que são fixas na inicialização: private_key, api_host, metrics_enabled, configurações LiveKit e
as listas de ativação/desativação de NIPs.
Correção: Use nostrfy restart. O log contém um aviso "a restart is required"
neste caso.
O relay continua morrendo sozinho
Causa: A máquina reiniciou ou o relay ficou sem memória (OOM).
Correção:
- Verifique o final do log:
tail -50 nostrfy.log. - Verifique se a máquina reiniciou:
uptime(um uptime muito curto significa reinicialização). - Verifique a memória:
free -h. - Inicie o relay novamente:
nostrfy start.
systemd não consegue iniciar o relay na porta 80
Um serviço systemd executando como root pode vincular a porta 80. Se você definiu User= para um usuário comum,
use uma porta mais alta (por ex. 8080) ou adicione AmbientCapabilities=CAP_NET_BIND_SERVICE à unit.
Ainda não resolveu?
- Verifique o log:
tail -100 nostrfy.log— geralmente indica a causa direta. - Revalide a configuração:
nostrfy check— mostra avisos e erros. - Reúna detalhes de reprodução: o que você estava fazendo, qual cliente, qual erro exato.
- Pergunte no repositório do projeto: https://github.com/iqbqioza/nostrfy — ao abrir uma issue, inclua as etapas de reprodução e o log.