nostr-nomad
migrates content from Substack to Nostr relays.
This project is a collaboration between Natalie and Alex.
Supports:
- Short-form content (event
kind:1
; NIP-1) — such as "Tweet"-style messages (no formatting). - WIP: Long-form content (event
kind:30023
; NIP-23) — such as blog posts (with Markdown formatting).
You need Python 3 (version 3.7.x or higher) to compile the project.
All Python dependencies will be automatically installed within the isolated virtual environment env
.
To generate documentation using make docs
, you need to install Texinfo and TeX first:
- Ubuntu/Debian:
sudo apt install texinfo texlive -y
- macOS:
brew install texinfo texlive
- Clone the Repository
First, clone the repository and navigate into the project directory:git clone https://github.com/alx-sch/nostr-nomad nostr-nomad && nostr-nomad
- Provide Substack Export
- Export your Substack data (check here).
- Unzip the archive and remove any posts you don’t want to migrate by deleting the corresponding
.html
files in theposts/
folder. - Place the unzipped export folder into
user_input/export/
. It should contain aposts.csv
file and aposts/
directory with your.html
files.
- Provide Key and Relays
- Add your private key (in hex or nsec format) and the relays you'd like to publish to in the
config.toml
file inuser_input/
. - The private key is used only to sign Nostr events and is never shared.
- If you prefer, you can leave the private key empty (
""
) to generate a random key at runtime. ⚠️ Note: Some relays may require prior authorization and might reject events from unknown keys.
- Run
nostr-nomad
Once everything is set up, you can run the following commands:
make
to build and execute the tool.make docs
to generate the documentation for the project.make clean
to remove compiled files, the virtual environment, and documentation.make clean-all
to also remove the cache (inuser_input/
). Please note that previously published posts are tracked in the cache, preventing duplicates from being sent to the same relay.
- Short-form vs Long-form message
- not all clients support long-form message or preview of all hyperlinks (eg. while most support previewing .jpeg not all support .avif
- some relays don't seem to like 'fast publishing' --> increase delay between posts (see fct
publish_posts
).
Before publishing to public Nostr relays, you might want to test your setup by publishing to a local relay. This allows you to familiarize yourself with how nostr-nomad
works without impacting the broader network.
Below is a setup guide for nostr-rs-relay
, but any other compatible relay should work as well.
-
Install Rust and
cargo
The first step is to install Rust and Cargo (Rust's package manager/build tool). This is needed to compile and run thenostr-rs-relay
project.curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
To make sure the
cargo
tool andrustc
are available in your terminal, run:source $HOME/.cargo/env
You can verify that the installation was successful by checking the versions:
rustc --version cargo --version
-
Install the Protocol Buffers Compiler
The build process fornostr-rs-relay
requires the Protocol Buffers compiler (protoc
). You can install it on Ubuntu with:sudo apt install protobuf-compiler
After installation, confirm that it's available by checking the version:
protoc --version
-
Clone the
nostr-rs-relay
Repository
Now, you’ll clone thenostr-rs-relay
repository to your local machine. This repository contains the source code for the relay server.git clone https://github.com/scsibug/nostr-rs-relay.git nostr-rs-relay && cd nostr-rs-relay
-
Build the Relay Server
Compile the project with thecargo
build tool; this might take some time.cargo build --release
-
Edit Configuration for the Local Relay
In yourconfig.toml
file, change the following fields to set up a local Nostr relay:[network] address = "127.0.0.1" # Or any other appropriate loopback IP, 127.0.0.1 is usually used as localhost. port = 8081 # Use any available port; 8081 is commonly used for development/testing.
Since this is for local testing, we will not enable WSS (secure WebSocket). This avoids the need to generate SSL/TLS certificates or configure encryption — keeping the setup simple and focused. The relay will run at:
ws://127.0.0.1:8081
or simplyws://localhost:8081
(confirm thatlocalhost
points to127.0.0.1
by runningping localhost
). -
Starting the Nostr Relay
Before running the relay, you need to create the database directory first (mkdir db
). The relay will store data such as events and connections here.
Once the database directory is created, you can start the relay by running the following command. This will provide detailed log output:RUST_LOG=debug ./target/release/nostr-rs-relay -c config.toml -d db
The relay should begin running, and you’ll see status updates in the terminal. This confirms that the relay is active and listening for WebSocket connections. Leave the terminal window open to keep the relay running. To interact with the relay, use
nostr-nomad
or other testing methods through a separate terminal window. -
Checking Messages of the Local Nostr Relay
You can use any Nostr client that allows for the inclusion of local relays. For example:For adding the local Nostr relay to Gossip, refer to this helpful blog post.
For a quick setup of the iris client, you can use the standalone desktop release. After installation and signing up:
- Go to Settings -> Network.
- Add
ws://localhost:8081
as a new relay. - Uncheck any other relays you might have subscribed to (to keep the feed focused on the local relay).
- Check the feed (house symbol).
If everything is set up correctly, you should now see events published to your local Nostr relay.
We'd like to thank lash for providing the excellent blog post, which helped us set up local relays and figure out how to send events to them. Lash has also been a mentor throughout this project.