2024-10-22 19:08:21 -04:00
# [nostream](https://github.com/cameri/nostream)
2022-04-16 23:53:25 +00:00
2022-10-26 16:38:50 -07:00
< p align = "center" >
2022-12-24 15:44:38 -05:00
< img alt = "nostream logo" height = "256px" width = "256px" src = "https://user-images.githubusercontent.com/378886/198158439-86e0345a-adc8-4efe-b0ab-04ff3f74c1b2.jpg" / >
2022-10-26 16:38:50 -07:00
< / p >
2022-10-19 02:37:20 +00:00
< p align = "center" >
2024-10-22 19:08:21 -04:00
< a href = "https://github.com/cameri/nostream/releases" >
2022-12-24 15:44:38 -05:00
< img alt = "GitHub release" src = "https://img.shields.io/github/v/release/Cameri/nostream" >
2022-11-06 12:04:38 -05:00
< / a >
2024-10-22 19:08:21 -04:00
< a href = "https://github.com/cameri/nostream/issues" >
2022-12-24 15:44:38 -05:00
< img alt = "GitHub issues" src = "https://img.shields.io/github/issues/Cameri/nostream?style=plastic" / >
2022-10-18 23:43:13 -04:00
< / a >
2024-10-22 19:08:21 -04:00
< a href = "https://github.com/cameri/nostream/stargazers" >
2022-12-24 15:44:38 -05:00
< img alt = "GitHub stars" src = "https://img.shields.io/github/stars/Cameri/nostream" / >
2022-10-18 23:43:13 -04:00
< / a >
2022-12-24 15:44:38 -05:00
< img alt = "GitHub top language" src = "https://img.shields.io/github/languages/top/Cameri/nostream" >
2024-10-22 19:08:21 -04:00
< a href = "https://github.com/cameri/nostream/network" >
2022-12-24 15:44:38 -05:00
< img alt = "GitHub forks" src = "https://img.shields.io/github/forks/Cameri/nostream" / >
2022-10-18 23:43:13 -04:00
< / a >
2024-10-22 19:08:21 -04:00
< a href = "https://github.com/cameri/nostream/blob/main/LICENSE" >
2022-12-24 15:44:38 -05:00
< img alt = "GitHub license" src = "https://img.shields.io/github/license/Cameri/nostream" / >
2022-10-18 23:43:13 -04:00
< / a >
2022-12-24 15:44:38 -05:00
< a href = 'https://coveralls.io/github/Cameri/nostream?branch=main' >
< img alt = 'Coverage Status' src = 'https://coveralls.io/repos/github/Cameri/nostream/badge.svg?branch=main' / >
2022-10-18 23:43:13 -04:00
< / a >
2022-12-26 01:21:25 -05:00
< a href = 'https://sonarcloud.io/project/overview?id=Cameri_nostr-ts-relay' >
< img alt = 'Sonarcloud quality gate' src = 'https://sonarcloud.io/api/project_badges/measure?project=Cameri_nostr&metric=alert_status' / >
2022-11-17 09:54:41 -05:00
< / a >
2024-10-22 19:08:21 -04:00
< a href = 'https://github.com/cameri/nostream/actions' >
< img alt = 'Build status' src = 'https://github.com/cameri/nostream/actions/workflows/checks.yml/badge.svg?branch=main&event=push' / >
2022-10-18 23:43:13 -04:00
< / a >
2022-10-19 02:37:20 +00:00
< / p >
2022-04-16 23:53:25 +00:00
This is a [nostr ](https://github.com/fiatjaf/nostr ) relay, written in
Typescript.
2022-10-17 04:35:12 +00:00
This implementation is production-ready. See below for supported features.
2024-10-22 19:08:21 -04:00
The project master repository is available on [GitHub ](https://github.com/cameri/nostream ).
2022-04-16 23:53:25 +00:00
2022-12-28 22:14:10 -05:00
[](https://railway.app/new/template/Xfk5F7?referralCode=Kfv2ly)
2022-11-11 15:51:33 +05:30
2022-04-16 23:53:25 +00:00
## Features
NIPs with a relay-specific implementation are listed here.
2022-08-13 06:43:32 +00:00
- [x] NIP-01: Basic protocol flow description
- [x] NIP-02: Contact list and petnames
- [x] NIP-04: Encrypted Direct Message
2022-08-16 04:10:00 +00:00
- [x] NIP-09: Event deletion
2022-08-08 13:04:43 +00:00
- [x] NIP-11: Relay information document
2023-02-20 12:15:45 -05:00
- [x] NIP-11a: Relay Information Document Extensions
2022-08-08 13:04:43 +00:00
- [x] NIP-12: Generic tag queries
2022-09-22 21:47:57 +00:00
- [x] NIP-13: Proof of Work
2022-08-07 07:38:18 +00:00
- [x] NIP-15: End of Stored Events Notice
2022-08-13 06:43:32 +00:00
- [x] NIP-16: Event Treatment
2022-11-15 20:09:52 -05:00
- [x] NIP-20: Command Results
2022-09-22 21:47:57 +00:00
- [x] NIP-22: Event `created_at` Limits
2024-01-12 16:12:04 -05:00
- [ ] NIP-26: Delegated Event Signing (REMOVED)
2022-12-26 01:21:25 -05:00
- [x] NIP-28: Public Chat
2022-10-30 18:17:04 -04:00
- [x] NIP-33: Parameterized Replaceable Events
2023-02-04 14:18:45 -05:00
- [x] NIP-40: Expiration Timestamp
2022-04-16 23:53:25 +00:00
2022-08-07 22:47:59 +00:00
## Requirements
2022-11-15 20:09:52 -05:00
### Standalone setup
2023-01-25 00:13:01 -05:00
- PostgreSQL 14.0
2022-11-15 20:09:52 -05:00
- Redis
2022-10-28 23:21:35 -04:00
- Node v18
2022-08-07 22:47:59 +00:00
- Typescript
2022-10-17 04:35:12 +00:00
2022-11-15 20:09:52 -05:00
### Docker setups
- Docker v20.10
2022-12-30 13:52:58 -06:00
- Docker Compose v2.10
### Local Docker setup
- Docker Desktop v4.2.0 or newer
- [mkcert ](https://github.com/FiloSottile/mkcert )
2022-11-15 20:09:52 -05:00
2022-12-24 12:00:04 -05:00
WARNING: Docker distributions from Snap, Brew or Debian repositories are NOT SUPPORTED and will result in errors.
Install Docker from their [official guide ](https://docs.docker.com/engine/install/ ) ONLY.
2022-12-17 15:19:16 -05:00
## Full Guide
2023-05-16 17:58:30 -07:00
- [Set up a Paid Nostr relay with Nostream and ZEBEDEE ](https://docs.zebedee.io/docs/guides/nostr-relay ) by [André Neves ](https://primal.net/andre ) (CTO & Co-Founder at [ZEBEDEE ](https://zebedee.io/ ))
2023-02-04 21:14:23 -08:00
- [Set up a Nostr relay in under 5 minutes ](https://andreneves.xyz/p/set-up-a-nostr-relay-server-in-under ) by [André Neves ](https://twitter.com/andreneves ) (CTO & Co-Founder at [ZEBEDEE ](https://zebedee.io/ ))
2022-12-17 15:19:16 -05:00
2023-05-16 17:58:30 -07:00
### Accepting Payments
2023-05-15 11:07:28 -04:00
2023-05-19 13:53:50 -04:00
1. Before you begin
- Complete one of the Quick Start guides in this document
- Create a `.env` file
- On `.nostr/settings.yaml` file make the following changes:
- Set `payments.enabled` to `true`
- Set `payments.feeSchedules.admission.enabled` to `true`
- Set `limits.event.pubkey.minBalance` to the minimum balance in msats required to accept events (i.e. `1000000` to require a balance of `1000` sats)
2023-05-23 11:08:16 -04:00
- Choose one of the following payment processors: `zebedee` , `nodeless` , `opennode` , `lnbits` , `lnurl`
2023-05-19 13:53:50 -04:00
2. [ZEBEDEE ](https://zebedee.io )
- Complete the step "Before you begin"
- [Sign up for a ZEBEDEE Developer Dashboard account ](https://dashboard.zebedee.io/signup ), create a new LIVE Project, and get that Project's API Key
- Set `ZEBEDEE_API_KEY` environment variable with the API Key above on your `.env` file
```
ZEBEDEE_API_KEY={YOUR_ZEBEDEE_API_KEY_HERE}
```
- Follow the required steps for all payments processors
- On `.nostr/settings.yaml` file make the following changes:
- `payments.processor` to `zebedee`
- `paymentsProcessors.zebedee.callbackBaseURL` to match your Nostream URL (e.g. `https://{YOUR_DOMAIN_HERE}/callbacks/zebedee` )
- Restart Nostream (`./scripts/stop` followed by `./scripts/start` )
- Read the in-depth guide for more information: [Set Up a Paid Nostr Relay with ZEBEDEE API ](https://docs.zebedee.io/docs/guides/nostr-relay )
2023-05-23 11:08:16 -04:00
3. [Nodeless ](https://nodeless.io/?ref=587f477f-ba1c-4bd3-8986-8302c98f6731 )
2023-05-19 13:53:50 -04:00
- Complete the step "Before you begin"
2023-05-23 11:08:16 -04:00
- [Sign up ](https://nodeless.io/?ref=587f477f-ba1c-4bd3-8986-8302c98f6731 ) for a new account, create a new store and take note of the store ID
2023-05-19 13:53:50 -04:00
- 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_KEY` and `NODELESS_WEBHOOK_SECRET` environment 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.yaml` file make the following changes:
- Set `payments.processor` to `nodeless`
- Set `paymentsProcessors.nodeless.storeId` to your store ID
- Restart Nostream (`./scripts/stop` followed by `./scripts/start` )
2023-05-23 11:08:16 -04:00
4. [OpenNode ](https://www.opennode.com/ )
- 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_KEY` environment variable on your `.env` file
```
OPENNODE_API_KEY={YOUR_OPENNODE_API_KEY}
```
- On your `.nostr/settings.yaml` file make the following changes:
- Set `payments.processor` to `opennode`
- Restart Nostream (`./scripts/stop` followed by `./scripts/start` )
5. [LNBITS ](https://lnbits.com/ )
2023-05-19 20:59:08 +02:00
- Complete the step "Before you begin"
2023-05-23 11:08:16 -04:00
- Create a new wallet on you public LNbits instance
2023-05-19 20:59:08 +02:00
- [Demo ](https://legend.lnbits.com/ ) 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_KEY` environment variable with the Invoice/read key Key above on your `.env` file
```
LNBITS_API_KEY={YOUR_LNBITS_API_KEY_HERE}
```
- On your `.nostr/settings.yaml` file make the following changes:
- Set `payments.processor` to `lnbits`
- set `lnbits.baseURL` to your LNbits instance URL (e.g. `https://{YOUR_LNBITS_DOMAIN_HERE}/` )
- Set `paymentsProcessors.lnbits.callbackBaseURL` to match your Nostream URL (e.g. `https://{YOUR_DOMAIN_HERE}/callbacks/lnbits` )
- Restart Nostream (`./scripts/stop` followed by `./scripts/start` )
2023-05-26 18:36:36 +05:30
6. [Alby ](https://getalby.com/ ) or any LNURL Provider with [LNURL-verify ](https://github.com/lnurl/luds/issues/182 ) support
- Complete the step "Before you begin"
- [Create a new account ](https://getalby.com/user/new ) if you don't have an LNURL
- On your `.nostr/settings.yaml` file make the following changes:
- Set `payments.processor` to `lnurl`
- Set `lnurl.invoiceURL` to your LNURL (e.g. `https://getalby.com/lnurlp/your-username` )
- Restart Nostream (`./scripts/stop` followed by `./scripts/start` )
7. Ensure payments are required for your public key
2023-05-19 13:53:50 -04:00
- 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 ](https://damus.io/key/ )
- Send the following JSON message: `["REQ", "payment-test", {"authors":["your-pubkey-in-hexadecimal"]}]`
- You should get back the few notes you sent earlier
2023-05-15 11:07:28 -04:00
2022-11-15 20:09:52 -05:00
## Quick Start (Docker Compose)
2022-08-07 22:47:59 +00:00
2022-11-06 01:25:36 -04:00
Install Docker following the [official guide ](https://docs.docker.com/engine/install/ ).
You may have to uninstall Docker if you installed it using a different guide.
Clone repository and enter directory:
```
2022-12-24 15:44:38 -05:00
git clone git@github .com:Cameri/nostream.git
cd nostream
2022-11-06 01:25:36 -04:00
```
2023-05-05 22:18:28 +02:00
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
```
2022-12-20 23:05:12 -05:00
Start:
2022-10-17 04:35:12 +00:00
```
2022-12-20 23:05:12 -05:00
./scripts/start
2022-10-28 23:21:35 -04:00
```
2022-12-20 23:05:12 -05:00
or
2022-11-06 19:30:29 -05:00
```
2022-12-20 23:05:12 -05:00
./scripts/start_with_tor
2022-11-06 19:30:29 -05:00
```
2022-12-20 23:05:12 -05:00
Stop the server with:
2022-11-06 19:30:29 -05:00
```
2022-12-20 23:05:12 -05:00
./scripts/stop
2022-11-06 19:30:29 -05:00
```
Print the Tor hostname:
```
2022-12-20 23:05:12 -05:00
./scripts/print_tor_hostname
2022-11-06 19:30:29 -05:00
```
2022-12-23 22:12:00 +00:00
### Running as a Service
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 ](https://www.swissrouting.com/nostr.html#installing-as-a-service ) if you want the server to run again automatically whenever the system is restarted. For example:
```
2022-12-24 15:44:38 -05:00
$ nano /etc/systemd/system/nostream.service
2022-12-23 22:12:00 +00:00
# Note: replace "User=..." with your username, and
2022-12-24 15:44:38 -05:00
# "/home/nostr/nostream" with the directory where you cloned the repo.
2022-12-23 22:12:00 +00:00
[Unit]
Description=Nostr TS Relay
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=5
User=nostr
2022-12-24 15:44:38 -05:00
WorkingDirectory=/home/nostr/nostream
ExecStart=/home/nostr/nostream/scripts/start
ExecStop=/home/nostr/nostream/scripts/stop
2022-12-23 22:12:00 +00:00
[Install]
WantedBy=multi-user.target
```
And then:
```
2022-12-24 15:44:38 -05:00
systemctl enable nostream
systemctl start nostream
2022-12-23 22:12:00 +00:00
```
The logs can be viewed with:
```
2022-12-24 15:44:38 -05:00
journalctl -u nostream
2022-12-23 22:12:00 +00:00
```
2022-11-06 19:30:29 -05:00
2022-10-17 04:35:12 +00:00
## Quick Start (Standalone)
2022-04-16 23:53:25 +00:00
2022-08-07 22:47:59 +00:00
Set the following environment variables:
```
2023-01-31 21:46:27 -06:00
DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test "
2023-02-10 21:48:32 +01:00
DB_USER=postgres
2023-02-20 12:15:45 -05:00
```
2023-01-31 21:46:27 -06:00
or
2023-02-20 12:15:45 -05:00
```
2022-08-07 22:47:59 +00:00
DB_HOST=localhost
DB_PORT=5432
2022-10-17 04:35:12 +00:00
DB_NAME=nostr_ts_relay
2022-08-07 22:47:59 +00:00
DB_USER=postgres
DB_PASSWORD=postgres
2023-02-20 12:15:45 -05:00
```
2023-01-31 21:46:27 -06:00
2023-02-20 12:15:45 -05:00
```
2023-01-31 21:46:27 -06:00
REDIS_URI="redis://default:nostr_ts_relay@localhost:6379 "
2022-11-15 20:09:52 -05:00
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_USER=default
REDIS_PASSWORD=nostr_ts_relay
2022-08-07 22:47:59 +00:00
```
2023-05-05 22:18:28 +02:00
Generate a long random secret and set SECRET:
You may want to use `openssl rand -hex 128` to generate a secret.
2023-02-20 12:15:45 -05:00
```
SECRET=aaabbbccc...dddeeefff
# Secret shortened for brevity
```
2023-05-15 11:07:28 -04:00
### Initializing the database
2023-02-20 12:15:45 -05:00
2022-10-17 04:35:12 +00:00
Create `nostr_ts_relay` database:
2022-08-07 22:47:59 +00:00
```
$ psql -h $DB_HOST -p $DB_PORT -U $DB_USER -W
2022-10-17 04:35:12 +00:00
postgres=# create database nostr_ts_relay;
2022-08-07 22:47:59 +00:00
postgres=# quit
```
2022-11-15 20:09:52 -05:00
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
```
2022-11-06 01:25:36 -04:00
Clone repository and enter directory:
```
2022-12-24 15:44:38 -05:00
git clone git@github .com:Cameri/nostream.git
cd nostream
2022-11-06 01:25:36 -04:00
```
2022-08-07 07:38:18 +00:00
Install dependencies:
```
2022-10-17 04:35:12 +00:00
npm install -g knex
2022-08-07 07:38:18 +00:00
npm install
```
2022-10-28 23:21:35 -04:00
Run migrations (at least once and after pulling new changes):
2022-08-07 22:47:59 +00:00
```
2023-02-17 14:33:09 -07:00
NODE_OPTIONS="-r dotenv/config" npm run db:migrate
2022-08-07 22:47:59 +00:00
```
2023-02-10 21:48:32 +01:00
Create .nostr folder inside nostream project folder and copy over the settings file:
2022-10-17 04:35:12 +00:00
```
2023-01-18 15:38:13 -08:00
mkdir .nostr
2023-02-10 21:48:32 +01:00
cp resources/default-settings.yaml .nostr/settings.yaml
2022-10-17 04:35:12 +00:00
```
2022-08-07 07:38:18 +00:00
To start in development mode:
```
npm run dev
```
2022-04-16 23:53:25 +00:00
2022-10-17 04:35:12 +00:00
Or, start in production mode:
```
npm run start
```
2022-10-28 23:21:35 -04:00
To clean up the build, coverage and test reports run:
```
npm run clean
```
2023-02-20 12:15:45 -05:00
## Development Quick Start (Docker Compose)
Install Docker Desktop following the [official guide ](https://docs.docker.com/desktop/ ).
You may have to uninstall Docker on your machine if you installed it using a different guide.
Clone repository and enter directory:
```
git clone git@github .com: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.
2022-10-28 23:21:35 -04:00
## Tests
### Unit tests
2022-11-06 01:25:36 -04:00
Open a terminal and change to the project's directory:
```
2022-12-24 15:44:38 -05:00
cd /path/to/nostream
2022-11-06 01:25:36 -04:00
```
2022-10-28 23:21:35 -04:00
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
```
### Integration tests (Docker Compose)
2022-11-06 01:25:36 -04:00
Open a terminal and change to the project's directory:
```
2022-12-24 15:44:38 -05:00
cd /path/to/nostream
2022-11-06 01:25:36 -04:00
```
2022-10-28 23:21:35 -04:00
Run integration tests with:
```
npm run docker:test:integration
```
And to get integration test coverage run:
```
npm run docker:cover:integration
```
### Integration tests (Standalone)
2022-11-06 01:25:36 -04:00
Open a terminal and change to the project's directory:
```
2022-12-24 15:44:38 -05:00
cd /path/to/nostream
2022-11-06 01:25:36 -04:00
```
2022-10-28 23:21:35 -04:00
Set the following environment variables:
```
2023-01-31 21:46:27 -06:00
DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test "
or
2022-10-28 23:21:35 -04:00
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
```
2022-04-16 23:53:25 +00:00
## Configuration
2022-10-17 04:35:12 +00:00
You can change the default folder by setting the `NOSTR_CONFIG_DIR` environment variable to a different path.
2023-01-18 15:38:13 -08:00
Run nostream using one of the quick-start guides at least once and `nostream/.nostr/settings.json` will be created.
2022-10-17 04:35:12 +00:00
Any changes made to the settings file will be read on the next start.
2022-04-16 23:53:25 +00:00
2023-01-11 00:59:18 -05:00
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.
2022-10-25 22:17:07 -04:00
2022-10-25 22:25:07 -04:00
See [CONFIGURATION.md ](CONFIGURATION.md ) for a detailed explanation of each environment variable and setting.
2022-04-16 23:53:25 +00:00
## Dev Channel
2023-01-18 15:38:13 -08:00
For development discussions, please use the [Nostr Typescript Relay Dev Group ](https://t.me/nostream_dev ).
2022-10-18 23:43:13 -04:00
2023-01-18 15:38:13 -08:00
For discussions about the protocol, please feel free to use the [Nostr Telegram Group ](https://t.me/nostr_protocol ).
2022-04-16 23:53:25 +00:00
2022-12-23 07:11:42 -05:00
# Author
I'm Cameri on most social networks. You can find me on Nostr by npub1qqqqqqyz0la2jjl752yv8h7wgs3v098mh9nztd4nr6gynaef6uqqt0n47m.
2023-01-18 15:38:13 -08:00
# Contributors (A-Z)
- Anton Livaja
- Juan Angel
- Kevin Smith
- Saransh Sharma
- swissrouting
2023-02-04 21:14:23 -08:00
- André Neves
2023-02-20 12:15:45 -05:00
- Semisol
2023-01-18 15:38:13 -08:00
2022-04-16 23:53:25 +00:00
## License
This project is MIT licensed.