Skip to content

sanah9/nopu

Repository files navigation

Nopu

Project Overview

Nopu is a completely free and open source push service based on the Nostr protocol

  • Built-in subscription management leveraging the NIP-29 relay implementation.
  • Users can configure pushes to be delivered exclusively to their own clients, or deploy a self-hosted push server.
  • The Nopu client can freely choose a private push server instead of the nopu.sh server.

System Architecture

System Architecture

  • Subscription Server
    • Self-hostable
    • Subscribes to relay events
    • Receives client subscriptions
  • nopu Push Server
    • Receives messages from Subscription Server
    • Forwards via FCM/APNs
  • nopu Clients (iOS / Android)
    • Display push messages
    • Send subscriptions to Subscription Server

Event Flow

  1. The client creates a subscription by publishing a kind 9007 event, which creates a NIP-29 private group. The event's about field uses the following format:

    ["REQ", <device_id>, <filters1>, <filters2>, ...]
    
  2. The server actively listens to multiple public relays for events matching client subscription filters. When an event is received, it is wrapped into a kind 20284 event and forwarded to the appropriate client group. The server also receives external kind 20285 events (with configurable pubkey whitelist) that contain original events in their content, which are then matched and forwarded to clients.

  3. For every group whose filters match the event:

    • A kind 20284 event (wrapped from the original relay event) is forwarded to the group for online clients.
    • If no members of the group are online, a push notification is sent via APNS / FCM.
  4. If the client needs to update its subscription filters, it publishes a kind 9002 event containing the new filter set to refresh the existing subscription.

Event Types

Kind 20284 - Wrapped Relay Events

The kind 20284 event wraps original events from public relays as a JSON string and targets a specific NIP-29 group for online clients. The subscription server actively listens to multiple public relays, wraps matching events into kind 20284, and forwards them to clients.

{
  "kind": 20284,
  "content": "<stringified original event JSON>",
  "created_at": <unix_timestamp>,
  "tags": [
    ["h", "<group_id>"]
  ],
  "pubkey": "<relay_pubkey>",
  "id": "<event_id>",
  "sig": "<signature>"
}

Field explanations:

  • content: The original Nostr event from public relays, serialized as a JSON string.
  • h tag: Associates the wrapped event with the target subscription group.
  • created_at: Timestamp generated by the relay when forwarding.
  • pubkey: The relay's public key used to sign the event.
  • sig: Signature computed with the relay's private key.

Kind 20285 - External Event Injection

The kind 20285 event is received from external sources (with configurable pubkey whitelist). The subscription server handles two scenarios:

  1. Empty content - If the 20285 event has empty content, it matches the 20285 event itself against client subscription filters
  2. Content with original event - If the 20285 event contains a complete original event in its content, it parses and matches the original event against client subscription filters

The server then forwards the event to all matching clients.

{
  "kind": 20285,
  "content": "<stringified original event JSON>",
  "created_at": <unix_timestamp>,
  "tags": [],
  "pubkey": "<external_pubkey>",
  "id": "<event_id>",
  "sig": "<signature>"
}

Field explanations:

  • content: A complete original Nostr event, serialized as a JSON string.
  • created_at: Timestamp when the 20285 event was created.
  • pubkey: The external source's public key (subject to whitelist validation).
  • sig: Signature computed with the external source's private key.

Quick Start

1. Environment Setup

# No external dependencies required!
# The system now uses in-memory queue instead of Redis
# This significantly reduces memory usage and simplifies deployment

2. Configuration

# Copy configuration file
cp config.yaml.example config.yaml

3. Start Service

# Install dependencies 
make deps

# Run both services
make run-both

# Or run services separately
make run-subscription  # Terminal 1
make run-push         # Terminal 2

4. Testing

# Run all tests
make test-all

# Run specific tests
make test-subscription  # Test subscription server
make test-push         # Test push server

# Run integration tests
make test-integration

# Run test client
make test-client

# For detailed testing guide, see TESTING.md

Development Status

Completed

  • Active listening to multiple public relays
  • Event wrapping into kind 20284 for online clients
  • External kind 20285 event injection with pubkey whitelist
  • Basic subscription workflow
  • Client online presence detection
  • APNs push notifications

In Progress

  • Intelligent minimal filters merging
  • FCM push notifications
  • Performance optimization

About

Nopu is a completely free and open source push service based on the Nostr protocol

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors