Skip to content

high-moctane/mocrelay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

939 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mocrelay

A middleware-composable Nostr relay library for Go.

Go Reference

Features

  • Middleware Architecture - Compose handlers and middleware to build your relay
  • NIP-11 Driven - Built-in middleware maps directly to NIP-11 limitation fields
  • Pure Go - No cgo dependencies, single binary deployment
  • Persistent Storage - Pebble-based LSM-tree storage with MVCC support
  • Full-text Search - Bleve-based NIP-50 search with CJK support
  • Prometheus Metrics - Built-in instrumentation for relay, router, auth, and storage
  • Standard http.Handler - Composes naturally with net/http.ServeMux

Requirements

  • Go 1.25 or later
  • GOEXPERIMENT=jsonv2 environment variable
export GOEXPERIMENT=jsonv2

Installation

go get github.com/high-moctane/mocrelay

Development

Git hooks are optional. To run go fix and gofmt automatically on staged Go files before each commit, install lefthook and run:

lefthook install

The lefthook.yml in the repository configures the hooks. CI runs the same checks, so skipping local hooks will not bypass them.

Quick Start

The simplest possible relay is a single line:

func main() {
	log.Fatal(http.ListenAndServe(":7447", mocrelay.NewRelay(mocrelay.NewNopHandler(), nil)))
}

This accepts all events and returns EOSE for all subscriptions — a valid relay with zero storage, in one line.

For a more practical starting point, see the examples.

Examples

The cmd/examples/ directory provides three graduated examples:

Example Description
nop One-line relay. Demonstrates that a Handler is all you need.
minimal In-memory storage, real-time routing, and basic middleware. A functional relay in ~80 lines.
kitchen-sink Pebble + Bleve + all middleware + Prometheus + ServeMux. Everything mocrelay offers.

Architecture

            ┌──────────────────────────────────────────────┐
            │          Relay (http.Handler)                │
            │          WebSocket lifecycle management      │
            ├──────────────────────────────────────────────┤
            │          Middleware Pipeline                 │
            │   Auth → ProtectedEvents → Limits → ...      │
            ├──────────────────────────────────────────────┤
            │              MergeHandler                    │
            │     ┌────────────────┬──────────────────┐    │
            │     │ StorageHandler │  RouterHandler   │    │
            │     │ (past events)  │  (real-time)     │    │
            │     └───────┬────────┴────────┬─────────┘    │
            ├─────────────┼─────────────────┼──────────────┤
            │   ┌─────────┴────────┐  ┌─────┴───────┐      │
            │   │ CompositeStorage │  │   Router    │      │
            │   │  ┌──────┬──────┐ │  │ (broadcast) │      │
            │   │  │Pebble│Bleve │ │  └─────────────┘      │
            │   │  └──────┴──────┘ │                       │
            │   └──────────────────┘                       │
            └──────────────────────────────────────────────┘
  • Relay serves HTTP/WebSocket and manages connection lifecycles
  • Handler processes messages for a single connection
  • Middleware wraps a Handler to add cross-cutting concerns
  • Storage persists and queries events using Go iterators (iter.Seq)
  • Router routes events between connected clients in real-time

Available Middleware

Middleware NIP-11 Field Description
MaxSubscriptions max_subscriptions Limit subscriptions per connection
MaxSubidLength max_subid_length Limit subscription ID length
MaxLimit max_limit, default_limit Clamp filter limit values
MaxEventTags max_event_tags Limit tags per event
MaxContentLength max_content_length Limit content length
CreatedAtLimits created_at_lower/upper_limit Restrict event timestamps
KindDenylist retention Block specific event kinds
RestrictedWrites restricted_writes Pubkey allow/deny list
MinPowDifficulty min_pow_difficulty Require proof-of-work (NIP-13)
Auth auth_required Require authentication (NIP-42)
Expiration - Handle event expiration (NIP-40)
ProtectedEvents - Protect events from republishing (NIP-70)

Multiple middleware are composed into a single pipeline via NewSimpleMiddleware:

handler = mocrelay.NewSimpleMiddleware(
    mocrelay.NewMaxSubscriptionsMiddlewareBase(20),
    mocrelay.NewMaxLimitMiddlewareBase(500, 100),
    mocrelay.NewKindDenylistMiddlewareBase([]int64{4, 1059}),
)(handler)

NIP Support

NIP Description
NIP-01 Basic Protocol
NIP-09 Event Deletion
NIP-11 Relay Information
NIP-13 Proof of Work
NIP-40 Expiration Timestamp
NIP-42 Authentication
NIP-45 Event Counts
NIP-50 Search Capability
NIP-70 Protected Events

License

MIT

About

A middleware-composable Nostr relay implementation in Go.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages