# 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-pg"`
- **Format**: String, max 64 characters
- **Example**: `"c-relay-pg 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-pg | 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_pg)

# Check for memory leaks
ps aux | grep c_relay_pg | 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_pg_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.