Relay Manager Docs
Modules

Relay Server Agent

Stateless REST abstraction over strfry. MIT, self-hosted, operator-owned.

Relay Server Agent (relay-agent)

License: MIT — github.com/bitmacro/relay-agent
Distribution: npx @bitmacro/relay-agent or docker pull ghcr.io/bitmacro/relay-agent:0.2.0
Port: 7810
State: None — all state lives in Supabase via the Web Server.

Runs on the same server as the relay process. Exposes an authenticated REST API that wraps strfry CLI commands. One container, N relays.


Deployment

# infra/compose/relay-agent.yml
services:
  relay-agent:
    image: ghcr.io/bitmacro/relay-agent:0.2.0
    ports:
      - "7810:7810"
    environment:
      RELAY_INSTANCES: |
        [
          {"id":"public",  "token":"tok_pub",  "strfryConfig":"/etc/strfry-public.yml",  "strfryDb":"/var/lib/strfry/public.lmdb"},
          {"id":"private", "token":"tok_priv", "strfryConfig":"/etc/strfry-private.yml", "strfryDb":"/var/lib/strfry/private.lmdb"},
          {"id":"paid",    "token":"tok_paid", "strfryConfig":"/etc/strfry-paid.yml",    "strfryDb":"/var/lib/strfry/paid.lmdb"}
        ]
      ALLOWED_ORIGINS: "https://relay-panel.bitmacro.io"
    volumes:
      - /etc/strfry:/etc/strfry:ro
      - /var/lib/strfry:/var/lib/strfry
    restart: unless-stopped

npx (development / quick test)

RELAY_INSTANCES='[{"id":"local","token":"dev","strfryConfig":"/etc/strfry.yml","strfryDb":"/var/lib/strfry/db"}]' \
  npx @bitmacro/relay-agent

API Reference (v0.2.0 — multi-relay)

All routes except /health and /:relayId/health require Authorization: Bearer <token>.
relayId matches the id field in RELAY_INSTANCES.

Global

MethodRouteAuthResponse
GET/health{status:"ok", relayIds:["public","private","paid"], version:"0.2.0"}

Per-relay (/:relayId/)

MethodRouteDescription
GET/:relayId/healthHealth for specific relay
GET/:relayId/stats{total_events, db_size_bytes, uptime_seconds, strfry_version}
GET/:relayId/eventsQuery events (NIP-01 filters via query params)
DELETE/:relayId/events/:idDelete event by ID
GET/:relayId/policyWrite policy (whitelist); strips comments and invalid pubkeys
POST/:relayId/policy/allowAdd pubkey to whitelist
POST/:relayId/policy/blockAdd pubkey to blocklist + delete all their events
GET/:relayId/usersUnique pubkeys from kinds 0, 1, 3

v0.1 compatibility

When RELAY_INSTANCES is not set, the agent falls back to v0.1 mode: single relay, single RELAY_AGENT_TOKEN, no path prefix.


Multi-Relay Internals

  • One LMDB mutex per relayId — reduces 503 Resource temporarily unavailable on concurrent strfry access.
  • strfryConfig and strfryDb are per-instance, allowing fully isolated relay DBs on the same host.
  • The agent process spawns strfry commands via:
    spawn('/bin/sh', ['-c', cmd], { stdio: ['ignore', 'pipe', 'pipe'] })
    This avoids TTY/EACCES issues on Ubuntu 24 kernel restriction.

CI/CD

TriggerAction
Push tag v*.*.*publish.yml → npm publish + GHCR multi-arch (amd64 + arm64)
PR to mainci.yml → Vitest (unit + integration; strfry-dependent tests skip if not present)

OIDC provenance (id-token: write) bypasses 2FA on CI publish.


Monitoring

Uptime Kuma: HTTP(s) keyword check on https://relay-agent.bitmacro.io/health
Keyword: "status":"ok"