Files
caravel/backend
2026-02-27 20:16:50 -08:00
..
2026-02-27 13:06:02 -08:00
2026-02-25 15:18:43 -08:00
2026-02-25 16:10:24 -08:00
2026-02-25 16:10:24 -08:00
2026-02-27 20:16:50 -08:00
2026-02-25 15:18:43 -08:00

Backend

Rust backend for the Nostr relay hosting platform. This service manages tenants, relays, invoices, and billing, and provisions relays by calling the zooid HTTP API. It authenticates requests using NIP-98.

Tech Stack

  • Rust (Edition 2024)
  • Axum (HTTP server)
  • SQLx + SQLite (persistence)
  • Nostr SDK (NIP-98 verification)

Layout

backend/
  migrations/          # SQL migrations
  src/
    auth.rs            # NIP-98 verification helper
    billing.rs         # Billing loop + invoice generation
    config.rs          # Env-based configuration
    db.rs              # SQLite pool + migrations
    main.rs            # Axum server entrypoint
    models.rs          # Data models
    notifications.rs   # NIP-17 DM sender + relay discovery
    platform.rs        # Startup kind 0/10050 publishing
    provisioning.rs    # Zooid provisioning worker
    repo.rs            # Data access layer

Configuration

Environment variables:

Variable Description Default
DATABASE_URL SQLite database URL sqlite://data/caravel.db
HOST Bind host 127.0.0.1
PORT Bind port 3000
ZOOID_API_URL Zooid API base URL http://127.0.0.1:8032
PLATFORM_SECRET Platform Nostr secret key for NIP-98 auth required
RELAY_DOMAIN Relay base domain for subdomains spaces.coracle.social
NWC_URL Platform NWC URL for invoice generation required for billing
NOSTR_INDEXER_RELAYS Comma-separated relays to fetch kind 10050 DM relays required for notifications
PLATFORM_NAME Platform display name for kind 0 metadata optional
PLATFORM_DESCRIPTION Platform description for kind 0 metadata optional
PLATFORM_PICTURE Platform picture URL for kind 0 metadata optional
PLATFORM_MESSAGING_RELAYS Comma-separated relays published in kind 10050 optional

The database directory is created automatically if it doesnt exist.

Database Schema

Created via migrations/0001_init.sql:

  • tenants
  • relays
  • invoices
  • invoice_items

Running

cd backend
cargo run

Health check:

GET /healthz

NIP-98 Authentication

NIP-98 verification is implemented in auth.rs using the Rust Nostr SDK. It verifies:

  • Authorization header format
  • Event signature and kind
  • URL + HTTP method tags
  • Timestamp validity

This is ready to be used by API routes.

Billing Jobs

The backend runs an in-process billing loop that:

  • Generates monthly invoices (using NWC_URL)
  • Uses the tenants tenant_nwc_url for recurring pull payments (if set)
  • Sends NIP-17 DMs with invoices when recurring is off
  • Sends NIP-17 DMs on successful payment when recurring is on

NIP-17 relay discovery:

  • Uses NOSTR_INDEXER_RELAYS to fetch kind 10050 for each tenant
  • Cached for a short period
  • If no relays are found, no DM is sent

On startup, the backend publishes:

  • Kind 0 metadata (name/description)
  • Kind 10050 relay list for DMs

These are published to the relays listed in NOSTR_INDEXER_RELAYS.

API Routes

Tenant routes (all require NIP-98 auth; pubkey is inferred from the token):

  • GET /tenant — fetch (or create) tenant
  • GET /tenant/relays — list tenant relays
  • POST /tenant/relays — create relay
  • GET /tenant/relays/:id — get relay
  • PUT /tenant/relays/:id — update relay
  • DELETE /tenant/relays/:id — deactivate relay
  • GET /tenant/invoices — list invoices
  • PUT /tenant/billing — update tenant billing (NWC URL)

Admin routes (all require NIP-98 auth; pubkey must be in PLATFORM_ADMIN_PUBKEYS):

  • GET /admin/tenants — list tenants
  • GET /admin/tenants/:pubkey — tenant detail (includes relays)
  • PUT /admin/tenants/:pubkey — update tenant status
  • GET /admin/relays — list relays
  • GET /admin/relays/:id — get relay
  • PUT /admin/relays/:id — update relay
  • DELETE /admin/relays/:id — deactivate relay