This is a multi-tenant relay based on Khatru which implements a range of access controls. It's designed to be used with Flotilla as a community relay (complete with NIP 29 support), but it can also be used outside of a community context.
A single zooid instance can run any number of "virtual" relays. The config directory can contain any number of configuration files, each of which represents a single virtual relay.
Zooid supports a few environment variables, which configure shared resources like the web server or sqlite database.
PORT- the port the server will listen on for all requests. Defaults to3334.CONFIG- where to store relay configuration files. Defaults to./config.MEDIA- where to store blossom media files. Defaults to./media.DATA- where to store databse files. Defaults to./data.API_HOST- the hostname on which to expose the management API. If not set, the API is disabled.API_WHITELIST- a comma-separated list of nostr hex pubkeys authorized to use the management API. Required whenAPI_HOSTis set.
Configuration files are written using toml. Top level configuration options are required:
host- a hostname to serve this relay on.schema- a string that identifies this relay. This cannot be changed, and must be usable as a sqlite identifier.secret- the nostr secret key of the relay. Will be used to populate the relay's NIP 11selffield and sign generated events.
Contains information for populating the relay's nip11 document.
name- the name of your relay.icon- an icon for your relay.pubkey- the public key of the relay owner. Does not affect access controls.description- your relay's description.
Contains policy and access related configuration.
public_join- whether to allow non-members to join the relay without an invite code. Defaults tofalse.strip_signatures- whether to remove signatures when serving events to non-admins. This requires clients/users to trust the relay to properly authenticate signatures. Be cautious about using this; a malicious relay will be able to execute all kinds of attacks, including potentially serving events unrelated to a community use case.
Configures NIP 29 support.
enabled- whether NIP 29 is enabled.
Configures NIP 86 support.
enabled- whether NIP 86 is enabled.
Configures blossom support.
enabled- whether blossom is enabled.
Configures NIP 9a push support.
enabled- whether push is enabled.
Defines roles that can be assigned to different users and attendant privileges. Each role is defined by a [roles.{role_name}] header and has the following options:
pubkeys- a list of nostr pubkeys this role is assigned to.can_invite- a boolean indicating whether this role can invite new members to the relay by requesting akind 28935claim. Defaults tofalse. See access requests for more details.can_manage- a boolean indicating whether this role can use NIP 86 relay management and administer NIP 29 groups. Defaults tofalse.
A special [roles.member] heading may be used to configure policies for all relay users (that is, pubkeys assigned to other roles, or who have redeemed an invite code).
Livekit is an open source WebSockets toolkit for audio and video calls. Configuring a livekit server allows clients to start audio and video calls.
server_url- the URL to your Livekit server.api_key- a key identifying this relay, assigned by the Livekit server.api_secret- a secret key authenticating this relay, assigned by the Livekit server.
The below config file might be saved as ./config/my-relay.example.com in order to route requests from wss://my-relay.example.com to this virtual relay.
host = "my-relay.example.com"
schema = "my_relay"
secret = "<hex private key>"
[info]
name = "My relay"
icon = "https://example.com/icon.png"
pubkey = "<hex public key>"
description = "A community relay for my friends"
[policy]
public_join = true
strip_signatures = false
[groups]
enabled = true
[management]
enabled = true
[blossom]
enabled = false
[push]
enabled = false
[roles.member]
can_invite = true
[roles.admin]
pubkeys = ["d9254d9898fd4728f7e2b32b87520221a50f6b8b97d935d7da2de8923988aa6d"]
can_manage = trueWhen API_HOST and API_WHITELIST are configured, a JSON REST API is available for managing virtual relays remotely. All API requests must be authenticated using NIP 98 HTTP AUTH.
The API accepts JSON config objects and stores them as TOML files in the CONFIG directory. Configs are validated for required fields (host, schema, secret) and duplicate checking (schema and host must be unique across all relays).
Endpoints:
POST /relay/{id}- Creates a new virtual relay config. Returns 201 on success, 409 if the id/schema/host already exists, 400 for invalid config.PUT /relay/{id}- Updates an existing virtual relay config. Returns 200 on success, 404 if the id doesn't exist, 409 if the new schema/host conflicts with another relay.PATCH /relay/{id}- Partially updates an existing virtual relay config by recursively merging the provided JSON. Returns 200 on success, 404 if the id doesn't exist, 409 if the new schema/host conflicts, 400 for invalid config. Usenullvalues to remove fields.DELETE /relay/{id}- Deletes a virtual relay config. Returns 200 on success, 404 if the id doesn't exist.
After running just build, a number of scripts will be available:
./bin/exportprints JSONL events to stdout for a given virtual relay./bin/importtakes JSONL events on stdin and imports it into the given virtual relay
See justfile for defined commands.
Zooid can be run using an OCI container:
podman run -it \
-p 3334:3334 \
-v ./config:/app/config \
-v ./media:/app/media \
-v ./data:/app/data \
ghcr.io/coracle-social/zooid