跳至主要內容
高級

中繼器架設

學習如何架設和運營自己的 Nostr 中繼器,包括軟體選擇、配置和維護。

25 分鐘

為什麼架設中繼器?

架設自己的 Nostr 中繼器可以提供數據主權、增強隱私、 為社群提供服務,或作為備份。雖然使用公共中繼器足夠日常使用, 但自有中繼器給予你完全的控制權。

優點

  • • 數據完全控制
  • • 增強隱私保護
  • • 自訂政策規則
  • • 貢獻網路基礎設施
  • • 可能的營收來源

考量

  • • 需要伺服器資源
  • • 需要維護時間
  • • 儲存空間成本
  • • 頻寬使用
  • • 需要技術知識

中繼器軟體選擇

軟體 語言 特點
strfry C++ 高效能、低資源、LMDB 儲存
nostr-rs-relay Rust 穩定可靠、SQLite/PostgreSQL
nostream TypeScript 功能豐富、PostgreSQL
khatru Go 模組化、易於擴展
relay Go 簡單、可嵌入

快速開始:strfry

# 安裝依賴 (Ubuntu/Debian)
sudo apt update
sudo apt install -y git build-essential liblmdb-dev libflatbuffers-dev \
  libsecp256k1-dev libzstd-dev libssl-dev zlib1g-dev

# 克隆並編譯
git clone https://github.com/hoytech/strfry.git
cd strfry
git submodule update --init
make setup-golpe
make -j4

# 創建配置
cp strfry.conf /etc/strfry.conf

# 運行
./strfry relay

strfry 配置

# /etc/strfry.conf

db = "./strfry-db/"

relay {
    bind = "127.0.0.1"
    port = 7777

    info {
        name = "My Nostr Relay"
        description = "A personal Nostr relay"
        contact = "[email protected]"
        pubkey = "你的公鑰"
    }

    maxWebsocketPayloadSize = 131072
    autoPingInterval = 55
    enableTcpKeepalive = true
}

events {
    maxEventSize = 65536
    rejectEventsNewerThanSeconds = 900
    rejectEventsOlderThanSeconds = 94608000
}

negentropy {
    enabled = true
}

快速開始:nostr-rs-relay

# 安裝 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 克隆並編譯
git clone https://github.com/scsibug/nostr-rs-relay.git
cd nostr-rs-relay
cargo build --release

# 創建配置
cp config.toml.sample config.toml

# 運行
./target/release/nostr-rs-relay

nostr-rs-relay 配置

# config.toml

[info]
relay_url = "wss://relay.example.com"
name = "My Relay"
description = "A Nostr relay"
pubkey = "你的公鑰"
contact = "[email protected]"

[database]
data_directory = "./db"

[network]
port = 8080
address = "127.0.0.1"

[limits]
messages_per_sec = 3
max_event_bytes = 131072
max_ws_message_bytes = 131072
max_ws_frame_bytes = 131072

[authorization]
# 開放所有人或設定白名單
pubkey_whitelist = []

[verified_users]
# 只接受有 NIP-05 驗證的用戶
verify_expiration = 3600
mode = "passive"

反向代理設定

Nginx 配置

# /etc/nginx/sites-available/nostr-relay

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream nostr_relay {
    server 127.0.0.1:7777;
}

server {
    listen 443 ssl http2;
    server_name relay.example.com;

    ssl_certificate /etc/letsencrypt/live/relay.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/relay.example.com/privkey.pem;

    location / {
        proxy_pass http://nostr_relay;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket 超時
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    # NIP-11 中繼器資訊
    location = / {
        if ($http_accept ~* "application/nostr\+json") {
            proxy_pass http://nostr_relay;
        }
        proxy_pass http://nostr_relay;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

Caddy 配置

# Caddyfile

relay.example.com {
    reverse_proxy localhost:7777
}

Systemd 服務

# /etc/systemd/system/nostr-relay.service

[Unit]
Description=Nostr Relay
After=network.target

[Service]
Type=simple
User=nostr
Group=nostr
WorkingDirectory=/opt/strfry
ExecStart=/opt/strfry/strfry relay
Restart=always
RestartSec=5

# 安全設定
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/strfry/strfry-db

[Install]
WantedBy=multi-user.target

# 啟用服務
sudo systemctl enable nostr-relay
sudo systemctl start nostr-relay
sudo systemctl status nostr-relay

Docker 部署

# docker-compose.yml

version: '3'
services:
  relay:
    image: scsibug/nostr-rs-relay:latest
    volumes:
      - ./config.toml:/usr/src/app/config.toml
      - ./data:/usr/src/app/db
    ports:
      - "8080:8080"
    restart: unless-stopped

  # 可選:添加 Caddy 作為反向代理
  caddy:
    image: caddy:latest
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    ports:
      - "80:80"
      - "443:443"
    restart: unless-stopped

volumes:
  caddy_data:

政策設定

常見政策類型:

1. 開放中繼器(預設)
   - 接受所有有效事件
   - 可能需要處理垃圾訊息

2. 白名單
   # nostr-rs-relay
   [authorization]
   pubkey_whitelist = [
     "公鑰1",
     "公鑰2"
   ]

3. 付費中繼器
   - 整合 NIP-42 認證
   - 整合閃電網路支付
   - 需要額外開發

4. NIP-05 驗證要求
   [verified_users]
   mode = "passive"  # 或 "active"

5. 工作量證明要求
   # 要求事件包含 NIP-13 PoW
   [limits]
   min_pow_difficulty = 16

strfry 寫入政策(插件):
# write-policy.lua
function filter(event)
    -- 只接受特定 kind
    if event.kind ~= 1 then
        return "blocked: only kind 1 allowed"
    end
    return nil  -- 接受
end

監控與維護

監控項目:

1. 日誌監控
   journalctl -u nostr-relay -f

2. 連接數
   ss -tnp | grep <port> | wc -l

3. 磁碟使用
   du -sh /path/to/db

4. 資源使用
   htop / top

5. 健康檢查
   curl -I https://relay.example.com

維護任務:

1. 定期備份
   - 資料庫檔案
   - 配置檔案

2. 事件清理
   - 刪除舊的臨時事件
   - 清理垃圾事件

3. 更新軟體
   git pull
   make / cargo build --release

4. 監控儲存空間
   - 設定告警閾值
   - 自動清理策略

資源需求

個人使用

  • • CPU: 1 核心
  • • RAM: 512MB+
  • • 儲存: 5GB+
  • • 費用: ~$5/月

小型社群

  • • CPU: 2 核心
  • • RAM: 2GB+
  • • 儲存: 50GB+
  • • 費用: ~$15/月

公共中繼器

  • • CPU: 4+ 核心
  • • RAM: 8GB+
  • • 儲存: 500GB+ SSD
  • • 費用: ~$50+/月

常見問題

WebSocket 連接被斷開?

檢查 Nginx/Caddy 的 WebSocket 超時設定。 確保 proxy_read_timeout 足夠長。

NIP-11 資訊不顯示?

確保反向代理正確處理 Accept: application/nostr+json 請求。 測試: curl -H "Accept: application/nostr+json" https://relay.example.com

儲存空間增長太快?

考慮限制事件保留時間、只接受特定 kind、 或要求 NIP-05 驗證來減少垃圾事件。

下一步: 學習 客戶端開發 來創建你自己的 Nostr 應用。

已複製連結
已複製到剪貼簿