This is a nostr relay, written in Typescript.
This implementation is production-ready. See below for supported features.
The project master repository is available on GitHub.
NIPs with a relay-specific implementation are listed here.
- NIP-01: Basic protocol flow description
- NIP-02: Contact list and petnames
- NIP-04: Encrypted Direct Message
- NIP-09: Event deletion
- NIP-11: Relay information document
- NIP-11a: Relay Information Document Extensions
- NIP-12: Generic tag queries
- NIP-13: Proof of Work
- NIP-15: End of Stored Events Notice
- NIP-16: Event Treatment
- NIP-20: Command Results
- NIP-22: Event
created_atLimits - NIP-26: Delegated Event Signing (REMOVED)
- NIP-28: Public Chat
- NIP-33: Parameterized Replaceable Events
- NIP-40: Expiration Timestamp
- PostgreSQL 14.0
- Redis
- Node v18
- Typescript
- Docker v20.10
- Docker Compose v2.10
- Docker Desktop v4.2.0 or newer
- mkcert
WARNING: Docker distributions from Snap, Brew or Debian repositories are NOT SUPPORTED and will result in errors. Install Docker from their official guide ONLY.
- Set up a Paid Nostr relay with Nostream and ZEBEDEE by André Neves (CTO & Co-Founder at ZEBEDEE)
- Set up a Nostr relay in under 5 minutes by André Neves (CTO & Co-Founder at ZEBEDEE)
Before you begin
- Complete one of the Quick Start guides in this document
- Create a
.envfile - On
.nostr/settings.yamlfile make the following changes:- Set
payments.enabledtotrue - Set
payments.feeSchedules.admission.enabledtotrue - Set
limits.event.pubkey.minBalanceto the minimum balance in msats required to accept events (i.e.1000000to require a balance of1000sats)
- Set
- Choose one of the following payment processors:
zebedee,nodeless,opennode,lnbits,lnurl
- Complete the step "Before you begin"
- Sign up for a ZEBEDEE Developer Dashboard account, create a new LIVE Project, and get that Project's API Key
- Set
ZEBEDEE_API_KEYenvironment variable with the API Key above on your.envfile
ZEBEDEE_API_KEY={YOUR_ZEBEDEE_API_KEY_HERE}- Follow the required steps for all payments processors
- On
.nostr/settings.yamlfile make the following changes:payments.processortozebedeepaymentsProcessors.zebedee.callbackBaseURLto match your Nostream URL (e.g.https://{YOUR_DOMAIN_HERE}/callbacks/zebedee)
- Restart Nostream (
./scripts/stopfollowed by./scripts/start) - Read the in-depth guide for more information: Set Up a Paid Nostr Relay with ZEBEDEE API
- Complete the step "Before you begin"
- Sign up for a new account, create a new store and take note of the store ID
- Go to Profile > API Tokens and generate a new key and take note of it
- Create a store webhook with your Nodeless callback URL (e.g.
https://{YOUR_DOMAIN_HERE}/callbacks/nodeless) and make sure to enable all of the events. Grab the generated store webhook secret - Set
NODELESS_API_KEYandNODELESS_WEBHOOK_SECRETenvironment variables with generated API key and webhook secret, respectively
NODELESS_API_KEY={YOUR_NODELESS_API_KEY} NODELESS_WEBHOOK_SECRET={YOUR_NODELESS_WEBHOOK_SECRET}- On your
.nostr/settings.yamlfile make the following changes:- Set
payments.processortonodeless - Set
paymentsProcessors.nodeless.storeIdto your store ID
- Set
- Restart Nostream (
./scripts/stopfollowed by./scripts/start)
Complete the step "Before you begin"
Sign up for a new account and get verified
Go to Developers > Integrations and setup two-factor authentication
Create a new API Key with Invoices permission
Set
OPENNODE_API_KEYenvironment variable on your.envfileOPENNODE_API_KEY={YOUR_OPENNODE_API_KEY}On your
.nostr/settings.yamlfile make the following changes:- Set
payments.processortoopennode
- Set
Restart Nostream (
./scripts/stopfollowed by./scripts/start)
Complete the step "Before you begin"
Create a new wallet on you public LNbits instance
- Demo server must not be used for production
- Your instance must be accessible from the internet and have a valid SSL/TLS certificate
Get wallet Invoice/read key (in Api docs section of your wallet)
set
LNBITS_API_KEYenvironment variable with the Invoice/read key Key above on your.envfileLNBITS_API_KEY={YOUR_LNBITS_API_KEY_HERE}On your
.nostr/settings.yamlfile make the following changes:- Set
payments.processortolnbits - set
lnbits.baseURLto your LNbits instance URL (e.g.https://{YOUR_LNBITS_DOMAIN_HERE}/) - Set
paymentsProcessors.lnbits.callbackBaseURLto match your Nostream URL (e.g.https://{YOUR_DOMAIN_HERE}/callbacks/lnbits)
- Set
Restart Nostream (
./scripts/stopfollowed by./scripts/start)
Alby or any LNURL Provider with LNURL-verify support
- Complete the step "Before you begin"
- Create a new account if you don't have an LNURL
- On your
.nostr/settings.yamlfile make the following changes:- Set
payments.processortolnurl - Set
lnurl.invoiceURLto your LNURL (e.g.https://getalby.com/lnurlp/your-username)
- Set
- Restart Nostream (
./scripts/stopfollowed by./scripts/start)
Ensure payments are required for your public key
- Visit https://{YOUR-DOMAIN}/
- You should be presented with a form requesting an admission fee to be paid
- Fill out the form and take the necessary steps to pay the invoice
- Wait until the screen indicates that payment was received
- Add your relay URL to your favorite Nostr client (wss://{YOUR-DOMAIN}) and wait for it to connect
- Send a couple notes to test
- Go to https://websocketking.com/ and connect to your relay (wss://{YOUR_DOMAIN})
- Convert your npub to hexadecimal using a Key Converter
- Send the following JSON message:
["REQ", "payment-test",{"authors":["your-pubkey-in-hexadecimal"]}] - You should get back the few notes you sent earlier
Install Docker following the official guide. You may have to uninstall Docker if you installed it using a different guide.
Clone repository and enter directory:
git clone [email protected]:Cameri/nostream.git cd nostream Generate a secret with: openssl rand -hex 128 Copy the output and paste it into an .env file:
SECRET=aaabbbccc...dddeeefff # Secret shortened for brevity Start:
./scripts/start or
./scripts/start_with_tor Stop the server with:
./scripts/stop Print the Tor hostname:
./scripts/print_tor_hostname By default this server will run continuously until you stop it with Ctrl+C or until the system restarts.
You can install as a systemd service if you want the server to run again automatically whenever the system is restarted. For example:
$ nano /etc/systemd/system/nostream.service # Note: replace "User=..." with your username, and # "/home/nostr/nostream" with the directory where you cloned the repo. [Unit] Description=Nostr TS Relay After=network.target StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=5 User=nostr WorkingDirectory=/home/nostr/nostream ExecStart=/home/nostr/nostream/scripts/start ExecStop=/home/nostr/nostream/scripts/stop [Install] WantedBy=multi-user.target And then:
systemctl enable nostream systemctl start nostream The logs can be viewed with:
journalctl -u nostream Set the following environment variables:
DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test" DB_USER=postgres or
DB_HOST=localhost DB_PORT=5432 DB_NAME=nostr_ts_relay DB_USER=postgres DB_PASSWORD=postgres REDIS_URI="redis://default:nostr_ts_relay@localhost:6379" REDIS_HOST=localhost REDIS_PORT=6379 REDIS_USER=default REDIS_PASSWORD=nostr_ts_relay Generate a long random secret and set SECRET: You may want to use openssl rand -hex 128 to generate a secret.
SECRET=aaabbbccc...dddeeefff # Secret shortened for brevity Create nostr_ts_relay database:
$ psql -h $DB_HOST -p $DB_PORT -U $DB_USER -W postgres=# create database nostr_ts_relay; postgres=# quit Start Redis and use redis-cli to set the default password and verify:
$ redis-cli 127.0.0.1:6379> CONFIG SET requirepass "nostr_ts_relay" OK 127.0.0.1:6379> AUTH nostr_ts_relay Ok Clone repository and enter directory:
git clone [email protected]:Cameri/nostream.git cd nostream Install dependencies:
npm install -g knex npm install Run migrations (at least once and after pulling new changes):
NODE_OPTIONS="-r dotenv/config" npm run db:migrate Create .nostr folder inside nostream project folder and copy over the settings file:
mkdir .nostr cp resources/default-settings.yaml .nostr/settings.yaml To start in development mode:
npm run dev Or, start in production mode:
npm run start To clean up the build, coverage and test reports run:
npm run clean Install Docker Desktop following the official guide. You may have to uninstall Docker on your machine if you installed it using a different guide.
Clone repository and enter directory:
git clone [email protected]:Cameri/nostream.git cd nostream Start:
./scripts/start_local This will run in the foreground of the terminal until you stop it with Ctrl+C.
Open a terminal and change to the project's directory:
cd /path/to/nostream Run unit tests with:
npm run test:unit Or, run unit tests in watch mode:
npm run test:unit:watch To get unit test coverage run:
npm run cover:unit To see the unit tests report open .test-reports/unit/index.html with a browser:
open .test-reports/unit/index.html To see the unit tests coverage report open .coverage/unit/lcov-report/index.html with a browser:
open .coverage/unit/lcov-report/index.html Open a terminal and change to the project's directory:
cd /path/to/nostream Run integration tests with:
npm run docker:test:integration And to get integration test coverage run:
npm run docker:cover:integration Open a terminal and change to the project's directory:
cd /path/to/nostream Set the following environment variables:
DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test" or DB_HOST=localhost DB_PORT=5432 DB_NAME=nostr_ts_relay_test DB_USER=postgres DB_PASSWORD=postgres DB_MIN_POOL_SIZE=1 DB_MAX_POOL_SIZE=2 Then run the integration tests:
npm run test:integration To see the integration tests report open .test-reports/integration/report.html with a browser:
open .test-reports/integration/report.html To get the integration test coverage run:
npm run cover:integration To see the integration test coverage report open .coverage/integration/lcov-report/index.html with a browser.
open .coverage/integration/lcov-report/index.html You can change the default folder by setting the NOSTR_CONFIG_DIR environment variable to a different path.
Run nostream using one of the quick-start guides at least once and nostream/.nostr/settings.json will be created. Any changes made to the settings file will be read on the next start.
Default settings can be found under resources/default-settings.yaml. Feel free to copy it to nostream/.nostr/settings.yaml if you would like to have a settings file before running the relay first.
See CONFIGURATION.md for a detailed explanation of each environment variable and setting.
For development discussions, please use the Nostr Typescript Relay Dev Group.
For discussions about the protocol, please feel free to use the Nostr Telegram Group.
I'm Cameri on most social networks. You can find me on Nostr by npub1qqqqqqyz0la2jjl752yv8h7wgs3v098mh9nztd4nr6gynaef6uqqt0n47m.
- Anton Livaja
- Juan Angel
- Kevin Smith
- Saransh Sharma
- swissrouting
- André Neves
- Semisol
This project is MIT licensed.
