Files
c-relay/docs/configuration_guide.md

13 KiB

Configuration Management Guide

Comprehensive guide for managing the C Nostr Relay's event-based configuration system.

Table of Contents

Overview

The C Nostr Relay uses a revolutionary event-based configuration system where all settings are stored as kind 33334 Nostr events in the database. This provides several advantages:

Benefits

  • Real-time updates: Configuration changes applied instantly without restart
  • Cryptographic security: All changes must be cryptographically signed by admin
  • Audit trail: Complete history of all configuration changes
  • Version control: Each configuration change is timestamped and signed
  • Zero files: No configuration files to manage, backup, or version control

How It Works

  1. Admin keypair: Generated on first startup, used to sign configuration events
  2. Configuration events: Kind 33334 Nostr events with relay settings in tags
  3. Real-time processing: New configuration events processed via WebSocket
  4. Immediate application: Changes applied to running system without restart

Configuration Events

Event Structure

Configuration events follow the standard Nostr event format with kind 33334:

{
  "id": "event_id_computed_from_content",
  "kind": 33334,
  "pubkey": "admin_public_key_hex",
  "created_at": 1699123456,
  "content": "C Nostr Relay Configuration",
  "tags": [
    ["d", "relay_public_key_hex"],
    ["relay_description", "My Nostr Relay"],
    ["max_subscriptions_per_client", "25"],
    ["pow_min_difficulty", "16"]
  ],
  "sig": "signature_computed_with_admin_private_key"
}

Required Tags

  • d tag: Must contain the relay's public key (identifies which relay this config is for)

Event Properties

  • Kind: Must be exactly 33334
  • Content: Should be descriptive (e.g., "C Nostr Relay Configuration")
  • Pubkey: Must be the admin public key generated at first startup
  • Signature: Must be valid signature from admin private key

Parameter Reference

Basic Relay Information

relay_description

  • Description: Human-readable relay description (shown in NIP-11)
  • Default: "C Nostr Relay"
  • Format: String, max 512 characters
  • Example: "My awesome Nostr relay for the community"

relay_contact

  • Description: Admin contact information (email, npub, etc.)
  • Default: "" (empty)
  • Format: String, max 256 characters
  • Example: "admin@example.com" or "npub1..."

relay_software

  • Description: Software identifier for NIP-11
  • Default: "c-relay"
  • Format: String, max 64 characters
  • Example: "c-relay v1.0.0"

relay_version

  • Description: Software version string
  • Default: Auto-detected from build
  • Format: Semantic version string
  • Example: "1.0.0"

Client Connection Limits

max_subscriptions_per_client

  • Description: Maximum subscriptions allowed per WebSocket connection
  • Default: "25"
  • Range: 1 to 100
  • Impact: Prevents individual clients from overwhelming the relay
  • Example: "50" (allows up to 50 subscriptions per client)

max_total_subscriptions

  • Description: Maximum total subscriptions across all clients
  • Default: "5000"
  • Range: 100 to 50000
  • Impact: Global limit to protect server resources
  • Example: "10000" (allows up to 10,000 total subscriptions)

Message and Event Limits

max_message_length

  • Description: Maximum WebSocket message size in bytes
  • Default: "65536" (64KB)
  • Range: 1024 to 1048576 (1MB)
  • Impact: Prevents large messages from consuming resources
  • Example: "131072" (128KB)

max_event_tags

  • Description: Maximum number of tags allowed per event
  • Default: "2000"
  • Range: 10 to 10000
  • Impact: Prevents events with excessive tags
  • Example: "5000"

max_content_length

  • Description: Maximum event content length in bytes
  • Default: "65536" (64KB)
  • Range: 1 to 1048576 (1MB)
  • Impact: Limits event content size
  • Example: "131072" (128KB for longer content)

Proof of Work (NIP-13)

pow_min_difficulty

  • Description: Minimum proof-of-work difficulty required for events
  • Default: "0" (no PoW required)
  • Range: 0 to 40
  • Impact: Higher values require more computational work from clients
  • Example: "20" (requires significant PoW)

pow_mode

  • Description: How proof-of-work is handled
  • Default: "optional"
  • Values:
    • "disabled": PoW completely ignored
    • "optional": PoW verified if present but not required
    • "required": All events must meet minimum difficulty
  • Example: "required" (enforce PoW for all events)

Event Expiration (NIP-40)

nip40_expiration_enabled

  • Description: Enable NIP-40 expiration timestamp support
  • Default: "true"
  • Values: "true" or "false"
  • Impact: When enabled, processes expiration tags and removes expired events
  • Example: "false" (disable expiration processing)

nip40_expiration_strict

  • Description: Strict mode for expiration handling
  • Default: "false"
  • Values: "true" or "false"
  • Impact: In strict mode, expired events are immediately rejected
  • Example: "true" (reject expired events immediately)

nip40_expiration_filter

  • Description: Filter expired events from query results
  • Default: "true"
  • Values: "true" or "false"
  • Impact: When enabled, expired events are filtered from responses
  • Example: "false" (include expired events in results)

nip40_expiration_grace_period

  • Description: Grace period in seconds before expiration takes effect
  • Default: "300" (5 minutes)
  • Range: 0 to 86400 (24 hours)
  • Impact: Allows some flexibility in expiration timing
  • Example: "600" (10 minute grace period)

NIP-59 Gift Wrap Timestamp Configuration

nip59_timestamp_max_delay_sec

  • Description: Controls timestamp randomization for NIP-59 gift wraps
  • Default: "0" (no randomization)
  • Range: 0 to 604800 (7 days)
  • Impact: Affects compatibility with other Nostr clients for direct messaging
  • Values:
    • "0": No randomization (maximum compatibility)
    • "1-604800": Random timestamp between now and N seconds ago
  • Example: "172800" (2 days randomization for privacy)

Configuration Examples

Basic Relay Setup

{
  "kind": 33334,
  "content": "Basic Relay Configuration",
  "tags": [
    ["d", "relay_pubkey_here"],
    ["relay_description", "Community Nostr Relay"],
    ["relay_contact", "admin@community-relay.com"],
    ["max_subscriptions_per_client", "30"],
    ["max_total_subscriptions", "8000"]
  ]
}

High-Security Relay

{
  "kind": 33334,
  "content": "High Security Configuration",
  "tags": [
    ["d", "relay_pubkey_here"],
    ["relay_description", "High-Security Nostr Relay"],
    ["pow_min_difficulty", "24"],
    ["pow_mode", "required"],
    ["max_subscriptions_per_client", "10"],
    ["max_total_subscriptions", "1000"],
    ["max_message_length", "32768"],
    ["nip40_expiration_strict", "true"]
  ]
}

Public Community Relay

{
  "kind": 33334,
  "content": "Public Community Relay Configuration",
  "tags": [
    ["d", "relay_pubkey_here"],
    ["relay_description", "Open Community Relay - Welcome Everyone!"],
    ["relay_contact", "community@relay.example"],
    ["max_subscriptions_per_client", "50"],
    ["max_total_subscriptions", "25000"],
    ["max_content_length", "131072"],
    ["pow_mode", "optional"],
    ["pow_min_difficulty", "8"],
    ["nip40_expiration_enabled", "true"],
    ["nip40_expiration_grace_period", "900"]
  ]
}

Private/Corporate Relay

{
  "kind": 33334,
  "content": "Corporate Internal Relay",
  "tags": [
    ["d", "relay_pubkey_here"],
    ["relay_description", "Corporate Internal Communications"],
    ["relay_contact", "it-admin@company.com"],
    ["max_subscriptions_per_client", "20"],
    ["max_total_subscriptions", "2000"],
    ["max_message_length", "262144"],
    ["nip40_expiration_enabled", "false"],
    ["pow_mode", "disabled"]
  ]
}

Security Considerations

Admin Key Management

Secure Storage

# Store admin private key securely
echo "ADMIN_PRIVKEY=your_admin_private_key_here" > .env
chmod 600 .env

# Or use a password manager
# Never store in version control
echo ".env" >> .gitignore

Key Rotation

Currently, admin key rotation requires:

  1. Stopping the relay
  2. Removing the database (loses all events)
  3. Restarting (generates new keys)

Future versions will support admin key rotation while preserving events.

Event Validation

The relay performs comprehensive validation on configuration events:

Cryptographic Validation

  • Signature verification: Uses nostr_verify_event_signature()
  • Event structure: Validates JSON structure with nostr_validate_event_structure()
  • Admin authorization: Ensures events are signed by the authorized admin pubkey

Content Validation

  • Parameter bounds checking: Validates numeric ranges
  • String length limits: Enforces maximum lengths
  • Enum validation: Validates allowed values for mode parameters

Network Security

Access Control

# Limit access with firewall
sudo ufw allow from 192.168.1.0/24 to any port 8888

# Or use specific IPs
sudo ufw allow from 203.0.113.10 to any port 8888

TLS/SSL Termination

# nginx configuration for HTTPS termination
server {
    listen 443 ssl;
    server_name relay.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://127.0.0.1:8888;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
    }
}

Troubleshooting

Configuration Not Applied

Check Event Signature

// Verify event signature with nostrtool or similar
const event = { /* your configuration event */ };
const isValid = nostrTools.verifySignature(event);

Verify Admin Pubkey

# Check current admin pubkey in database
sqlite3 relay.nrdb "SELECT DISTINCT pubkey FROM events WHERE kind = 33334 ORDER BY created_at DESC LIMIT 1;"

# Compare with expected admin pubkey from first startup
grep "Admin Public Key" relay.log

Check Event Structure

# View the exact event stored in database
sqlite3 relay.nrdb "SELECT json_pretty(json_object(
  'kind', kind,
  'pubkey', pubkey, 
  'created_at', created_at,
  'content', content,
  'tags', json(tags),
  'sig', sig
)) FROM events WHERE kind = 33334 ORDER BY created_at DESC LIMIT 1;"

Configuration Validation Errors

Invalid Parameter Values

# Check relay logs for validation errors
journalctl -u c-relay | grep "Configuration.*invalid\|Invalid.*configuration"

# Common issues:
# - Numeric values outside valid ranges
# - Invalid enum values (e.g., pow_mode)
# - String values exceeding length limits

Missing Required Tags

# Ensure 'd' tag is present with relay pubkey
sqlite3 relay.nrdb "SELECT tags FROM events WHERE kind = 33334 ORDER BY created_at DESC LIMIT 1;" | grep '"d"'

Performance Impact

Monitor Configuration Changes

# Track configuration update frequency
sqlite3 relay.nrdb "SELECT datetime(created_at, 'unixepoch') as date, 
  COUNT(*) as config_updates 
FROM events WHERE kind = 33334 
GROUP BY date(created_at, 'unixepoch') 
ORDER BY date DESC;"

Resource Usage After Changes

# Monitor system resources after configuration updates
top -p $(pgrep c_relay)

# Check for memory leaks
ps aux | grep c_relay | awk '{print $6}' # RSS memory

Emergency Recovery

Reset to Default Configuration

If configuration becomes corrupted or causes issues:

# Create emergency configuration event
nostrtool event \
  --kind 33334 \
  --content "Emergency Reset Configuration" \
  --tag d YOUR_RELAY_PUBKEY \
  --tag max_subscriptions_per_client 25 \
  --tag max_total_subscriptions 5000 \
  --tag pow_mode optional \
  --tag pow_min_difficulty 0 \
  --private-key YOUR_ADMIN_PRIVKEY \
  | nostrtool send ws://localhost:8888

Database Recovery

# If database is corrupted, backup and recreate
cp relay.nrdb relay.nrdb.backup
rm relay.nrdb*
./build/c_relay_x86  # Creates fresh database with new keys

This configuration guide covers all aspects of managing the C Nostr Relay's event-based configuration system. The system provides unprecedented flexibility and security for Nostr relay administration while maintaining simplicity and real-time responsiveness.