This is a nostr relay, written in Rust. It currently supports the entire relay protocol, and persists data with SQLite.
This is a fork of https://github.com/scsibug/nostr-rs-relay.
The intention is that in the future, this fork will implement Lightning integration for relays to earn micr-payments for posts and facilitate tips between users.
NIPs with a relay-specific implementation are listed here.
- NIP-01: Basic protocol flow description
- Core event model
- Hide old metadata events
- Id/Author prefix search
- NIP-02: Contact List and Petnames
- NIP-03: OpenTimestamps Attestations for Events
- NIP-05: Mapping Nostr keys to DNS-based internet identifiers
- NIP-09: Event Deletion
- NIP-11: Relay Information Document
- NIP-12: Generic Tag Queries
- NIP-15: End of Stored Events Notice
- NIP-16: Event Treatment
- NIP-20: Command Results
- NIP-22: Event
created_at
limits (future-dated events only) - NIP-26: Event Delegation
Using a virtual machine allows you to scale your relay as the amount of data and users increases with time. For a private-ish, friends/family relay, you can start with an x64 based architecture, 2 GB RAM, 30 GB SSD. Make sure you choose Ubuntu Server 20.04 or 22.04. Generate a SSH keypair file, make a note of the name, and save it locally. Ensure that the server is available via SSH (22), HTTP (80), and HTTPS (443).
Login to your DNS provider and set an A record for nostr.example.com
to point to the public IP address of the VM you just created. You can confirm the DNS propogation is successful by running:
$ ping nostr.example.com
123.456.789.100
To connect the the machine, run the following SSH command (on Windows, by opening a command window as an Administrator, and changing directory to where you saved the SSH keypair file) and run:
$ ssh -i <SSH-keypair-filename>.pem <SSH-keypair-name>@<IP-address>
To update your Ubuntu system packages, run the following:
$ sudo apt update
$ sudo apt upgrade -y
To install the required dependencies, such as the nginx
web server, certbot
to generate SSL certificates, python3-certbot-nginx
to serve HTTPS content, apt-transport-https
to allow for the use of repositories accessed via the HTTP Secure protoco, ca-certificates
to be a Certificate Authority on the Ubuntu server, curl
to be able to transmit data using various protocols using the command line, and software-properties-common
to allow us to easily manage distribution and independent software vendor software sources.
$ sudo apt install -y nginx certbot python3-certbot-nginx
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
To check the installation of some of the dependencies, run:
$ nginx -V
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1f 31 Mar 2020
TLS SNI support enabled
$ certbot --version
certbot 1.32.2
As Ubuntu desn't ship with Docker's package repository, we need to add it. Packages repositories and signed with with GPG, we first need to make a directory to store pub keys, then import Dockers.
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
We then need to put the PGP key we downloaded, and put it in the right place by running:
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
To setup Docker, run the following:
$ sudo apt update
$ sudo apt-get install -y docker-ce
To check Docker is installed correctly run:
$ docker --version
Docker version 20.10.22, build 3a2c30b
$ sudo groupadd --gid 1000 appuser
$ sudo useradd --uid 1000 --gid appuser appuser
$ sudo mkdir /nostr-data
$ sudo mkdir /nostr-data/data
$ sudo chown -R 1000:1000 /nostr-data
To make changes to the relay, we need to edit the config.toml
file. This file gives options include rate-limiting, event size limits, and network address settings. To make the changes required, run:
$ sudo nano /nostr-data/config.toml
Within this file, you will want to make changes to the following lines (replacing with your relay details and your public key in HEX format):
name = "nostr-example"
description = "A newly created nostr-rs-relay from nostr.example.com."
pubkey = "971615b70ad9ec896f8d5ba0f2d01652f1dfe5f9ced81ac9469ca7facefad68b"
mode = "passive"
port = 7000
relay_url = "wss://nostr.example.com/"
If, for example if you want to restrict publishing on your relay to NIP-05 verified users of a particular domain locate the [verified_users]
section towards the bottom of the file and make the following changes:
- Change
mode = "passive"
tomode = "enabled"
- Change
#domain_whitelist = ["example.com"]
todomain_whitelist = ["nostr.example.com"]
(note the removal of the#
at the beginning of the line)
Save your changes by pressing Ctrl
+X
, enter Y
, then Return
.
To start the relay, run the following command:
$ sudo docker run -it -d \
-p 127.0.0.1:7000:7000 \
--mount src=/nostr-data/config.toml,target=/usr/src/app/config.toml,type=bind \
--mount src=/nostr-data/data,target=/usr/src/app/db,type=bind \
--restart unless-stopped \
--pull always \
scsibug/nostr-rs-relay:latest
To check for success, run the following command:
curl localhost:7000
You should see Please use a Nostr client to connect
.
To make changes to default Nginx configuration, run:
$ sudo nano /etc/nginx/sites-available/default
And insert the following (replacing nostr.example.com
with your domain):
server{
server_name nostr.example.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:7000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Save your changes by pressing Ctrl
+X
, enter Y
, then Return
.
Now restart Nginx by running:
$ sudo systemctl restart nginx
We can request an SSL certificate from letsencrypt/certbot by running the following (replace nostr.example.com
with yours):
$ sudo certbot --nginx -d nostr.example.com
To test the WebSocket connection, navigate to https://websocketking.com,and enter wss://nostr.example.com
(replacing with your sub-domain details), and click Connect
. You should see you are successfully connected.
To test the HTTPS connection, navigate to https://nostr.example.com
(replacing with your sub-domain details). It should say Please use a Nostr client to connect
.
Finally, in your Nostr client, add your newly created relay wss://nostr.example.com
(replacing with your sub-domain details). Submit some posts :-)
To determine the size of your database, you can do:
$ wc -c /nostr-data/data/nostr.db
392765440 /nostr-data/data/nostr.db
To query the database itself, we need to install SQLite3, by running:
$ sudo apt install sqlite3
You can then query your relay, by running commands such as:
$ sqlite3 /nostr-data/data/nostr.db
$ .tables
event tag user_verification
$ pragma table_info(event);
0|id|INTEGER|0||1
1|event_hash|BLOB|1||0
2|first_seen|INTEGER|1||0
3|created_at|INTEGER|1||0
4|author|BLOB|1||0
5|delegated_by|BLOB|0||0
6|kind|INTEGER|1||0
7|hidden|INTEGER|0||0
8|content|TEXT|1||0
$ pragma table_info(tag);
0|id|INTEGER|0||1
1|event_id|INTEGER|1||0
2|name|TEXT|0||0
3|value|TEXT|0||0
4|value_hex|BLOB|0||0
$ pragma table_info(user_verification);
0|id|INTEGER|0||1
1|metadata_event|INTEGER|1||0
2|name|TEXT|1||0
3|verified_at|INTEGER|0||0
4|failed_at|INTEGER|0||0
5|failure_count|INTEGER|0|0|0
$ select count(*) from event;
5
$ select count(distinct author) from event;
1
$ select count(*) from event where kind = 1;
Press CTRL + Z
and ENTER
to exit SQLite3.
To publicly announce your relay, you can add your relay to the list in Relays.Yaml
and then submit a pull-request:
https://github.com/dskvr/nostr-watch
Once merged, your relay should appear here:
You may want to consider hardening your VM against common attack types by performing actions such as:
- Hardning the SSH server
- Installing a firewall
Note: If you want to make further changes to those you made in Step 7, you'll need to locate the ID of your docker container to restart it and then restart it (replacing the ID with your container ID):
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
45c85585b818 scsibug/nostr-rs-relay:latest "/bin/sh -c './nostr…" 3 days ago Up 3 days 0.0.0.0:7000->7000/tcp, :::7000->7000/tcp, 8080/tcp agitated_darwin
$ sudo docker restart 45c85585b818