fixed initialization and syncing
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
# View logs
|
# View logs
|
||||||
docker-compose logs -f stella-relay
|
docker-compose logs -f orly-relay
|
||||||
|
|
||||||
# Stop the relay
|
# Stop the relay
|
||||||
docker-compose down
|
docker-compose down
|
||||||
@@ -136,7 +136,7 @@ go run ./cmd/stresstest -relay ws://localhost:7777
|
|||||||
```bash
|
```bash
|
||||||
# Container debugging
|
# Container debugging
|
||||||
docker ps | grep relay
|
docker ps | grep relay
|
||||||
docker logs stella-relay
|
docker logs orly-relay
|
||||||
curl -I http://127.0.0.1:7777 # Should return HTTP 426
|
curl -I http://127.0.0.1:7777 # Should return HTTP 426
|
||||||
|
|
||||||
# WebSocket testing
|
# WebSocket testing
|
||||||
@@ -153,7 +153,7 @@ grep ProxyPass /etc/apache2/plesk.conf.d/vhosts/domain.conf
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# View relay logs
|
# View relay logs
|
||||||
docker-compose logs -f stella-relay
|
docker-compose logs -f orly-relay
|
||||||
|
|
||||||
# View nginx logs (if using proxy)
|
# View nginx logs (if using proxy)
|
||||||
docker-compose logs -f nginx
|
docker-compose logs -f nginx
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
# Owner: npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx
|
# Owner: npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx
|
||||||
|
|
||||||
services:
|
services:
|
||||||
stella-relay:
|
orly-relay:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
image: silberengel/next-orly:latest
|
image: silberengel/next-orly:latest
|
||||||
container_name: stella-nostr-relay
|
container_name: orly-nostr-relay
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:7777:7777"
|
- "127.0.0.1:7777:7777"
|
||||||
@@ -22,14 +22,14 @@ services:
|
|||||||
- ORLY_LOG_LEVEL=info
|
- ORLY_LOG_LEVEL=info
|
||||||
- ORLY_DB_LOG_LEVEL=error
|
- ORLY_DB_LOG_LEVEL=error
|
||||||
- ORLY_OWNERS=npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx
|
- ORLY_OWNERS=npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx
|
||||||
- ORLY_ADMINS=npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx
|
- ORLY_ADMINS=npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx,npub1m4ny6hjqzepn4rxknuq94c2gpqzr29ufkkw7ttcxyak7v43n6vvsajc2jl,npub1l5sga6xg72phsz5422ykujprejwud075ggrr3z2hwyrfgr7eylqstegx9z
|
||||||
|
|
||||||
# ACL and Spider Configuration
|
# ACL and Spider Configuration
|
||||||
- ORLY_ACL_MODE=follows
|
- ORLY_ACL_MODE=follows
|
||||||
- ORLY_SPIDER_MODE=follows
|
- ORLY_SPIDER_MODE=follows
|
||||||
|
|
||||||
# Bootstrap relay URLs for initial sync
|
# Bootstrap relay URLs for initial sync
|
||||||
- ORLY_BOOTSTRAP_RELAYS=wss://profiles.nostr1.com,wss://purplepag.es,wss://relay.damus.io,wss://nostr.wine,wss://relay.nostr.band,wss://freelay.sovbit.host
|
- ORLY_BOOTSTRAP_RELAYS=wss://profiles.nostr1.com,wss://purplepag.es,wss://relay.nostr.band,wss://relay.damus.io
|
||||||
|
|
||||||
# Subscription Settings (optional)
|
# Subscription Settings (optional)
|
||||||
- ORLY_SUBSCRIPTION_ENABLED=false
|
- ORLY_SUBSCRIPTION_ENABLED=false
|
||||||
@@ -77,7 +77,7 @@ services:
|
|||||||
- ./nginx/ssl:/etc/nginx/ssl:ro
|
- ./nginx/ssl:/etc/nginx/ssl:ro
|
||||||
- nginx_logs:/var/log/nginx
|
- nginx_logs:/var/log/nginx
|
||||||
depends_on:
|
depends_on:
|
||||||
- stella-relay
|
- orly-relay
|
||||||
profiles:
|
profiles:
|
||||||
- proxy # Only start with: docker-compose --profile proxy up
|
- proxy # Only start with: docker-compose --profile proxy up
|
||||||
|
|
||||||
@@ -93,4 +93,4 @@ volumes:
|
|||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: stella-relay-network
|
name: orly-relay-network
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
PROJECT_DIR="$SCRIPT_DIR"
|
PROJECT_DIR="$SCRIPT_DIR"
|
||||||
|
|
||||||
# Configuration from docker-compose.yml
|
# Configuration from docker-compose.yml
|
||||||
RELAY_SERVICE="stella-relay"
|
RELAY_SERVICE="orly-relay"
|
||||||
CONTAINER_NAME="stella-nostr-relay"
|
CONTAINER_NAME="orly-nostr-relay"
|
||||||
RELAY_URL="ws://127.0.0.1:7777"
|
RELAY_URL="ws://127.0.0.1:7777"
|
||||||
HTTP_URL="http://127.0.0.1:7777"
|
HTTP_URL="http://127.0.0.1:7777"
|
||||||
RELAY_DATA_DIR="/home/madmin/.local/share/orly-relay"
|
RELAY_DATA_DIR="/home/madmin/.local/share/orly-relay"
|
||||||
@@ -21,7 +21,7 @@ cd "$PROJECT_DIR"
|
|||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
"start")
|
"start")
|
||||||
echo "🚀 Starting Stella's Orly Relay..."
|
echo "🚀 Starting Stella's Orly Relay..."
|
||||||
docker compose up -d stella-relay
|
docker compose up -d orly-relay
|
||||||
echo "✅ Relay started!"
|
echo "✅ Relay started!"
|
||||||
;;
|
;;
|
||||||
"stop")
|
"stop")
|
||||||
@@ -31,16 +31,16 @@ case "${1:-}" in
|
|||||||
;;
|
;;
|
||||||
"restart")
|
"restart")
|
||||||
echo "🔄 Restarting Stella's Orly Relay..."
|
echo "🔄 Restarting Stella's Orly Relay..."
|
||||||
docker compose restart stella-relay
|
docker compose restart orly-relay
|
||||||
echo "✅ Relay restarted!"
|
echo "✅ Relay restarted!"
|
||||||
;;
|
;;
|
||||||
"status")
|
"status")
|
||||||
echo "📊 Stella's Orly Relay Status:"
|
echo "📊 Stella's Orly Relay Status:"
|
||||||
docker compose ps stella-relay
|
docker compose ps orly-relay
|
||||||
;;
|
;;
|
||||||
"logs")
|
"logs")
|
||||||
echo "📜 Stella's Orly Relay Logs:"
|
echo "📜 Stella's Orly Relay Logs:"
|
||||||
docker compose logs -f stella-relay
|
docker compose logs -f orly-relay
|
||||||
;;
|
;;
|
||||||
"test")
|
"test")
|
||||||
echo "🧪 Testing relay connection..."
|
echo "🧪 Testing relay connection..."
|
||||||
@@ -77,7 +77,7 @@ case "${1:-}" in
|
|||||||
echo "🐳 Docker Information:"
|
echo "🐳 Docker Information:"
|
||||||
echo " Compose File: $PROJECT_DIR/docker-compose.yml"
|
echo " Compose File: $PROJECT_DIR/docker-compose.yml"
|
||||||
echo " Container Status:"
|
echo " Container Status:"
|
||||||
docker compose ps stella-relay 2>/dev/null || echo " Not running"
|
docker compose ps orly-relay 2>/dev/null || echo " Not running"
|
||||||
echo ""
|
echo ""
|
||||||
echo "💡 Configuration:"
|
echo "💡 Configuration:"
|
||||||
echo " All settings are defined in docker-compose.yml"
|
echo " All settings are defined in docker-compose.yml"
|
||||||
@@ -85,26 +85,26 @@ case "${1:-}" in
|
|||||||
;;
|
;;
|
||||||
"docker-logs")
|
"docker-logs")
|
||||||
echo "🐳 Docker Container Logs:"
|
echo "🐳 Docker Container Logs:"
|
||||||
docker compose logs -f stella-relay 2>/dev/null || echo "❌ Container not found or not running"
|
docker compose logs -f orly-relay 2>/dev/null || echo "❌ Container not found or not running"
|
||||||
;;
|
;;
|
||||||
"docker-status")
|
"docker-status")
|
||||||
echo "🐳 Docker Container Status:"
|
echo "🐳 Docker Container Status:"
|
||||||
docker compose ps stella-relay
|
docker compose ps orly-relay
|
||||||
;;
|
;;
|
||||||
"docker-restart")
|
"docker-restart")
|
||||||
echo "🔄 Restarting Docker Container..."
|
echo "🔄 Restarting Docker Container..."
|
||||||
docker compose restart stella-relay
|
docker compose restart orly-relay
|
||||||
echo "✅ Container restarted!"
|
echo "✅ Container restarted!"
|
||||||
;;
|
;;
|
||||||
"docker-update")
|
"docker-update")
|
||||||
echo "🔄 Updating and restarting Docker Container..."
|
echo "🔄 Updating and restarting Docker Container..."
|
||||||
docker compose pull stella-relay
|
docker compose pull orly-relay
|
||||||
docker compose up -d stella-relay
|
docker compose up -d orly-relay
|
||||||
echo "✅ Container updated and restarted!"
|
echo "✅ Container updated and restarted!"
|
||||||
;;
|
;;
|
||||||
"docker-build")
|
"docker-build")
|
||||||
echo "🔨 Building Docker Container..."
|
echo "🔨 Building Docker Container..."
|
||||||
docker compose build stella-relay
|
docker compose build orly-relay
|
||||||
echo "✅ Container built!"
|
echo "✅ Container built!"
|
||||||
;;
|
;;
|
||||||
"docker-down")
|
"docker-down")
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package acl
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -22,9 +24,9 @@ import (
|
|||||||
"next.orly.dev/pkg/encoders/envelopes/reqenvelope"
|
"next.orly.dev/pkg/encoders/envelopes/reqenvelope"
|
||||||
"next.orly.dev/pkg/encoders/event"
|
"next.orly.dev/pkg/encoders/event"
|
||||||
"next.orly.dev/pkg/encoders/filter"
|
"next.orly.dev/pkg/encoders/filter"
|
||||||
"next.orly.dev/pkg/encoders/hex"
|
|
||||||
"next.orly.dev/pkg/encoders/kind"
|
"next.orly.dev/pkg/encoders/kind"
|
||||||
"next.orly.dev/pkg/encoders/tag"
|
"next.orly.dev/pkg/encoders/tag"
|
||||||
|
"next.orly.dev/pkg/encoders/timestamp"
|
||||||
"next.orly.dev/pkg/protocol/publish"
|
"next.orly.dev/pkg/protocol/publish"
|
||||||
"next.orly.dev/pkg/utils"
|
"next.orly.dev/pkg/utils"
|
||||||
"next.orly.dev/pkg/utils/normalize"
|
"next.orly.dev/pkg/utils/normalize"
|
||||||
@@ -108,7 +110,7 @@ func (f *Follows) Configure(cfg ...any) (err error) {
|
|||||||
for _, v := range ev.Tags.GetAll([]byte("p")) {
|
for _, v := range ev.Tags.GetAll([]byte("p")) {
|
||||||
// log.I.F("adding follow: %s", v.Value())
|
// log.I.F("adding follow: %s", v.Value())
|
||||||
var a []byte
|
var a []byte
|
||||||
if b, e := hex.Dec(string(v.Value())); chk.E(e) {
|
if b, e := hex.DecodeString(string(v.Value())); chk.E(e) {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
a = b
|
a = b
|
||||||
@@ -253,18 +255,45 @@ func (f *Follows) startSubscriptions(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
c, _, err := websocket.Dial(ctx, u, nil)
|
// Create a timeout context for the connection
|
||||||
|
connCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
|
|
||||||
|
// Create proper headers for the WebSocket connection
|
||||||
|
headers := http.Header{}
|
||||||
|
headers.Set("User-Agent", "ORLY-Relay/0.9.2")
|
||||||
|
headers.Set("Origin", "https://orly.dev")
|
||||||
|
|
||||||
|
// Use proper WebSocket dial options
|
||||||
|
dialOptions := &websocket.DialOptions{
|
||||||
|
HTTPHeader: headers,
|
||||||
|
}
|
||||||
|
|
||||||
|
c, _, err := websocket.Dial(connCtx, u, dialOptions)
|
||||||
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.W.F("follows syncer: dial %s failed: %v", u, err)
|
log.W.F("follows syncer: dial %s failed: %v", u, err)
|
||||||
if strings.Contains(
|
|
||||||
err.Error(), "response status code 101 but got 403",
|
// Handle different types of errors
|
||||||
) {
|
if strings.Contains(err.Error(), "response status code 101 but got 403") {
|
||||||
// 403 means the relay is not accepting connections from
|
// 403 means the relay is not accepting connections from us
|
||||||
// us. Forbidden is the meaning, usually used to
|
// Forbidden is the meaning, usually used to indicate either the IP or user is blocked
|
||||||
// indicate either the IP or user is blocked. so stop
|
// But we should still retry after a longer delay
|
||||||
// trying this one.
|
log.W.F("follows syncer: relay %s returned 403, will retry after longer delay", u)
|
||||||
return
|
timer := time.NewTimer(5 * time.Minute) // Wait 5 minutes before retrying 403 errors
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-timer.C:
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if strings.Contains(err.Error(), "timeout") || strings.Contains(err.Error(), "connection refused") {
|
||||||
|
// Network issues, retry with normal backoff
|
||||||
|
log.W.F("follows syncer: network issue with %s, retrying in %v", u, backoff)
|
||||||
|
} else {
|
||||||
|
// Other errors, retry with normal backoff
|
||||||
|
log.W.F("follows syncer: connection error with %s, retrying in %v", u, backoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := time.NewTimer(backoff)
|
timer := time.NewTimer(backoff)
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@@ -277,22 +306,37 @@ func (f *Follows) startSubscriptions(ctx context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
backoff = time.Second
|
backoff = time.Second
|
||||||
// send REQ
|
log.I.F("follows syncer: successfully connected to %s", u)
|
||||||
|
|
||||||
|
// send REQ for kind 3 (follow lists), kind 10002 (relay lists), and all events from follows
|
||||||
ff := &filter.S{}
|
ff := &filter.S{}
|
||||||
f1 := &filter.F{
|
f1 := &filter.F{
|
||||||
Authors: tag.NewFromBytesSlice(authors...),
|
Authors: tag.NewFromBytesSlice(authors...),
|
||||||
Kinds: kind.NewS(kind.New(kind.RelayListMetadata.K)),
|
Kinds: kind.NewS(kind.New(kind.FollowList.K)),
|
||||||
Limit: values.ToUintPointer(0),
|
Limit: values.ToUintPointer(100),
|
||||||
}
|
}
|
||||||
*ff = append(*ff, f1)
|
f2 := &filter.F{
|
||||||
|
Authors: tag.NewFromBytesSlice(authors...),
|
||||||
|
Kinds: kind.NewS(kind.New(kind.RelayListMetadata.K)),
|
||||||
|
Limit: values.ToUintPointer(100),
|
||||||
|
}
|
||||||
|
// Add filter for all events from follows (last 30 days)
|
||||||
|
oneMonthAgo := timestamp.FromUnix(time.Now().Add(-30 * 24 * time.Hour).Unix())
|
||||||
|
f3 := &filter.F{
|
||||||
|
Authors: tag.NewFromBytesSlice(authors...),
|
||||||
|
Since: oneMonthAgo,
|
||||||
|
Limit: values.ToUintPointer(1000),
|
||||||
|
}
|
||||||
|
*ff = append(*ff, f1, f2, f3)
|
||||||
req := reqenvelope.NewFrom([]byte("follows-sync"), ff)
|
req := reqenvelope.NewFrom([]byte("follows-sync"), ff)
|
||||||
if err = c.Write(
|
if err = c.Write(
|
||||||
ctx, websocket.MessageText, req.Marshal(nil),
|
ctx, websocket.MessageText, req.Marshal(nil),
|
||||||
); chk.E(err) {
|
); chk.E(err) {
|
||||||
|
log.W.F("follows syncer: failed to send REQ to %s: %v", u, err)
|
||||||
_ = c.Close(websocket.StatusInternalError, "write failed")
|
_ = c.Close(websocket.StatusInternalError, "write failed")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.T.F("sent REQ to %s for follows subscription", u)
|
log.I.F("follows syncer: sent REQ to %s for kind 3, 10002, and all events (last 30 days) from followed users", u)
|
||||||
// read loop
|
// read loop
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -320,6 +364,23 @@ func (f *Follows) startSubscriptions(ctx context.Context) {
|
|||||||
if ok, err := res.Event.Verify(); chk.T(err) || !ok {
|
if ok, err := res.Event.Verify(); chk.T(err) || !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process events based on kind
|
||||||
|
switch res.Event.Kind {
|
||||||
|
case kind.FollowList.K:
|
||||||
|
log.I.F("follows syncer: received kind 3 (follow list) event from %s on relay %s",
|
||||||
|
hex.EncodeToString(res.Event.Pubkey), u)
|
||||||
|
// Extract followed pubkeys from 'p' tags in kind 3 events
|
||||||
|
f.extractFollowedPubkeys(res.Event)
|
||||||
|
case kind.RelayListMetadata.K:
|
||||||
|
log.I.F("follows syncer: received kind 10002 (relay list) event from %s on relay %s",
|
||||||
|
hex.EncodeToString(res.Event.Pubkey), u)
|
||||||
|
default:
|
||||||
|
// Log all other events from followed users
|
||||||
|
log.I.F("follows syncer: received kind %d event from %s on relay %s",
|
||||||
|
res.Event.Kind, hex.EncodeToString(res.Event.Pubkey), u)
|
||||||
|
}
|
||||||
|
|
||||||
if _, _, err = f.D.SaveEvent(
|
if _, _, err = f.D.SaveEvent(
|
||||||
ctx, res.Event,
|
ctx, res.Event,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@@ -397,6 +458,20 @@ func (f *Follows) GetFollowedPubkeys() [][]byte {
|
|||||||
return followedPubkeys
|
return followedPubkeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractFollowedPubkeys extracts followed pubkeys from 'p' tags in kind 3 events
|
||||||
|
func (f *Follows) extractFollowedPubkeys(event *event.E) {
|
||||||
|
if event.Kind != kind.FollowList.K {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract all 'p' tags (followed pubkeys) from the kind 3 event
|
||||||
|
for _, tag := range event.Tags.GetAll([]byte("p")) {
|
||||||
|
if len(tag.Value()) == 32 { // Valid pubkey length
|
||||||
|
f.AddFollow(tag.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AddFollow appends a pubkey to the in-memory follows list if not already present
|
// AddFollow appends a pubkey to the in-memory follows list if not already present
|
||||||
// and signals the syncer to refresh subscriptions.
|
// and signals the syncer to refresh subscriptions.
|
||||||
func (f *Follows) AddFollow(pub []byte) {
|
func (f *Follows) AddFollow(pub []byte) {
|
||||||
@@ -413,6 +488,7 @@ func (f *Follows) AddFollow(pub []byte) {
|
|||||||
b := make([]byte, len(pub))
|
b := make([]byte, len(pub))
|
||||||
copy(b, pub)
|
copy(b, pub)
|
||||||
f.follows = append(f.follows, b)
|
f.follows = append(f.follows, b)
|
||||||
|
log.I.F("follows syncer: added new followed pubkey: %s", hex.EncodeToString(pub))
|
||||||
// notify syncer if initialized
|
// notify syncer if initialized
|
||||||
if f.updated != nil {
|
if f.updated != nil {
|
||||||
select {
|
select {
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ Group=madmin
|
|||||||
WorkingDirectory=/home/madmin/Projects/GitCitadel/next.orly.dev
|
WorkingDirectory=/home/madmin/Projects/GitCitadel/next.orly.dev
|
||||||
|
|
||||||
# Start the relay using docker compose
|
# Start the relay using docker compose
|
||||||
ExecStart=/usr/bin/docker compose up -d stella-relay
|
ExecStart=/usr/bin/docker compose up -d orly-relay
|
||||||
|
|
||||||
# Stop the relay
|
# Stop the relay
|
||||||
ExecStop=/usr/bin/docker compose down
|
ExecStop=/usr/bin/docker compose down
|
||||||
|
|
||||||
# Reload configuration (restart containers)
|
# Reload configuration (restart containers)
|
||||||
ExecReload=/usr/bin/docker compose restart stella-relay
|
ExecReload=/usr/bin/docker compose restart orly-relay
|
||||||
|
|
||||||
# Security settings
|
# Security settings
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
|
|||||||
Reference in New Issue
Block a user