Skip to content

rabble/ombra

Repository files navigation

Umbra

High-performance Nostr relay built with Rust and OpenSearch.

Features

  • NIP-01, NIP-09, NIP-11, NIP-16, NIP-33, NIP-45, NIP-50, NIP-86
  • Multi-process architecture for connection scaling
  • OpenSearch backend with full-text search
  • Realtime streaming via Redis pub/sub (multi-node support)
  • Advanced NIP-50 search extensions (top, hot, controversial, rising)
  • Event counting via NIP-45 COUNT
  • Relay management API (NIP-86) with NIP-98 authentication
  • Relay-to-relay sync via Negentropy
  • Prometheus metrics

Quick Start

# Start OpenSearch
docker run -d -p 9200:9200 \
  -e "discovery.type=single-node" \
  -e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=Admin123!" \
  opensearchproject/opensearch:latest

# Build and run
cargo build --release
./target/release/umbra

Configuration

Set via environment variables:

  • UMBRA_BIND - WebSocket address (default: 0.0.0.0:7777)
  • UMBRA_OPENSEARCH_URL - OpenSearch URL(s), comma-separated for multiple nodes (default: http://localhost:9200)
  • UMBRA_REDIS_URL - Redis URL for cross-node streaming (optional, e.g., redis://localhost:6379)
  • UMBRA_WORKERS - Worker processes (default: CPU cores)
  • UMBRA_ADMIN_PUBKEYS - Comma-separated list of admin pubkeys for NIP-86
  • UMBRA_RELAY_URL - Public relay URL for NIP-98 verification (default: http://localhost:7777)
  • UMBRA_POOL_MAX_IDLE_PER_HOST - Max idle connections to OpenSearch per host (default: 100)
  • UMBRA_POOL_IDLE_TIMEOUT_SECS - Idle connection timeout in seconds (default: 300)
  • RUST_LOG - Log level (default: info)

Realtime Streaming

Umbra supports realtime event streaming to connected clients. When a client sends a REQ message, Umbra returns matching stored events, sends EOSE, then keeps the subscription open for new events.

Local streaming works out of the box - events received by a node are immediately broadcast to matching local subscriptions using in-memory inverted indexes for efficient O(1) lookups by author, kind, and tags.

Cross-node streaming requires Redis. When configured, events are published to a nostr:events Redis pub/sub channel, allowing multiple Umbra nodes to share events in realtime:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Node A    │────▶│    Redis    │◀────│   Node B    │
│  (events)   │◀────│  pub/sub    │────▶│  (events)   │
└─────────────┘     └─────────────┘     └─────────────┘

Advanced Search

Umbra supports powerful NIP-50 search extensions for content discovery:

{"kinds": [1], "search": "sort:hot bitcoin", "limit": 50}

Sort Modes:

  • sort:top - Most referenced events (all-time best)
  • sort:hot - Trending now (recent + popular)
  • sort:controversial - Mixed positive/negative reactions
  • sort:rising - Rapidly gaining traction

Metrics

Prometheus metrics available at http://localhost:9090/metrics

Testing

Run the test suite:

# Run all tests (single-threaded for env var tests)
cargo test -- --test-threads=1

# Run clippy with pedantic checks
cargo clippy -- -D warnings -D clippy::all -D clippy::pedantic

Note: Some tests manipulate environment variables and require single-threaded execution to avoid race conditions.

License

AGPLv3

About

Nostr relay with purgatory mode for content moderation

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors