15 KiB
C Nostr Relay - User Guide
Complete guide for deploying, configuring, and managing the C Nostr Relay with event-based configuration system.
Table of Contents
- Quick Start
- Installation
- Web Admin Interface
- Configuration Management
- Administration
- Monitoring
- Troubleshooting
- Advanced Usage
Quick Start
1. Build and Start
# Clone and build
git clone <repository-url>
cd c-relay
git submodule update --init --recursive
make
# Start relay (zero configuration needed)
./build/c_relay_x86
2. First Startup - Save Keys
The relay will display admin keys on first startup:
=================================================================
IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!
=================================================================
Admin Private Key: a018ecc259ff296ef7aaca6cdccbc52cf28104ac7a1f14c27b0b8232e5025ddc
Admin Public Key: 68394d08ab87f936a42ff2deb15a84fbdfbe0996ee0eb20cda064aae673285d1
=================================================================
⚠️ CRITICAL: Save the admin private key - it's needed for configuration updates and only shown once!
3. Connect Clients
Your relay is now available at:
- WebSocket:
ws://localhost:8888 - NIP-11 Info:
http://localhost:8888(withAccept: application/nostr+jsonheader) - Web Admin Interface:
http://localhost:8888/api/(serves embedded admin interface)
Installation
System Requirements
- Operating System: Linux, macOS, or Windows (WSL)
- RAM: Minimum 512MB, recommended 2GB+
- Disk: 100MB for binary + database storage (grows with events)
- Network: Port 8888 (configurable via events)
Dependencies
Install required libraries:
Ubuntu/Debian:
sudo apt update
sudo apt install build-essential git sqlite3 libsqlite3-dev libwebsockets-dev libssl-dev libsecp256k1-dev libcurl4-openssl-dev zlib1g-dev
CentOS/RHEL:
sudo yum install gcc git sqlite-devel libwebsockets-devel openssl-devel libsecp256k1-devel libcurl-devel zlib-devel
macOS (Homebrew):
brew install git sqlite libwebsockets openssl libsecp256k1 curl zlib
Building from Source
# Clone repository
git clone <repository-url>
cd c-relay
# Initialize submodules
git submodule update --init --recursive
# Build
make clean && make
# Verify build
ls -la build/c_relay_x86
Production Deployment
SystemD Service (Recommended)
# Install as system service
sudo systemd/install-service.sh
# Start service
sudo systemctl start c-relay
# Enable auto-start
sudo systemctl enable c-relay
# Check status
sudo systemctl status c-relay
Manual Deployment
# Create dedicated user
sudo useradd --system --home-dir /opt/c-relay --shell /bin/false c-relay
# Install binary
sudo mkdir -p /opt/c-relay
sudo cp build/c_relay_x86 /opt/c-relay/
sudo chown -R c-relay:c-relay /opt/c-relay
# Run as service user
sudo -u c-relay /opt/c-relay/c_relay_x86
Configuration Management
Event-Based Configuration System
Unlike traditional relays that use config files, this relay stores all configuration as kind 33334 Nostr events in the database. This provides:
- Real-time updates: Changes applied instantly without restart
- Cryptographic security: All config changes must be signed by admin
- Audit trail: Complete history of configuration changes
- No file management: No config files to manage or version control
First-Time Configuration
On first startup, the relay:
- Generates keypairs: Creates cryptographically secure admin and relay keys
- Creates database:
<relay_pubkey>.nrdbfile with optimized schema - Stores default config: Creates initial kind 33334 event with sensible defaults
- Displays admin key: Shows admin private key once for you to save
Updating Configuration
To change relay configuration, create and send a signed kind 33334 event:
Using nostrtool (recommended)
# Install nostrtool
npm install -g nostrtool
# Update relay description
nostrtool event \
--kind 33334 \
--content "C Nostr Relay Configuration" \
--tag d <relay_pubkey> \
--tag relay_description "My Production Relay" \
--tag max_subscriptions_per_client 50 \
--private-key <admin_private_key> \
| nostrtool send ws://localhost:8888
Manual Event Creation
{
"kind": 33334,
"content": "C Nostr Relay Configuration",
"tags": [
["d", "<relay_pubkey>"],
["relay_description", "My Production Relay"],
["max_subscriptions_per_client", "50"],
["pow_min_difficulty", "20"]
],
"created_at": 1699123456,
"pubkey": "<admin_pubkey>",
"id": "<computed_event_id>",
"sig": "<signature>"
}
Send this to your relay via WebSocket, and changes are applied immediately.
Configuration Parameters
Basic Settings
| Parameter | Description | Default | Example |
|---|---|---|---|
relay_description |
Relay description for NIP-11 | "C Nostr Relay" | "My awesome relay" |
relay_contact |
Admin contact information | "" | "admin@example.com" |
relay_software |
Software identifier | "c-relay" | "c-relay v1.0" |
Client Limits
| Parameter | Description | Default | Range |
|---|---|---|---|
max_subscriptions_per_client |
Max subscriptions per client | "25" | 1-100 |
max_total_subscriptions |
Total relay subscription limit | "5000" | 100-50000 |
max_message_length |
Maximum message size (bytes) | "65536" | 1024-1048576 |
max_event_tags |
Maximum tags per event | "2000" | 10-10000 |
max_content_length |
Maximum event content length | "65536" | 1-1048576 |
Proof of Work (NIP-13)
| Parameter | Description | Default | Options |
|---|---|---|---|
pow_min_difficulty |
Minimum PoW difficulty | "0" | 0-40 |
pow_mode |
PoW validation mode | "optional" | "disabled", "optional", "required" |
Event Expiration (NIP-40)
| Parameter | Description | Default | Options |
|---|---|---|---|
nip40_expiration_enabled |
Enable expiration handling | "true" | "true", "false" |
nip40_expiration_strict |
Strict expiration mode | "false" | "true", "false" |
nip40_expiration_filter |
Filter expired events | "true" | "true", "false" |
nip40_expiration_grace_period |
Grace period (seconds) | "300" | 0-86400 |
Web Admin Interface
The relay includes a built-in web-based administration interface that provides a user-friendly way to manage your relay without command-line tools.
Accessing the Interface
- Open your browser and navigate to:
http://localhost:8888/api/ - Authenticate using your Nostr identity (the admin interface uses NIP-42 authentication)
- Manage configuration through the web interface
Features
- Real-time Configuration: View and edit all relay settings
- Database Statistics: Monitor event counts, storage usage, and performance metrics
- Auth Rules Management: Configure whitelist/blacklist rules for pubkeys
- Relay Connection Testing: Verify WebSocket connectivity and NIP-11 information
- Event-Based Updates: All changes are applied as signed Nostr events
Security Notes
- The web interface requires NIP-42 authentication with your admin pubkey
- All configuration changes are cryptographically signed
- The interface serves embedded static files (no external dependencies)
- CORS headers are included for proper browser operation
Browser Compatibility
The admin interface works with modern browsers that support:
- WebSocket connections
- ES6 JavaScript features
- Modern CSS Grid and Flexbox layouts
Administration
Viewing Current Configuration
# Find your database
ls -la *.nrdb
# View configuration events
sqlite3 <relay_pubkey>.nrdb "SELECT created_at, tags FROM events WHERE kind = 33334 ORDER BY created_at DESC LIMIT 1;"
# View all configuration history
sqlite3 <relay_pubkey>.nrdb "SELECT datetime(created_at, 'unixepoch') as date, tags FROM events WHERE kind = 33334 ORDER BY created_at DESC;"
Admin Key Management
Backup Admin Keys
# Create secure backup
echo "Admin Private Key: <your_admin_key>" > admin_keys_backup_$(date +%Y%m%d).txt
chmod 600 admin_keys_backup_*.txt
# Store in secure location (password manager, encrypted drive, etc.)
Key Recovery
If you lose your admin private key:
- Stop the relay:
pkill c_relayorsudo systemctl stop c-relay - Backup events:
cp <relay_pubkey>.nrdb backup_$(date +%Y%m%d).nrdb - Remove database:
rm <relay_pubkey>.nrdb* - Restart relay: This creates new database with new keys
- ⚠️ Note: All stored events and configuration history will be lost
Security Best Practices
Admin Key Security
- Never share the admin private key
- Store securely in password manager or encrypted storage
- Backup safely to multiple secure locations
- Monitor configuration changes in logs
Network Security
# Restrict access with firewall
sudo ufw allow 8888/tcp
# Use reverse proxy for HTTPS (recommended)
# Configure nginx/apache to proxy to ws://localhost:8888
Database Security
# Secure database file permissions
chmod 600 <relay_pubkey>.nrdb
chown c-relay:c-relay <relay_pubkey>.nrdb
# Regular backups
cp <relay_pubkey>.nrdb backup/relay_backup_$(date +%Y%m%d_%H%M%S).nrdb
Monitoring
Service Status
# Check if relay is running
ps aux | grep c_relay
# SystemD status
sudo systemctl status c-relay
# Network connections
netstat -tln | grep 8888
sudo ss -tlpn | grep 8888
Log Monitoring
# Real-time logs (systemd)
sudo journalctl -u c-relay -f
# Recent logs
sudo journalctl -u c-relay --since "1 hour ago"
# Error logs only
sudo journalctl -u c-relay -p err
# Configuration changes
sudo journalctl -u c-relay | grep "Configuration updated via kind 33334"
Database Analytics
# Connect to database
sqlite3 <relay_pubkey>.nrdb
# Event statistics
SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;
# Recent activity
SELECT datetime(created_at, 'unixepoch') as date, kind, LENGTH(content) as content_size
FROM events
ORDER BY created_at DESC
LIMIT 10;
# Subscription analytics (if logging enabled)
SELECT * FROM subscription_analytics ORDER BY date DESC LIMIT 7;
# Configuration changes
SELECT datetime(created_at, 'unixepoch') as date, tags
FROM configuration_events
ORDER BY created_at DESC;
Performance Monitoring
# Database size
du -sh <relay_pubkey>.nrdb*
# Memory usage
ps aux | grep c_relay | awk '{print $6}' # RSS memory in KB
# Connection count (approximate)
netstat -an | grep :8888 | grep ESTABLISHED | wc -l
# System resources
top -p $(pgrep c_relay)
Troubleshooting
Common Issues
Relay Won't Start
# Check port availability
netstat -tln | grep 8888
# If port in use, find process: sudo lsof -i :8888
# Check binary permissions
ls -la build/c_relay_x86
chmod +x build/c_relay_x86
# Check dependencies
ldd build/c_relay_x86
Configuration Not Updating
- Verify signature: Ensure event is properly signed with admin private key
- Check admin pubkey: Must match the pubkey from first startup
- Validate event structure: Use
nostrtool validateor similar - Check logs: Look for validation errors in relay logs
- Test WebSocket: Ensure WebSocket connection is active
# Test WebSocket connection
wscat -c ws://localhost:8888
# Send test message
{"id":"test","method":"REQ","params":["test",{}]}
Database Issues
# Check database integrity
sqlite3 <relay_pubkey>.nrdb "PRAGMA integrity_check;"
# Check schema version
sqlite3 <relay_pubkey>.nrdb "SELECT * FROM schema_info WHERE key = 'version';"
# View database size and stats
sqlite3 <relay_pubkey>.nrdb "PRAGMA page_size; PRAGMA page_count;"
Performance Issues
# Analyze slow queries (if any)
sqlite3 <relay_pubkey>.nrdb "PRAGMA compile_options;"
# Check database optimization
sqlite3 <relay_pubkey>.nrdb "PRAGMA optimize;"
# Monitor system resources
iostat 1 5 # I/O statistics
free -h # Memory usage
Recovery Procedures
Corrupted Database Recovery
# Attempt repair
sqlite3 <relay_pubkey>.nrdb ".recover" > recovered.sql
sqlite3 recovered.nrdb < recovered.sql
# If repair fails, start fresh (loses all events)
mv <relay_pubkey>.nrdb <relay_pubkey>.nrdb.corrupted
./build/c_relay_x86 # Creates new database
Lost Configuration Recovery
If configuration is lost but database is intact:
- Find old config:
sqlite3 <relay_pubkey>.nrdb "SELECT * FROM configuration_events;" - Create new config event: Use last known good configuration
- Sign and send: Update with current timestamp and new signature
Emergency Restart
# Quick restart with clean state
sudo systemctl stop c-relay
mv <relay_pubkey>.nrdb <relay_pubkey>.nrdb.backup
sudo systemctl start c-relay
# Check logs for new admin keys
sudo journalctl -u c-relay --since "5 minutes ago" | grep "Admin Private Key"
Advanced Usage
Custom Event Handlers
The relay supports custom handling for different event types. Configuration changes trigger:
- Subscription Manager Updates: When client limits change
- PoW System Reinitialization: When PoW settings change
- Expiration System Updates: When NIP-40 settings change
- Relay Info Updates: When NIP-11 information changes
API Integration
// Connect and send configuration update
const ws = new WebSocket('ws://localhost:8888');
ws.on('open', function() {
const configEvent = {
kind: 33334,
content: "Updated configuration",
tags: [
["d", relayPubkey],
["relay_description", "Updated via API"]
],
created_at: Math.floor(Date.now() / 1000),
pubkey: adminPubkey,
// ... add id and sig
};
ws.send(JSON.stringify(["EVENT", configEvent]));
});
Backup Strategies
Automated Backup
#!/bin/bash
# backup-relay.sh
DATE=$(date +%Y%m%d_%H%M%S)
DB_FILE=$(ls *.nrdb | head -1)
BACKUP_DIR="/backup/c-relay"
mkdir -p $BACKUP_DIR
cp $DB_FILE $BACKUP_DIR/relay_backup_$DATE.nrdb
gzip $BACKUP_DIR/relay_backup_$DATE.nrdb
# Cleanup old backups (keep 30 days)
find $BACKUP_DIR -name "relay_backup_*.nrdb.gz" -mtime +30 -delete
Configuration Export
# Export configuration events
sqlite3 <relay_pubkey>.nrdb "SELECT json_object(
'kind', kind,
'content', content,
'tags', json(tags),
'created_at', created_at,
'pubkey', pubkey,
'sig', sig
) FROM events WHERE kind = 33334 ORDER BY created_at;" > config_backup.json
Migration Between Servers
# Source server
tar czf relay_migration.tar.gz *.nrdb* relay.log
# Target server
tar xzf relay_migration.tar.gz
./build/c_relay_x86 # Will detect existing database and continue
This user guide provides comprehensive coverage of the C Nostr Relay's event-based configuration system. For additional technical details, see the developer documentation in the docs/ directory.