Skip to main content

Relay Sync Tools

Tools and techniques for synchronizing events between relays.

Why Sync Relays?​

  • Backup: Replicate events to personal relay
  • Migration: Move from one relay to another
  • Bridging: Connect different relay networks
  • Archiving: Preserve historical events

Negentropy Sync (strfry)​

strfry includes built-in negentropy sync for efficient relay-to-relay synchronization.

How It Works​

Negentropy is a set reconciliation protocol that efficiently determines which events differ between two relays without transferring all events.

Sync Command​

# Sync from remote relay to local
strfry sync wss://relay.damus.io

# Sync specific filter
strfry sync wss://relay.damus.io --filter '{"kinds":[1],"limit":1000}'

# Continuous sync
strfry sync wss://relay.damus.io --continuous

Configuration​

Add to strfry.conf:

sync {
# Relays to sync with
upstreams = [
"wss://relay.damus.io",
"wss://nos.lol"
]

# Filter for sync
filter = {
"kinds": [0, 1, 3, 7]
}

# Sync interval (seconds)
interval = 300
}

NAK (Nostr Army Knife)​

nak includes sync capabilities.

Installation​

go install github.com/fiatjaf/nak@latest

Sync Usage​

# Sync events from one relay to another
nak sync wss://source-relay.com wss://destination-relay.com

# With filter
nak sync wss://source.com wss://dest.com --filter '{"authors":["pubkey"]}'

Guide​

For detailed instructions, see: NAK Sync Guide

Manual Sync Scripts​

Export and Import​

# Export from one relay
echo '["REQ","export",{"kinds":[1],"limit":10000}]' | \
websocat -n wss://source-relay.com > events.jsonl

# Process and publish to another relay
cat events.jsonl | jq -c '.[2] // empty' | while read event; do
echo "[\"EVENT\",$event]" | websocat -n wss://dest-relay.com
done

Sync Script​

#!/bin/bash
# sync-events.sh

SOURCE="wss://source-relay.com"
DEST="wss://destination-relay.com"
PUBKEY="your-pubkey-hex"

# Fetch events from source
echo "Fetching events from $SOURCE..."
echo "[\"REQ\",\"sync\",{\"authors\":[\"$PUBKEY\"],\"limit\":1000}]" | \
timeout 30 websocat -n "$SOURCE" | \
jq -c 'select(.[0] == "EVENT") | .[2]' > /tmp/events.jsonl

# Count events
COUNT=$(wc -l < /tmp/events.jsonl)
echo "Found $COUNT events"

# Publish to destination
echo "Publishing to $DEST..."
cat /tmp/events.jsonl | while read event; do
echo "[\"EVENT\",$event]" | websocat -n "$DEST"
sleep 0.1 # Rate limiting
done

echo "Done!"

Hyper-Nostr P2P Sync​

hyper-nostr enables peer-to-peer relay synchronization.

Setup​

npm install -g hyper-nostr

# Start relay with topic
hyper-nostr 3338 nostr

How It Works​

  • Relays join a "topic" (DHT key)
  • Automatically discover peers
  • Sync events in real-time
  • No central coordinator needed

Use Cases​

  • Distributed relay networks
  • Offline-first applications
  • Resilient sync infrastructure

RSS Bridges​

Sync content to/from RSS feeds.

nostrss​

Publish RSS feeds to Nostr.

Repository: github.com/Asone/nostrss

# Clone and configure
git clone https://github.com/Asone/nostrss
cd nostrss
cp config.example.toml config.toml
# Edit config.toml with your feeds and keys

# Run
cargo run

atomstr​

Convert Nostr to Atom feeds.

Repository: git.sr.ht/~psic4t/atomstr

Mirroring​

nostream Mirror Mode​

Configure nostream to mirror events from other relays:

MIRROR_ENABLED=true
MIRROR_URLS="wss://relay.damus.io,wss://nos.lol"

Custom Mirror Script​

#!/usr/bin/env python3
# mirror.py

import asyncio
import json
import websockets

SOURCE = "wss://source-relay.com"
DEST = "wss://dest-relay.com"

async def mirror():
async with websockets.connect(SOURCE) as source:
async with websockets.connect(DEST) as dest:
# Subscribe to all events
await source.send(json.dumps(["REQ", "mirror", {"limit": 0}]))

async for message in source:
data = json.loads(message)
if data[0] == "EVENT":
event = data[2]
await dest.send(json.dumps(["EVENT", event]))
print(f"Mirrored: {event['id'][:16]}...")

asyncio.run(mirror())

Update Relay Lists​

Publish your relay list (NIP-65) to multiple relays:

# Using nak
for relay in $(curl -s https://api.nostr.watch/v1/online | jq -r '.[]'); do
nak event -c "" \
-t r=wss://relay1.com \
-t r=wss://relay2.com \
-t r=wss://relay3.com \
--kind 10002 \
--sec $PRIVKEY \
$relay
done

Best Practices​

  1. Rate limit sync operations to avoid overloading relays
  2. Use filters to sync only needed events
  3. Verify events before publishing to destination
  4. Monitor sync progress and errors
  5. Deduplicate to avoid publishing duplicates

See Also​