Conceitos básicos
A configuração é um arquivo TOML, por padrão chamado nostrfy.toml. Crie-o com init:
nostrfy --config nostrfy.toml init
Valide-o (recomendado antes de cada inicialização):
nostrfy --config nostrfy.toml check
Cada comando aceita --config <path> (padrão nostrfy.toml).
Sintaxe geral:
[section]
key = "string"
key = 8080
key = [1, 2]
key = true
Seções de configuração
| Seção | Finalidade |
|---|
[relay] | Identidade, URLs e chaves de ativação de NIP |
[server] | Vinculação de rede, separação de API, métricas |
[rpc] | RPC de gerenciamento NIP-86 (autenticação, limite do corpo) |
[limits] | Todos os limites e proteções contra sobrecarga |
[database] | Armazenamento LMDB, índice de pesquisa, limites de fila |
[daemon] | Arquivos PID, de log e de estatísticas e rotação |
[access] | Listas iniciais de controle de acesso (alteráveis em tempo de execução) |
[blossom] | Servidor de arquivos Blossom (hospedagem de mídia) |
Cada chave é opcional; uma chave ausente usa seu valor padrão.
Seção [relay] — identidade do relay
| Chave | Tipo | Padrão | Descrição |
|---|
name | string | "nostrfy" | Nome do relay exibido aos clientes via NIP-11 |
description | string | "A minimal and stable Nostr relay" | Descrição do relay (NIP-11) |
pubkey | string (64 hex) | "" | Chave pública do administrador (campo pubkey do NIP-11) |
contact | string | "" | URI de contato do administrador (mailto: ou https://) |
icon | string | "" | URL da imagem do ícone do relay |
post_policy | string | "" | URL que aponta para a política de publicação do relay |
private_key | string (64 hex) | "" | Chave secreta própria do relay; necessária para grupos NIP-29 |
public_url | string | "" | URL pública, ex. wss://relay.example.com |
livekit_url | string | "" | URL do servidor LiveKit para salas de áudio/vídeo NIP-29 |
livekit_api_key | string | "" | Chave API do LiveKit |
livekit_api_secret | string | "" | Segredo API do LiveKit (usado para assinar JWTs) |
enabled_nips | array de inteiros | [] | Lista explícita de NIPs permitidos |
disabled_nips | array de inteiros | [] | NIPs a desativar (ignorado quando enabled_nips não está vazio) |
reject_ephemeral | boolean | false | Rejeitar eventos efêmeros NIP-01 (kinds 20000-29999) |
enabled_git | boolean | false | Aceitar eventos git NIP-34 (kinds 1617-1633, 30617/30618) |
require_pow | integer | 0 | Prova de trabalho exigida em bits zero iniciais |
new_pubkey_min_age_secs | integer | 0 | Recusar eventos de pubkeys mais novas que isto (segundos; 0 = desligado) |
max_events_per_min_per_pubkey | integer | 0 | Limite de publicação por pubkey (por minuto; 0 = sem limite) |
max_groups | integer | 1000 | Limite do armazenamento de grupos NIP-29 em memória |
require_auth | boolean | false | Exigir autenticação NIP-42 para REQ/EVENT/COUNT/NEG |
send_auth_challenge | boolean | true | Enviar o desafio AUTH ao conectar |
enabled_nip78_auth | boolean | true | Exigir AUTH NIP-42 antes de aceitar eventos kind 78/30078 |
enabled_command_events | boolean | false | Executar comandos de operador kind:1 criados pela pubkey do admin |
Detalhes das chaves
- private_key — a chave secreta própria do relay, usada para assinar eventos gerados pelo relay: metadados de grupos NIP-29 (39000-39005) e eventos de função/membros NIP-43. Gere com
nostrfy genkey; mantenha-a em segredo. Ela é lida uma vez na inicialização, portanto alterá-la exige reiniciar. - public_url — usada para validar tags com URL dos clientes: AUTH NIP-42, vanish NIP-62 e auth de admin NIP-98. Quando vazia, o relay recorre a
host:port, que nunca corresponde a uma URL real de cliente ao vincular 0.0.0.0 ou 127.0.0.1 (um aviso é registrado). Defina-a sempre. - enabled_nips vs disabled_nips — a lista de permissão vence: quando
enabled_nips não está vazio, apenas seus NIPs são anunciados e disabled_nips é ignorado. Ambos exigem reiniciar. - reject_ephemeral — os kinds 20000-29999 são rejeitados, mas os kinds isentos que os NIPs exigem retransmitir ainda são encaminhados: 22242, 27235, 28934/28935/28936, 24133, 23194/23195, 24242 e 21059. Aplica-se com SIGHUP.
- enabled_git — NIP-34 opcional: aceita os kinds 1617-1633 e 30617/30618 e anuncia NIP-34. Desligado por padrão porque cargas de patch podem ser grandes. Aplica-se com SIGHUP.
Seção [server] — configurações do servidor
| Chave | Tipo | Padrão | Descrição |
|---|
host | string | "127.0.0.1" | Endereço de vinculação; 0.0.0.0 aceita conexões de qualquer lugar |
port | integer | 8080 | Porta (1-65535); a porta 80 exige root |
api_host | string | "" | Nome de host dedicado à API REST |
metrics_enabled | boolean | true | Servir métricas Prometheus em /metrics |
ws_paths | string | "root" | Caminhos do endpoint WebSocket: root, inbox-outbox ou all |
inbox_write_policy | string | "any" | Quem pode escrever em /inbox: "any" ou "relay" (eventos ainda devem ter tag p) |
outbox_write_policy | string | "any" | Quem pode escrever em /outbox: "any" (próprios eventos da pubkey autenticada NIP-42) ou "relay" |
trusted_proxies | array de strings | [] | Endereços/CIDR de proxies reversos cujo X-Forwarded-For é confiável (vazio = não confiar em nenhum proxy) |
Detalhes das chaves
- host —
0.0.0.0 vincula todas as interfaces IPv4; 127.0.0.1 é somente local. - port — 1-65535; a porta 80 exige root. Esta única porta serve o relay WebSocket, o documento NIP-11, a API REST e o RPC NIP-86 juntos.
- api_host — dedica a API REST a um único nome de host para que a API e o relay possam compartilhar uma porta atrás de um proxy reverso. Fixo na inicialização — exige reiniciar.
- ws_paths —
root serve apenas /, inbox-outbox serve apenas /inbox e /outbox, all serve ambos. Fixo na inicialização — exige reiniciar. - trusted_proxies — liste apenas os endereços próprios do proxy (loopback para nginx/Caddy no mesmo host, o intervalo de origem do balanceador na nuvem). Com ele definido, o IP do cliente é derivado da última entrada não confiável de
X-Forwarded-For para os limites por IP, o limite de taxa, blockip e os logs. Nunca adicione um endereço que os clientes possam alcançar diretamente — eles poderiam falsificar o cabeçalho e contornar os limites por IP. Fixo na inicialização — exige reiniciar.
Seção [rpc] — gerenciamento NIP-86
| Chave | Tipo | Padrão | Descrição |
|---|
management_token | string | "" | Token Bearer para as APIs de gerenciamento |
admin_pubkey | string (64 hex) | "" | Pubkey do administrador para auth de gerenciamento NIP-98 |
max_admin_body_bytes | integer | 65536 | Limite do corpo para o RPC de gerenciamento NIP-86 |
O RPC NIP-86 é montado nas rotas públicas POST / do relay — não há porta de gerenciamento separada. management_token e admin_pubkey às vezes aparecem sob [server] em guias antigos; essas grafias são apelidos legados destas chaves [rpc].
Seção [limits] — limites e proteções
Conexões e mensagens
| Chave | Tipo | Padrão | Descrição |
|---|
max_connections | integer | 10000 | Conexões simultâneas máximas |
max_connections_per_ip | integer | 64 | Conexões máximas por IP de origem |
max_ws_message_bytes | integer | 1048576 | Bytes máximos por mensagem/frame WebSocket |
socket_recv_buffer_kb | integer | 64 | Buffer de recepção do kernel por conexão (KiB) |
max_out_queue_bytes | integer | 262144 | Limite da fila de saída por conexão (bytes) |
ws_idle_timeout_secs | integer | 300 | Fechar conexões ociosas após este tempo |
http_read_timeout_secs | integer | 30 | Tempo limite do cabeçalho HTTP (defesa slow-loris) |
max_connections_per_sec_per_ip | integer | 0 | Conexões novas máximas por segundo por IP de origem |
Assinaturas e consultas
| Chave | Tipo | Padrão | Descrição |
|---|
max_filters | integer | 20 | Filtros máximos por REQ |
max_subscriptions | integer | 20 | Assinaturas máximas por conexão |
max_limit | integer | 500 | Teto para o limit do REQ |
max_count | integer | 2000 | Teto para resultados COUNT |
max_sub_id_len | integer | 64 | Comprimento máximo do id de assinatura (caracteres, não bytes) |
max_sub_bytes | integer | 1048576 | Bytes totais de filtros de assinatura por conexão |
max_req_response_bytes | integer | 33554432 (32 MB) | Teto de bytes totais que uma única resposta REQ pode enviar |
Eventos
| Chave | Tipo | Padrão | Descrição |
|---|
max_content_bytes | integer | 65536 | Comprimento máximo do conteúdo do evento em caracteres |
max_tags | integer | 2000 | Tags máximas por evento |
max_tag_value_bytes | integer | 1024 | Bytes máximos por valor de tag |
max_created_at_future_secs | integer | 3600 | Desvio futuro tolerado de created_at |
group_late_publish_secs | integer | 3600 | Atraso tolerado para eventos de admin de grupos NIP-29 (segundos) |
max_neg_items | integer | 100000 | Registros máximos por sincronização de negentropia NIP-77 |
Apelidos legados: limits.require_pow, limits.new_pubkey_min_age_secs e limits.max_indexed_words ainda são aceitos como apelidos de relay.require_pow, relay.new_pubkey_min_age_secs e database.max_indexed_words.
API REST
| Chave | Tipo | Padrão | Descrição |
|---|
max_api_concurrent | integer | 8 | Solicitações /api/v1 simultâneas máximas |
max_api_limit | integer | 5000 | Teto para o parâmetro limit da API |
max_api_offset | integer | 50000 | Teto para o parâmetro offset da API |
max_api_fetch | integer | 55001 | Janela máxima de sobrebusca para consultas com offset — deve cobrir max_api_offset + max_api_limit + 1 (0 = sem limite) |
max_api_search_bytes | integer | 2048 | Bytes máximos do parâmetro search da API |
Distribuição ao vivo
| Chave | Tipo | Padrão | Descrição |
|---|
live_batch_interval_ms | integer | 20 | Frequência de descarga de eventos ao vivo (ms) |
live_batch_size | integer | 32 | Eventos máximos por lote ao vivo |
live_buffer | integer | 65536 | Tamanho da fila de distribuição ao vivo |
Seção [database] — banco de dados
| Chave | Tipo | Padrão | Descrição |
|---|
path | string | "./data" | Diretório do banco de dados (LMDB) |
max_dbs | integer | 32 | Máximo de bancos de dados nomeados LMDB |
max_readers | integer | 128 | Máximo de leitores simultâneos LMDB |
map_size | integer | 1073741824 (1 GB) | Tamanho mínimo do mapa de memória (bytes) |
max_map_size | integer | 1099511627776 (1 TB) | Tamanho máximo do mapa de memória (bytes) |
purge_interval_secs | integer | 300 | Intervalo de purga NIP-40 (segundos) |
search_index | boolean | true | Habilitar o índice de palavras NIP-50 |
reader_threads | integer | 2 | Threads dedicadas de varredura |
max_indexed_words | integer | 32 | Palavras do conteúdo de cada evento indexadas para pesquisa |
meta_index | boolean | true | Gravar o cabeçalho de metadados por evento usado pelo pré-filtro de varredura |
disabled_fsync | boolean | false | Pular a descarga síncrona em disco após cada lote de gravação |
db_buffer_size | integer | 2048 | Buffer WebSocket inicial por conexão (bytes) |
db_request_timeout_secs | integer | 30 | Tempo máximo que uma solicitação ao banco de dados pode aguardar antes de falhar |
max_db_queue_msgs | integer | 4096 | Mensagens pendentes máximas na fila antes de falhar rápido |
max_db_queue_events | integer | 262144 | Eventos máximos em lotes na fila antes de falhar rápido |
max_db_queue_bytes | integer | 268435456 (256 MiB) | Bytes máximos de solicitações ao banco de dados na fila antes de falhar rápido (0 = sem limite de bytes) |
Detalhes das chaves
- map_size — o mínimo do mapa de memória: o mapa é sempre aberto com pelo menos este tamanho.
- max_map_size — o máximo, aberto como reserva virtual esparsa: o disco físico só cresce com os dados realmente gravados. Aumente-o quando vir
database map is full. - search_index = false — a pesquisa continua funcionando (correspondência de palavras inteiras contra o conteúdo) mas as varreduras ficam mais lentas; em um VPS pequeno isso reduz o banco de dados pela metade. Recomendado em instâncias pequenas.
- disabled_fsync — troca durabilidade por taxa de transferência: as gravações são confirmadas no cache de páginas do SO e uma queda de energia pode perder as gravações mais recentes.
Seção [daemon] — daemon
| Chave | Tipo | Padrão | Descrição |
|---|
pid_file | string | "./nostrfy.pid" | Caminho do arquivo PID |
log_file | string | "./nostrfy.log" | Caminho do arquivo de log |
stats_file | string | "./nostrfy.stats.json" | Caminho do arquivo de estatísticas |
stats_interval_secs | integer | 5 | Intervalo de gravação de estatísticas (segundos) |
max_log_size_bytes | integer | 52428800 (50 MB) | Tamanho de rotação do log (0 = sem rotação) |
max_log_files | integer | 5 | Gerações de logs rotacionados a manter |
Os caminhos são resolvidos em relação ao diretório do arquivo de configuração, portanto permanecem válidos depois que o daemon muda seu diretório de trabalho.
Seção [access] — controle de acesso
| Chave | Tipo | Padrão | Descrição |
|---|
restrict_relay | boolean | false | Somente pubkeys na lista de permissão podem publicar |
blocked_kinds | array de inteiros | [] | Kinds a rejeitar |
allowed_kinds | array de inteiros | [] | Lista de kinds permitidos; somente estes kinds são aceitos quando não vazia |
blocked_ips | array de strings | [] | Endereços IP recusados no momento da conexão |
method_grants | tabela: pubkey → array de strings | {} | Concessões de métodos NIP-86 para pubkeys não admin (gerenciadas em tempo de execução com assignmethod) |
As listas de pubkeys permitidas/negadas não são chaves de configuração — elas vivem no banco de dados do relay (LMDB) e são gerenciadas em tempo de execução:
nostrfy relay allow npub1...
nostrfy relay deny npub1...
nostrfy relay list
- restrict_relay = true — somente as pubkeys na lista de permissão podem publicar, enquanto a leitura permanece aberta a todos (qualquer cliente ainda pode assinar e buscar dados).
- Uma pubkey negada é sempre rejeitada ao publicar e nunca é servida ao ler.
- method_grants — concessões de métodos NIP-86 para pubkeys não admin (pubkey → nomes de método, ex. um moderador com
banevent e listbannedevents). Semeadas a partir da configuração na primeira execução, depois gerenciadas em tempo de execução com assignmethod/unassignmethod do NIP-86 (inspecionadas com listmethodassignees). Somente métodos de moderação e leitura podem ser concedidos — o gerenciamento de permissões, funções, convites e identidade do relay permanece somente admin, e uma pubkey banida é recusada mesmo com concessões. Veja a API de gerenciamento.
Seção [blossom] — servidor de arquivos Blossom
| Chave | Tipo | Padrão | Descrição |
|---|
host | string | "" | Nome de host para o servidor Blossom (vazio = desativado) |
storage | string | "local" | Backend: "local" (local_path) ou "s3" (bucket compatível com S3) |
local_path | string | "/var/lib/nostrfy/images" | Raiz de armazenamento local para arquivos de mídia |
max_upload_bytes | integer | 20971520 (20 MB) | Tamanho máximo de arquivo de mídia |
min_free_bytes | integer | 33554432 (32 MB) | Espaço em disco abaixo do qual uploads são recusados |
s3_endpoint | string | "" | Endpoint compatível com S3 (ex. R2) |
s3_region | string | "" | Região S3 (R2 usa "auto") |
s3_bucket | string | "" | Nome do bucket S3 |
s3_access_key | string | "" | Chave de acesso S3 |
s3_secret_key | string | "" | Chave secreta S3 |
restrict_uploads | boolean | false | Somente pubkeys na lista de permissão podem enviar arquivos |
Recarga a quente (SIGHUP)
Editar o arquivo e enviar kill -HUP $(cat nostrfy.pid) recarrega a configuração sem reiniciar. A maioria das configurações tem efeito imediato; algumas são fixas na inicialização:
| Aplica-se com SIGHUP | Exige reiniciar |
|---|
| relay.name, description, pubkey, contact, icon, post_policy, public_url | relay.private_key |
| reject_ephemeral, enabled_git, enabled_nip78_auth | relay.livekit_*, enabled_nips / disabled_nips |
| a maioria de [limits] | api_host, trusted_proxies, metrics_enabled, ws_paths, database.*, tamanhos do daemon, tetos de limite, blossom.* |
[access] não é aplicado por recarga — as listas são semeadas uma vez na inicialização e depois gerenciadas em tempo de execução via NIP-86. O log avisa quando uma configuração que exige reiniciar muda, e algumas configurações capturadas na inicialização não são verificadas pela recarga.
| Erro | Correção |
|---|
| public_url não definido | defina wss://... |
| host deixado em 127.0.0.1 | clientes externos não conseguem conectar |
| private_key não definido com NIP-29 | execute nostrfy genkey + reinicie |
| restrict_relay true com allowlist vazia | todos bloqueados |
| alterar chaves que só exigem reiniciar e só fazer SIGHUP | use nostrfy restart |