433 lines
13 KiB
Markdown
433 lines
13 KiB
Markdown
# Configuration Management Guide
|
|
|
|
Comprehensive guide for managing the C Nostr Relay's event-based configuration system.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Configuration Events](#configuration-events)
|
|
- [Parameter Reference](#parameter-reference)
|
|
- [Configuration Examples](#configuration-examples)
|
|
- [Security Considerations](#security-considerations)
|
|
- [Troubleshooting](#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
|
|
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:
|
|
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
# 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
|
|
```javascript
|
|
// Verify event signature with nostrtool or similar
|
|
const event = { /* your configuration event */ };
|
|
const isValid = nostrTools.verifySignature(event);
|
|
```
|
|
|
|
#### Verify Admin Pubkey
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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. |