A service that implements encrypted push notifications for Nostr clients following the NIP-XX Push Notifications draft specification.
This service:
- Listens for encrypted push token registrations from Nostr clients (kinds 3079-3082)
- Monitors configured relays for events matching user-defined filters
- Sends push notifications via Firebase Cloud Messaging (FCM) when relevant events occur
- Supports multiple apps with isolated token management
- Requires NIP-44 encryption for all tokens (plaintext tokens are rejected)
The service implements four Nostr event kinds:
- 3079: Register push token (encrypted)
- 3080: Deregister push token (encrypted)
- 3081: Add/update notification filter (encrypted)
- 3082: Delete notification filter (encrypted)
All events must include a p tag with the service's public key and use NIP-44 encryption. See the protocol specification for details.
# Required
NOSTR_PUSH__SERVICE__PRIVATE_KEY_HEX="<service_private_key>" # For NIP-44 decryption
REDIS_URL="redis://localhost:6379" # Token storage# LOCAL DEVELOPMENT - Point to local files:
export NOSTR_PUSH__APPS__NOSTRPUSHDEMO__CREDENTIALS_PATH="./firebase-service-account-nostrpushdemo.json"
export NOSTR_PUSH__APPS__UNIVERSES__CREDENTIALS_PATH="./firebase-service-account-universes.json"
# Or just place files with these exact names (auto-detection):
# - firebase-service-account-nostrpushdemo.json
# - firebase-service-account-universes.json
# PRODUCTION (K8s) - Point to mounted secret files:
export NOSTR_PUSH__APPS__NOSTRPUSHDEMO__CREDENTIALS_PATH="/app/secrets/firebase-nostrpushdemo.json"
export NOSTR_PUSH__APPS__UNIVERSES__CREDENTIALS_PATH="/app/secrets/firebase-universes.json"Configure supported apps in config/settings.yaml:
apps:
- name: "nostrpushdemo"
fcm_project_id: "plur-push-local"
- name: "universes"
fcm_project_id: "universes-push" # Your Firebase project IDEach app needs its own Firebase service account. See setup-credentials.sh for configuration options.
docker compose build
docker compose up -dcargo build --release
cargo run --releaseVisit http://localhost:8000/ for a test interface that demonstrates:
- Token registration with NIP-44 encryption
- Subscription management
- Push notification testing
- Clients publish encrypted registration events to Nostr relays
- Service monitors relays and decrypts events targeted to its public key
- Redis stores pubkey→token mappings with app isolation
- FCM delivers push notifications to registered devices
The service supports NIP-29 relay-based groups with membership validation:
- Validates group membership before sending notifications for group events (h-tag)
- Queries relay for kind 39002 (group members) events
- Caches membership data (default: 5 minutes) to reduce relay queries
- Supports both managed and unmanaged groups
Users can subscribe to group messages via custom filters:
{
"kinds": [9],
"#h": ["group-id"]
}- Orphaned subscriptions automatically removed when membership check fails
- Only removes subscriptions specific to that single group (safe for multi-group filters)
- Self-healing without monitoring moderation events
Your NIP-29 relay must:
- Publish kind 39002 events (group members list) signed by relay key
- Publish kind 39001 events (group admins) for broadcast validation
- Support standard NIP-29 group management events
- All tokens must be NIP-44 encrypted (plaintext rejected)
- Tokens are isolated by app ID to prevent cross-app access
- Invalid tokens are automatically removed on FCM errors
- Supports token transfer between pubkeys for account switching