First, ensure you have access to modify the DNS settings for a domain name you want to use.
Next, ensure you get a virtual machine from your favorite provider. For a private-ish, friends/family relay, get something with 2GB RAM. YMMV. Make sure you choose Ubuntu Server 20.04 or 22.04.
You'll need to log into your DNS provider, and set an A record for your (sub)domain to point to the public IP address of the VM you just created.
Now, log into your VM over SSH
sudo apt update
sudo apt upgrade -y
sudo apt install -y nginx certbot python3-certbot-nginx
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
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
sudo apt update
sudo apt-get install -y docker-ce
docker --version
nginx -V
certbot --version
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
sudo nano /nostr-data/config.toml
sudo docker run -it -d \
-p 127.0.0.1:8080:8080 \
--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
Check installation is successful, you should see "Please use a Nostr client to connect." as the reponse
curl localhost:8080
sudo rm -rf /etc/nginx/sites-available/default
sudo nano /etc/nginx/sites-available/default
sudo systemctl restart nginx
sudo certbot --nginx -d subdomain.mydomain.com
Navigate to https://websocketking.com, enter wss://subdomain.mydomain.com (replace with yours), and click connect. You should see connected.
Navigate to https://subdomain.mydomain.com (replace with yours). It should say "Please use a Nostr client to connect.".
Finally, in your Nostr client, add your newly created relay wss://subdomain.yourdomain.com
You may want to consider hardening your VM against common attack types. Hardning the SSH server, install a firewall like UFW, etc. There are lots of guides out there. If you do decide to install a firewall, keep in mind that we're using ports 22(ssh), 80(http), and 443(https/websocket).
Use the contents below as the contents of the default
nginx setting. Don't forget to change subdomain.mydomain.com to your domain.
server{
server_name subdomain.mydomain.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:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Use the contents below as the contents of the config.toml
nostr-rs-relay configuration file. Be sure to change the following settings: relay_url, name, description fields at a minimum.
# Nostr-rs-relay configuration
[info]
# The advertised URL for the Nostr websocket.
relay_url = "wss://nostr.example.com/"
# Relay information for clients. Put your unique server name here.
name = "nostr-rs-relay"
# Description
description = "A newly created nostr-rs-relay.\n\nCustomize this with your own info."
# Administrative contact pubkey
#pubkey = "0c2d168a4ae8ca58c9f1ab237b5df682599c6c7ab74307ea8b05684b60405d41"
# Administrative contact URI
#contact = "mailto:contact@example.com"
[diagnostics]
# Enable tokio tracing (for use with tokio-console)
#tracing = true
[database]
# Directory for SQLite files. Defaults to the current directory. Can
# also be specified (and overriden) with the "--db dirname" command
# line option.
data_directory = "."
# Use an in-memory database instead of 'nostr.db'.
# Caution; this will not survive a process restart!
#in_memory = false
# Database connection pool settings for subscribers:
# Minimum number of SQLite reader connections
#min_conn = 4
# Maximum number of SQLite reader connections
#max_conn = 128
[network]
# Bind to this network address
address = "0.0.0.0"
# Listen on this port
port = 8080
# If present, read this HTTP header for logging client IP addresses.
# Examples for common proxies, cloudflare:
#remote_ip_header = "x-forwarded-for"
#remote_ip_header = "cf-connecting-ip"
# Websocket ping interval in seconds, defaults to 5 minutes
#ping_interval = 300
[options]
# Reject events that have timestamps greater than this many seconds in
# the future. Recommended to reject anything greater than 30 minutes
# from the current time, but the default is to allow any date.
reject_future_seconds = 1800
[limits]
# Limit events created per second, averaged over one minute. Must be
# an integer. If not set (or set to 0), defaults to unlimited. Note:
# this is for the server as a whole, not per-connection.
# messages_per_sec = 0
# Limit client subscriptions created per second, averaged over one
# minute. Must be an integer. If not set (or set to 0), defaults to
# unlimited.
#subscriptions_per_min = 0
# UNIMPLEMENTED...
# Limit how many concurrent database connections a client can have.
# This prevents a single client from starting too many expensive
# database queries. Must be an integer. If not set (or set to 0),
# defaults to unlimited (subject to subscription limits).
#db_conns_per_client = 0
# Limit blocking threads used for database connections. Defaults to 16.
#max_blocking_threads = 16
# Limit the maximum size of an EVENT message. Defaults to 128 KB.
# Set to 0 for unlimited.
#max_event_bytes = 131072
# Maximum WebSocket message in bytes. Defaults to 128 KB.
#max_ws_message_bytes = 131072
# Maximum WebSocket frame size in bytes. Defaults to 128 KB.
#max_ws_frame_bytes = 131072
# Broadcast buffer size, in number of events. This prevents slow
# readers from consuming memory.
#broadcast_buffer = 16384
# Event persistence buffer size, in number of events. This provides
# backpressure to senders if writes are slow.
#event_persist_buffer = 4096
[authorization]
# Pubkey addresses in this array are whitelisted for event publishing.
# Only valid events by these authors will be accepted, if the variable
# is set.
#pubkey_whitelist = [
# "35d26e4690cbe1a898af61cc3515661eb5fa763b57bd0b42e45099c8b32fd50f",
# "887645fef0ce0c3c1218d2f5d8e6132a19304cdc57cd20281d082f38cfea0072",
#]
[verified_users]
# NIP-05 verification of users. Can be "enabled" to require NIP-05
# metadata for event authors, "passive" to perform validation but
# never block publishing, or "disabled" to do nothing.
#mode = "disabled"
# Domain names that will be prevented from publishing events.
#domain_blacklist = ["wellorder.net"]
# Domain names that are allowed to publish events. If defined, only
# events NIP-05 verified authors at these domains are persisted.
#domain_whitelist = ["example.com"]
# Consider an pubkey "verified" if we have a successful validation
# from the NIP-05 domain within this amount of time. Note, if the
# domain provides a successful response that omits the account,
# verification is immediately revoked.
#verify_expiration = "1 week"
# How long to wait between verification attempts for a specific author.
#verify_update_frequency = "24 hours"
# How many consecutive failed checks before we give up on verifying
# this author.
#max_consecutive_failures = 20
Hi! Thanks for these instructions. On Ubuntu 22.04 curl failing. The nostr-rs-relay port (8080) is open but it's closing it immediately.
The only thing I changed is the id for appuser from 1000 to 2000
Any ideas?