ORLY implements NIP-77 negentropy-based set reconciliation for efficient relay synchronization. This guide covers configuration for all deployment modes.
NIP-77 allows clients and relays to efficiently determine which events they have in common and which they're missing, without transferring full event lists. A client sends a NEG-OPEN message with a filter and a compact fingerprint of its local event set. The relay compares this against its own events and responds with NEG-MSG containing the diff. After one or more round-trips the reconciliation completes and the relay sends the missing EVENT messages.
ORLY supports two negentropy modes:
The mode is determined by ORLY_SYNC_TYPE:
local (default) = embedded modegrpc = gRPC mode (used automatically when running via orly launcher)The simplest setup. One env var, one process:
ORLY_NEGENTROPY_ENABLED=true ./orly
This starts the relay with an embedded negentropy handler. Clients can immediately use NEG-OPEN/NEG-MSG/NEG-CLOSE messages.
Verify it works — you should see this in the logs:
initializing embedded negentropy handler
embedded negentropy handler initialized (NIP-77 enabled)
If you don't see these lines, negentropy is not active. Check that ORLY_NEGENTROPY_ENABLED=true is actually set (not ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED — that's a different variable for the launcher).
Verify via NIP-11 — the relay info document should list NIP-77 support:
curl -s -H "Accept: application/nostr+json" https://your-relay.example.com | jq '.supported_nips'
When running via orly launcher, negentropy runs as a separate subprocess. The launcher automatically sets all the env vars the relay needs (ORLY_SYNC_TYPE=grpc, ORLY_NEGENTROPY_ENABLED=true, ORLY_GRPC_SYNC_NEGENTROPY=...).
You only need to tell the launcher to enable it:
ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED=true ./orly launcher
Verify it works — you should see these log lines in order:
starting negentropy service on 127.0.0.1:50064
negentropy service is ready
connecting to gRPC negentropy server at 127.0.0.1:50064
gRPC negentropy client connected
If you see negentropy client is nil when a client sends NEG-OPEN, the gRPC connection failed. See Troubleshooting below.
To sync events with other relays in the background:
# Standalone
ORLY_NEGENTROPY_ENABLED=true \
ORLY_SYNC_NEGENTROPY_PEERS=wss://relay1.example.com,wss://relay2.example.com \
./orly
# Launcher mode
ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED=true \
ORLY_SYNC_NEGENTROPY_PEERS=wss://relay1.example.com,wss://relay2.example.com \
./orly launcher
The relay periodically reconciles with each peer using negentropy, pulling and pushing events as needed.
These control the relay's NIP-77 behavior. In launcher mode, most are set automatically by the launcher.
| Variable | Default | Description |
|---|---|---|
ORLY_NEGENTROPY_ENABLED | false | Enable NIP-77 negentropy support. Required. |
ORLY_SYNC_TYPE | local | local = embedded handler, grpc = connect to gRPC service. The launcher sets this automatically. |
ORLY_GRPC_SYNC_NEGENTROPY | 127.0.0.1:50056 | gRPC address of negentropy service. Only used when ORLY_SYNC_TYPE=grpc. |
ORLY_GRPC_SYNC_TIMEOUT | 10s | Timeout for gRPC connection to negentropy service. |
These control whether and how the launcher spawns the negentropy subprocess.
| Variable | Default | Description |
|---|---|---|
ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED | false | Enable negentropy subprocess in launcher mode. |
ORLY_LAUNCHER_SYNC_NEGENTROPY_LISTEN | 127.0.0.1:50064 | gRPC listen address for the negentropy service. |
These configure the negentropy service itself (the subprocess, not the relay).
| Variable | Default | Description |
|---|---|---|
ORLY_SYNC_NEGENTROPY_PEERS | Comma-separated WebSocket URLs of peer relays to sync with. | |
ORLY_SYNC_NEGENTROPY_INTERVAL | 60s | How often to sync with peers. |
ORLY_SYNC_NEGENTROPY_FRAME_SIZE | 4096 | Negentropy protocol frame size in bytes. |
ORLY_SYNC_NEGENTROPY_ID_SIZE | 16 | Event ID truncation size (bytes). 16 = first 16 bytes of 32-byte ID. |
ORLY_SYNC_NEGENTROPY_SESSION_TIMEOUT | 5m | How long a client reconciliation session stays open before timeout. |
Limit which events are included in negentropy reconciliation:
| Variable | Default | Description |
|---|---|---|
ORLY_SYNC_NEGENTROPY_FILTER_KINDS | Comma-separated kind numbers (e.g., 0,1,3,6,7). | |
ORLY_SYNC_NEGENTROPY_FILTER_AUTHORS | Comma-separated hex pubkeys. | |
ORLY_SYNC_NEGENTROPY_FILTER_SINCE | Unix timestamp: only events after this time. | |
ORLY_SYNC_NEGENTROPY_FILTER_UNTIL | Unix timestamp: only events before this time. |
[Unit]
Description=ORLY Nostr Relay
After=network.target
[Service]
ExecStart=/usr/local/bin/orly
Environment=ORLY_NEGENTROPY_ENABLED=true
Environment=ORLY_PORT=3334
[Install]
WantedBy=multi-user.target
[Unit]
Description=ORLY Nostr Relay (Launcher)
After=network.target
[Service]
ExecStart=/usr/local/bin/orly launcher
Environment=ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED=true
Environment=ORLY_LAUNCHER_SYNC_NEGENTROPY_LISTEN=127.0.0.1:50064
Environment=ORLY_PORT=3334
[Install]
WantedBy=multi-user.target
[program:orly-db]
command=/app/code/orly db --driver=badger
environment=ORLY_DATA_DIR="/app/data/ORLY"
priority=15
[program:orly-negentropy]
command=/app/code/orly sync --driver=negentropy
environment=ORLY_SYNC_NEGENTROPY_LISTEN="127.0.0.1:50064",ORLY_SYNC_NEGENTROPY_DB_TYPE="grpc",ORLY_SYNC_NEGENTROPY_DB_SERVER="127.0.0.1:50051"
priority=20
[program:orly]
command=/app/code/orly
environment=ORLY_DB_TYPE="grpc",ORLY_GRPC_SERVER="127.0.0.1:50051",ORLY_NEGENTROPY_ENABLED="true",ORLY_SYNC_TYPE="grpc",ORLY_GRPC_SYNC_NEGENTROPY="127.0.0.1:50064"
priority=25
Note: when running the relay process directly (not via launcher), you must set BOTH ORLY_NEGENTROPY_ENABLED=true AND ORLY_SYNC_TYPE=grpc to use the gRPC negentropy service. Missing ORLY_SYNC_TYPE=grpc causes the relay to silently use the embedded handler instead.
ORLY's NIP-77 implementation is compatible with strfry's sync command:
# Pull events from ORLY into strfry
strfry sync wss://your-orly-relay.com --filter '{"kinds": [0, 1, 3]}' --dir down
# Push events from strfry to ORLY
strfry sync wss://your-orly-relay.com --filter '{"kinds": [0, 1, 3]}' --dir up
# Bidirectional
strfry sync wss://your-orly-relay.com --dir both
The relay received a NEG-OPEN from a client but no negentropy handler was registered. The only cause is:
`ORLY_NEGENTROPY_ENABLED` is not `true`. The relay skips negentropy init entirely. In launcher mode, this means ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED was not set — the launcher only passes ORLY_NEGENTROPY_ENABLED=true to the relay subprocess when this is enabled.
Note: gRPC connection failures and timeouts no longer cause this. If the gRPC negentropy service is unreachable, the relay automatically falls back to the embedded handler and logs a warning. NIP-77 stays enabled either way.
ORLY_NEGENTROPY_ENABLED is not true. The init function logs "negentropy NIP-77 disabled" and returns. Set it and restart.
The relay tried to connect to the gRPC negentropy service but failed (connection refused or 30s timeout). It fell back to the embedded handler, so NIP-77 still works. However, you're not getting the benefits of the separate negentropy service (process isolation, independent restarts). Check that:
orly sync --driver=negentropy)ORLY_GRPC_SYNC_NEGENTROPY on the relay side must match ORLY_LAUNCHER_SYNC_NEGENTROPY_LISTEN (or ORLY_SYNC_NEGENTROPY_LISTEN) on the service sideORLY_SYNC_TYPE is local (the default). The relay went straight to the embedded handler without attempting gRPC. Set ORLY_SYNC_TYPE=grpc or use orly launcher which sets it automatically.
curl -s -H "Accept: application/nostr+json" wss://peer-relay.comsupported_nips in relay infoORLY_LOG_LEVEL=debugORLY_SYNC_NEGENTROPY_FRAME_SIZE to 2048 or lowerORLY_SYNC_NEGENTROPY_INTERVAL to reduce frequencyClient ──NEG-OPEN──► ┌────────────────────────────┐
Client ◄──NEG-MSG─── │ orly (relay) │
Client ──NEG-MSG───► │ │
Client ◄──EVENT───── │ embedded negentropy handler │
│ ↕ │
│ badger/neo4j DB │
└────────────────────────────────┘
Client ──NEG-OPEN──► ┌──────────┐ gRPC ┌───────────────────┐
Client ◄──NEG-MSG─── │ orly │ ──────► │ orly sync │
Client ──NEG-MSG───► │ (relay) │ ◄────── │ --driver=negentropy│
Client ◄──EVENT───── └──────────┘ └─────────┬──────────┘
│ │
│ gRPC │ gRPC
▼ ▼
┌──────────────────────────────────┐
│ orly db --driver=badger │
└──────────────────────────────────┘