Skip to content

BlockChainCaffe/Nostr-Relay-Setup-Guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 

Repository files navigation

Nostr relay Setup on AWS

Intro

This is a step-by-step, complete guide on how to set up a Nostr relay with Nginx reverse proxy, SSL/TSL with some extra info on how to control and administer it. And no, there is no way you can do that properly in "5 minutes" The steps are based mostly on Amazon AWS EC2 instance but it can be easily applied to any other VPS provider like DigitalOcean, OVH, Linode etc... It will use nostr-rs-relay, a Rust implementation that uses SQLite database.

Requirements

  • AWS account with some cash on it OR
    • any other cloud/VPS provider will do, just change this steps accordingly
  • root privileges
  • a domain you own and can set DNS records
    • in this guide we'll pretend is nostr.domainname.com

Please note: Unless otherwise specified all commands are executed as root.

Ec2 rollout

  • Pick your EC2 instance, for example:
    • t3micro - 2vCPU - 1GiB Ram - 8Gib HD
    • x86
    • Linux Ubuntu
  • If on AWS:
    • generate and store the keypair and store it
    • select/create a security group that allows ssh, http, https
    • launch the instance
    • connect to the instance with ssh (ex:)
ssh -i your-key.pem ubuntu@ec2-X-XXX-XXX-XXX.eu-central-1.compute.amazonaws.com
  • otherwise: (DigitalOcean, OVH...)
    • get means to access the VPS via ssh
    • check with your provider or manually setup the firewall (iptables, ufw...)
    • connect to the instance with ssh

Domain DNS configuration

Go to your Domain/DNS provider and use one of the following options:

  1. create a CNAME record that points to the public DNS of your EC2/VPS or
  2. create a A record entry that points to the public IP of your VPS

Installation Steps

Perform the updates

apt-get update
apt-get upgrade -y

Install rust tools (press 1 when asked)

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source /root/.cargo/env

Check that rust is installed and in your path

rustc --version
cargo --version

Install dependencies

apt-get install certbot build-essential sqlite3 libsqlite3-dev libssl-dev pkg-config nginx git -y
apt-get install net-tools whois -y

Compile nostr-rs

cd /opt
mkdir nostr-data
git clone https://github.com/scsibug/nostr-rs-relay.git
cd nostr-rs-relay
cargo build --release

Compilation can take about 10 minutes or so and produces a binary of about 19mb

Install nostr-rs

install target/release/nostr-rs-relay /usr/local/bin

Clean compilation artifacts

Since the instance you are using has little disk space (mine has 8Gb total) you don't want to waste valuable disk space and save it for nostr messages. Once successfully compiled the compilation artifacts can use up to 2Gb of space.

In order to reclaim that space, once the compiled binaries are installed and moved under /usr/local/bin, you can clean them up with

cargo clean

or (last ditch)

rm -Rf /opt/nostr-rs-relay/target

Uninstall compiler tools

Another surce of wasted space (other 2Gb) is in the /root/.rustup folder.

You want to remove/disinstall that too

rm -Rf /root/.rustup

Nostr Configuration

Create a nostr user to run the service and turn into that user

adduser --disabled-login nostr  # keep pressing enter until it ends 
su - nostr

Download the sample configuration file

cd /opt/nostr-rs-relay
wget https://raw.githubusercontent.com/scsibug/nostr-rs-relay/master/config.toml

Update / change the /opt/nostr-rs-relay/config.toml configuration file with your favourite editor (ex vim o nano) Parameters you might want to change:

  • relay_url : put nostr.domainname.com ( ⚠️ replace with the URL of the domain name you own and that points to the server)
  • name : don't be shy ...
  • description : ... introduce yourself
  • pubkey : your public key
  • contact : your email
  • tracing : ⚠️ leave commented otherwise it trows errors and won't start
  • data_directory : set it to /opt/nostr-data/
  • address : set it to 127.0.0.1 as we will later use nginx as a proxy
  • remote_ip_header : set it to "x-forwarded-for" for logging real client IP addresses

Go back to user root

exit

First Test / Dry-run

Start nostr-relay as a stand alone foreground process and check the logs

RUST_LOG=warn,nostr_rs_relay=info /usr/local/bin/nostr-rs-relay

Check the INFO messages, then check that the DB and other files are there

ls -al /opt/nostr-data
total 112
drwxr-xr-x 2 root root  4096 Jan  9 07:54 ./
drwxr-xr-x 4 root root  4096 Jan  8 19:53 ../
-rw-r--r-- 1 root root 73728 Jan  9 07:55 nostr.db
-rw-r--r-- 1 root root 32768 Jan  9 07:55 nostr.db-shm
-rw-r--r-- 1 root root     0 Jan  9 07:55 nostr.db-wal

Give the permissions to the user nostr

chown -R nostr:nostr /opt/nostr-data

Service Setup

Systemd run script

Create a file /etc/systemd/system/nostr-relay.service with the following content

[Unit]
Description=Nostr Relay
After=network.target

[Service]
Type=simple
User=nostr
WorkingDirectory=/home/nostr
Environment=RUST_LOG=info,nostr_rs_relay=info
ExecStart=/usr/local/bin/nostr-rs-relay
Restart=on-failure

[Install]
WantedBy=multi-user.target

Then enable and start the nostr relay service

systemctl daemon-reload
systemctl enable nostr-relay.service
systemctl start nostr-relay.service

Check that the service is running

systemctl status nostr-relay.service
netstat -tnap | grep nostr
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      37860/nostr-rs-rela 

Setup NginX proxy

Site configuration

Create a nginx configuration file for the proxy and folders for HTTPS/TLS certificate creation

mkdir -p /var/www/nostr/.well-known/acme-challenge/
chown -R 33:33 /var/www/nostr
cd /etc/nginx/sites-available
vim nostr-relay.conf

Paste this as the content of the configuration file. ⚠️ Remember to use the domain you picked

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream websocket {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name nostr.domainname.com;  ## <<=== CHANGE THIS

    location /.well-known/acme-challenge/ {
    root /var/www/nostr;
    allow all;
    }

    location / {
        proxy_pass http://websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

Enable and start the site

ln -s /etc/nginx/sites-available/nostr-relay.conf /etc/nginx/sites-enabled/.
rm -f /etc/nginx/sites-enabled/default
nginx -t # must say "ok... test successful"
nginx -s reload

Run an external check

From another pc/server/vps (your laptop) check that you can connect to nostr through nginx

wget nostr.domainname.com  ## <<=== CHANGE THIS

this should download an index.html file. Check the content

cat index.html 
Please use a Nostr client to connect

Add HTTPS/TLS

Prepare dhparams

Create dhparams 4096 bit prime number(this will require a minute or so)

mkdir /etc/nginx/ssl
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

Let the screen fill up with "....+..." etc

Certificate request

Try certificate request in dry-run mode

cd /var/www/nostr
certbot certonly --webroot -w . -d nostr.domainname.com --dry-run --agree-tos ## <<== Change with your domain

If all goes well do the real certificate request

cd /var/www/nostr
certbot certonly --webroot -w . -d nostr.domainname.com ## <<== Change with your domain

The issued certificates will be found in letsencrypt folder

ll /etc/letsencrypt/live/nostr.domainname.com/
total 12
drwxr-xr-x 2 root root 4096 Jan  9 09:04 ./
drwx------ 3 root root 4096 Jan  9 09:04 ../
-rw-r--r-- 1 root root  692 Jan  9 09:04 README
lrwxrwxrwx 1 root root   48 Jan  9 09:04 cert.pem -> ../../archive/nostr.domainname.com/cert1.pem
lrwxrwxrwx 1 root root   49 Jan  9 09:04 chain.pem -> ../../archive/nostr.domainname.com/chain1.pem
lrwxrwxrwx 1 root root   53 Jan  9 09:04 fullchain.pem -> ../../archive/nostr.domainname.com/fullchain1.pem
lrwxrwxrwx 1 root root   51 Jan  9 09:04 privkey.pem -> ../../archive/nostr.domainname.com/privkey1.pem

Now that you have a valid certificate set, replace the nginx configuration file to use it

cd /etc/nginx/sites-available
vim nostr-relay.conf

Update Nginx site file

Update the content as follows:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream websocket {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name nostr.domainname.com;

   location /.well-known/acme-challenge/ {
        root /var/www/nostr;
        allow all;
    }

    location / {
        return 301 https://nostr.domainname.com;
    }
}

server  {
    listen          443 ssl;
    server_name nostr.domainname.com;

    location / {
        proxy_pass http://websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

    #### SSL ####

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_dhparam ssl/dhparam.pem;
    ssl_ecdh_curve secp384r1;

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy same-origin;
    add_header Feature-Policy "geolocation none;midi none;notifications none;push none;sync-xhr none;microphone none;camera none;magnetometer none;gyroscope none;speaker self;vibrate none;fullscreen self;payment none;";


    ssl_certificate /etc/letsencrypt/live/nostr.domainname.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/nostr.domainname.com/privkey.pem; 
}

NOTE : remember to change all the occurrences of nostr.domainname.com with your domain

Check the new configuration and reload it into nginx

nginx -t
nginx -s reload

Now check that nginx + http + nostr are all working

netstat -tnap | grep 'nginx\|nostr'
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      37860/nostr-rs-rela 
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      8545/nginx: master  
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      8545/nginx: master 

Now check that they are reachable from the outside. Like before go to another pc/server and

wget nostr.domainname.com
--2023-01-09 10:22:05--  http://nostr.domainname.com/
Resolving nostr.domainname.com (nostr.domainname.com)... 3.123.142.158
Connecting to nostr.domainname.com (nostr.domainname.com)|3.123.142.158|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://nostr.domainname.com [following]
--2023-01-09 10:22:05--  https://nostr.domainname.com/
Connecting to nostr.domainname.com (nostr.domainname.com)|3.123.142.158|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 37 [text/plain]
Saving to: ‘index.html.1’

index.html.1                     100%[=============================>]      37  --.-KB/s    in 0s      

NOTE : the test is like the previous one, just this time it tries to connect to http first and get redirected (301) to https, then in https the file is download and its content are the same as before

cat index.html 
Please use a Nostr client to connect

See it at work

This section is mostly sysadmin related but can be very useful when trying to get "why it's not working"

Logs

Nostr relay logs

To keep an eye on what's goin on simply ask the logs

journalctl -f | grep --line-buffered nostr_rs_relay | cut -d' ' -f 10,12-100 

... you might want to set an alias for this. This will show the logs of nostr relay in real time. Press CTRL+C to stop it

Nginx logs

tail -f /var/log/nginx/*.log

You can fire up a tmux session if you don't want to start multiple consoles

Inspect Database

NOTE : ⚠️ carefull with this one as you might damage the db

Try some sqlite commands like:

cd /opt/nostr-data
sqlite3 nostr.db
...
sqlite> .databases
sqlite> .tables
sqlite> select * from event;
sqlite> select count(*) from event;
...

Connect your client

If you made it so far, congrats !!

Now is time to connect your client and see it at work !!

Just connect your client to wss://nostr.domainname.com. Send some messages, see the log get them in (almost) real time and find them in the database.

Pitfalls

  • Do not install rust, cargo etc using apt. Just use rustup

Links

About

A complete step by step setup guide for Nostr relay based on nostr-rs-relay

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published