# C Nostr Relay - Event-Based Configuration System A high-performance Nostr relay implemented in C with SQLite backend, featuring a revolutionary **zero-configuration** approach using event-based configuration management. ## 📜 Supported NIPs - [x] NIP-01: Basic protocol flow implementation - [x] NIP-09: Event deletion - [x] NIP-11: Relay information document - [x] NIP-13: Proof of Work - [x] NIP-15: End of Stored Events Notice - [x] NIP-20: Command Results - [x] NIP-33: Parameterized Replaceable Events - [x] NIP-40: Expiration Timestamp - [x] NIP-42: Authentication of clients to relays - [ ] NIP-45: Counting results - [ ] NIP-50: Keywords filter - [ ] NIP-70: Protected Events ## 🔧 Administrator API C-Relay uses an innovative **event-based administration system** where all configuration and management commands are sent as signed Nostr events using the admin private key generated during first startup. Admin commands use ephemeral kinds 23455 and 23456 with **optional NIP-44 encryption** for enhanced security. ### Authentication All admin commands require signing with the admin private key displayed during first-time startup. **Save this key securely** - it cannot be recovered and is needed for all administrative operations. ### Security Options **Standard Mode (Plaintext):** Commands sent in tags as normal **Encrypted Mode (NIP-44):** Commands encrypted in content field, no tags used ### Kind 23455: Configuration Management (Ephemeral) Update relay configuration parameters or query available settings. **Configuration Update:** ```json { "kind": 23455, "content": "", "tags": [ ["config_key1", "config_value1"], ["config_key2", "config_value2"] ] } ``` **Query Available Config Keys:** ```json { "kind": 23455, "content": "", "tags": [ ["config_query", "list_all_keys"] ] } ``` **Get Current Configuration:** ```json { "kind": 23455, "content": "", "tags": [ ["config_query", "get_current_config"] ] } ``` **Available Configuration Keys:** **Basic Relay Settings:** - `relay_description`: Relay description text - `relay_contact`: Contact information - `max_connections`: Maximum concurrent connections - `max_subscriptions_per_client`: Max subscriptions per client - `max_event_tags`: Maximum tags per event - `max_content_length`: Maximum event content length **Authentication & Access Control:** - `auth_enabled`: Enable whitelist/blacklist auth rules (`true`/`false`) - `nip42_auth_required`: Enable NIP-42 cryptographic authentication (`true`/`false`) - `nip42_auth_required_kinds`: Event kinds requiring NIP-42 auth (comma-separated) - `nip42_challenge_timeout`: NIP-42 challenge expiration seconds **Proof of Work & Validation:** - `pow_min_difficulty`: Minimum proof-of-work difficulty - `nip40_expiration_enabled`: Enable event expiration (`true`/`false`) ### Kind 23456: Auth Rules & System Management (Ephemeral) Manage whitelist/blacklist rules and system administration commands. **Add Blacklist Rule:** ```json { "kind": 23456, "content": "", "tags": [ ["blacklist", "pubkey", "deadbeef1234abcd..."] ] } ``` **Add Whitelist Rule:** ```json { "kind": 23456, "content": "", "tags": [ ["whitelist", "pubkey", "cafebabe5678efgh..."] ] } ``` **Remove Rule:** ```json { "kind": 23456, "content": "", "tags": [ ["blacklist", "pubkey", "deadbeef1234abcd..."] ] } ``` **Query Auth Rules:** ```json { "kind": 23456, "content": "", "tags": [ ["auth_query", "all"] ] } ``` **Query Specific Rule Type:** ```json { "kind": 23456, "content": "", "tags": [ ["auth_query", "whitelist"] ] } ``` **Query Specific Pattern:** ```json { "kind": 23456, "content": "", "tags": [ ["auth_query", "pattern", "deadbeef1234abcd..."] ] } ``` **Clear All Auth Rules:** ```json { "kind": 23456, "content": "", "tags": [ ["system_command", "clear_all_auth_rules"] ] } ``` ### Response Format All admin commands return JSON responses via WebSocket: **Success Response:** ```json ["OK", "event_id", true, "Operation completed successfully"] ``` **Error Response:** ```json ["OK", "event_id", false, "Error: invalid configuration value"] ``` ### Command Examples **Using `nak` CLI tool:** ```bash # Set environment variables ADMIN_PRIVKEY="your_admin_private_key_here" RELAY_PUBKEY="your_relay_public_key_here" RELAY_URL="ws://localhost:8888" # List all available configuration keys nak event -k 23455 --content "Discovery query" \ -t "config_query=list_all_keys" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Enable whitelist/blacklist auth rules nak event -k 23455 --content "Enable auth rules" \ -t "auth_enabled=true" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Add user to blacklist nak event -k 23456 --content "Block spam user" \ -t "blacklist=pubkey;$SPAM_USER_PUBKEY" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Add user to whitelist nak event -k 23456 --content "Allow trusted user" \ -t "whitelist=pubkey;$TRUSTED_USER_PUBKEY" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Query all current auth rules nak event -k 23456 --content "Get all auth rules" \ -t "auth_query=all" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Query only whitelist rules nak event -k 23456 --content "Get whitelist rules" \ -t "auth_query=whitelist" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Query only blacklist rules nak event -k 23456 --content "Get blacklist rules" \ -t "auth_query=blacklist" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Check if specific pattern exists nak event -k 23456 --content "Check user status" \ -t "auth_query=pattern;$CHECK_USER_PUBKEY" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Clear all auth rules (for testing) nak event -k 23456 --content "Clear all rules" \ -t "system_command=clear_all_auth_rules" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Update relay description nak event -k 23455 --content "Update description" \ -t "relay_description=My awesome relay" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Set connection limits nak event -k 23455 --content "Update limits" \ -t "max_connections=500" \ -t "max_subscriptions_per_client=10" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL ``` **For encrypted commands (NIP-44), use empty tags and encrypted content:** ```bash # Enable auth rules (encrypted) ENCRYPTED_TAGS=$(echo '[["auth_enabled","true"]]' | nip44_encrypt_with_relay_pubkey) nak event -k 23455 --content "{\"encrypted_tags\":\"$ENCRYPTED_TAGS\"}" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Add user to blacklist (encrypted) ENCRYPTED_TAGS=$(echo '[["blacklist","pubkey","'$SPAM_USER_PUBKEY'"]]' | nip44_encrypt_with_relay_pubkey) nak event -k 23456 --content "{\"encrypted_tags\":\"$ENCRYPTED_TAGS\"}" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL ``` ### Authentication Systems C-Relay supports **two independent authentication systems**: #### 1. Auth Rules (Whitelist/Blacklist) - **Config Key**: `auth_enabled=true` - **Purpose**: Block or allow specific pubkeys from publishing events - **Method**: Database-driven rules enforcement - **Use Case**: Spam prevention, content moderation #### 2. NIP-42 Cryptographic Authentication - **Config Key**: `nip42_auth_required=true` - **Purpose**: Require cryptographic proof of pubkey ownership - **Method**: Challenge-response authentication protocol - **Use Case**: Verified identity, premium features **Important**: These systems can be used independently or together: - `auth_enabled=true` + `nip42_auth_required=false`: Only whitelist/blacklist rules - `auth_enabled=false` + `nip42_auth_required=true`: Only NIP-42 auth challenges - Both `true`: Users must pass NIP-42 auth AND not be blacklisted ### Security Considerations - **Private Key Protection**: Admin private key grants full relay control - **Network Access**: Admin commands should only be sent over secure connections - **Backup**: Keep secure backups of admin private key - **Rotation**: Consider implementing admin key rotation for production deployments ### Troubleshooting **Common Issues:** - `auth-required: not authorized admin`: Verify you're using the correct admin private key - `invalid: missing or invalid kind`: Ensure event kind is 23455 or 23456 - `error: failed to process configuration event`: Check configuration key/value validity - `no valid auth rules found`: Verify tag format uses semicolon syntax for multi-element tags **Debug Commands:** ```bash # Check if relay is accepting connections echo '["REQ","test",{}]' | websocat ws://localhost:8888 # Test admin authentication nak event -k 23455 --content "Test auth" \ -t "test_config=true" \ --sec $ADMIN_PRIVKEY | nak event ws://localhost:8888 # Discover available configuration keys nak event -k 23455 --content "Discovery query" \ -t "config_query=list_all_keys" \ --sec $ADMIN_PRIVKEY | nak event ws://localhost:8888 # Query current auth rules nak event -k 23456 --content "Get auth rules" \ -t "auth_query=all" \ --sec $ADMIN_PRIVKEY | nak event ws://localhost:8888 ``` ### Configuration Discovery Before making changes, admins can query the relay to discover all available configuration options: ```bash # Get list of all editable configuration keys with descriptions nak event -k 23455 --content '{"query":"list_config_keys","description":"Discovery"}' \ -t "config_query=list_all_keys" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL # Get current values of all configuration parameters nak event -k 23455 --content '{"query":"get_config","description":"Current state"}' \ -t "config_query=get_current_config" \ --sec $ADMIN_PRIVKEY | nak event $RELAY_URL ``` **Expected Response Format:** ```json ["EVENT", "subscription_id", { "kind": 23455, "content": "{\"config_keys\": [\"auth_enabled\", \"max_connections\", ...], \"descriptions\": {...}}", "tags": [["response_type", "config_keys_list"]] }] ```