12 KiB
Configuration Management Guide
Comprehensive guide for managing the C Nostr Relay's event-based configuration system.
Table of Contents
- Overview
- Configuration Events
- Parameter Reference
- Configuration Examples
- Security Considerations
- Troubleshooting
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
- Admin keypair: Generated on first startup, used to sign configuration events
- Configuration events: Kind 33334 Nostr events with relay settings in tags
- Real-time processing: New configuration events processed via WebSocket
- 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
dtag: 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:
1to100 - 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:
100to50000 - 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:
1024to1048576(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:
10to10000 - Impact: Prevents events with excessive tags
- Example:
"5000"
max_content_length
- Description: Maximum event content length in bytes
- Default:
"65536"(64KB) - Range:
1to1048576(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:
0to40 - 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:
0to86400(24 hours) - Impact: Allows some flexibility in expiration timing
- Example:
"600"(10 minute grace period)
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:
- Stopping the relay
- Removing the database (loses all events)
- 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.