How to Run Your Own Nostr Relay on Android with Cloudflare Domain
Step-by-step guide to running a personal Nostr relay on Android using Citrine and Cloudflare Tunnels. Learn how to set up secure WebSocket connections, manage relay lists, and maintain a reliable private relay with your custom domain.

Prerequisites
-
Install Citrine on your Android device:
- Visit https://github.com/greenart7c3/Citrine/releases
- Download the latest release using:
- zap.store
- Obtainium
- F-Droid
- Or download the APK directly
- Note: You may need to enable "Install from Unknown Sources" in your Android settings
-
Domain Requirements:
- Purchase a domain if you don't have one
- Transfer your domain to Cloudflare if it's not already there (for free SSL certificates and cloudflared support)
-
Tools to use:
- nak (the nostr army knife):
- Download from https://github.com/fiatjaf/nak/releases
- Installation steps:
- For Linux/macOS:
# Download the appropriate version for your system wget https://github.com/fiatjaf/nak/releases/latest/download/nak-linux-amd64 # for Linux # or wget https://github.com/fiatjaf/nak/releases/latest/download/nak-darwin-amd64 # for macOS # Make it executable chmod +x nak-* # Move to a directory in your PATH sudo mv nak-* /usr/local/bin/nak
- For Windows:
# Download the Windows version curl -L -o nak.exe https://github.com/fiatjaf/nak/releases/latest/download/nak-windows-amd64.exe # Move to a directory in your PATH (e.g., C:\Windows) move nak.exe C:\Windows\nak.exe
- For Linux/macOS:
- Verify installation:
nak --version
- nak (the nostr army knife):
Setting Up Citrine
- Open the Citrine app
- Start the server
- You'll see it running on
ws://127.0.0.1:4869
(local network only) - Go to settings and paste your npub into "Accept events signed by" inbox and press the + button. This prevents others from publishing events to your personal relay.
Installing Required Tools
- Install Termux from Google Play Store
- Open Termux and run:
pkg update && pkg install wget
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb
dpkg -i cloudflared-linux-arm64.deb
Cloudflare Authentication
- Run the authentication command:
cloudflared tunnel login
- Follow the instructions:
- Copy the provided URL to your browser
- Log in to your Cloudflare account
- If the URL expires, copy it again after logging in
Creating the Tunnel
- Create a new tunnel:
cloudflared tunnel create <TUNNEL_NAME>
- Choose any name you prefer for your tunnel
- Copy the tunnel ID after creating the tunnel
- Create and configure the tunnel config:
touch ~/.cloudflared/config.yml
nano ~/.cloudflared/config.yml
- Add this configuration (replace the placeholders with your values):
tunnel: <TUNNEL_UUID>
credentials-file: /data/data/com.termux/files/home/.cloudflared/<TUNNEL_UUID>.json
ingress:
- hostname: nostr.yourdomain.com
service: ws://localhost:4869
- service: http_status:404
- Note: In nano editor:
CTRL+O
and Enter to saveCTRL+X
to exit
- Note: Check the credentials file path in the logs
- Validate your configuration:
cloudflared tunnel validate
- Start the tunnel:
cloudflared tunnel run my-relay
Preventing Android from Killing the Tunnel
Run these commands to maintain tunnel stability:
date && apt install termux-tools && termux-setup-storage && termux-wake-lock
echo "nameserver 1.1.1.1" > $PREFIX/etc/resolv.conf
Tip: You can open multiple Termux sessions by swiping from the left edge of the screen while keeping your tunnel process running.
Updating Your Outbox Model Relays
Once your relay is running and accessible via your domain, you'll want to update your relay list in the Nostr network. This ensures other clients know about your relay and can connect to it.
Decoding npub (Public Key)
Private keys (nsec) and public keys (npub) are encoded in bech32 format, which includes:
- A prefix (like nsec1, npub1 etc.)
- The encoded data
- A checksum
This format makes keys:
- Easy to distinguish
- Hard to copy incorrectly
However, most tools require these keys in hexadecimal (hex) format.
To decode an npub string to its hex format:
nak decode nostr:npub1dejts0qlva8mqzjlrxqkc2tmvs2t7elszky5upxaf3jha9qs9m5q605uc4
Change it with your own npub.
{
"pubkey": "6e64b83c1f674fb00a5f19816c297b6414bf67f015894e04dd4c657e94102ee8"
}
Copy the pubkey value in quotes.
Create a kind 10002 event with your relay list:
- Include your new relay with write permissions
- Include other relays you want to read from and write to, omit 3rd parameter to make it both read and write
Example format:
{
"kind": 10002,
"tags": [
["r", "wss://your-relay-domain.com", "write"],
["r", "wss://eden.nostr.land/"],
["r", "wss://nos.lol/"],
["r", "wss://nostr.bitcoiner.social/"],
["r", "wss://nostr.mom/"],
["r", "wss://relay.primal.net/"],
["r", "wss://nostr.wine/", "read"],
["r", "wss://relay.damus.io/"],
["r", "wss://relay.nostr.band/"],
["r", "wss://relay.snort.social/"]
],
"content": ""
}
Save it to a file called event.json
Note: Add or remove any relays you want. To check your existing 10002 relays:
-
nostr.band is an indexing service, it probably has your relay list.
-
Replace
npub1xxx
in the URL with your own npub -
Click "VIEW JSON" from the menu to see the raw event
-
Or use the
nak
tool if you know the relaysnak req -k 10002 -a <your-pubkey> wss://relay1.com wss://relay2.com
Replace
<your-pubkey>
with your public key in hex format (you can get it usingnak decode <your-npub>
)
- Sign and publish the event:
- Use a Nostr client that supports kind 10002 events
- Or use the
nak
command-line tool:
nak event --sec ncryptsec1... wss://relay1.com wss://relay2.com $(cat event.json)
Important Security Notes:
- Never share your nsec (private key) with anyone
- Consider using NIP-49 encrypted keys for better security
- Never paste your nsec or private key into the terminal. The command will be saved in your shell history, exposing your private key. To clear the command history:
- For bash: use
history -c
- For zsh: use
fc -W
to write history to file, thenfc -p
to read it back - Or manually edit your shell history file (e.g.,
~/.zsh_history
or~/.bash_history
)
- For bash: use
- if you're using
zsh
, usefc -p
to prevent the next command from being saved to history - Or temporarily disable history before running sensitive commands:
unset HISTFILE
nak key encrypt ...
set HISTFILE
How to securely create NIP-49 encypted private key
# Read your private key (input will be hidden)
read -s SECRET
# Read your password (input will be hidden)
read -s PASSWORD
# encrypt command
echo "$SECRET" | nak key encrypt "$PASSWORD"
# copy and paste the ncryptsec1 text from the output
read -s ENCRYPTED
nak key decrypt "$ENCRYPTED"
# clear variables from memory
unset SECRET PASSWORD ENCRYPTED
On a Windows command line, to read from stdin and use the variables in nak
commands, you can use a combination of set /p
to read input and then use those variables in your command. Here's an example:
@echo off
set /p "SECRET=Enter your secret key: "
set /p "PASSWORD=Enter your password: "
echo %SECRET%| nak key encrypt %PASSWORD%
:: Clear the sensitive variables
set "SECRET="
set "PASSWORD="
If your key starts with ncryptsec1
, the nak
tool will securely prompt you for a password when using the --sec
parameter, unless the command is used with a pipe < >
or |
.
nak event --sec ncryptsec1... wss://relay1.com wss://relay2.com $(cat event.json)
- Verify the event was published:
- Check if your relay list is visible on other relays
- Use the
nak
tool to fetch your kind 10002 events:
nak req -k 10002 -a <your-pubkey> wss://relay1.com wss://relay2.com
- Testing your relay:
- Try connecting to your relay using different Nostr clients
- Verify you can both read from and write to your relay
- Check if events are being properly stored and retrieved
- Tip: Use multiple Nostr clients to test different aspects of your relay
Note: If anyone in the community has a more efficient method of doing things like updating outbox relays, please share your insights in the comments. Your expertise would be greatly appreciated!