Own Your Outbox: Running Haven as Your Personal Nostr Relay

npub1klkk3vrzme455yh9rl2jshq7rc8dpegj3ndf82c3ks2sk40dxt7qulx3vt
hex
4907af08add071d6117fa278367987145eb013ecfd883497f5286b161056ee27nevent
nevent1qqsyjpa0pzkaquwkz9l6y7pk0xr3gh4sz0k0mzp5jl6js6ckzptwufcprpmhxue69uhhyetvv9ujuem4d36kwatvw5hx6mm9qgst0mtgkp3du662ztj3l4fgts0purksu5fgek5n4vgmg9gt2hkn9lq84npqtnaddr
naddr1qqgrjef4x43kxd3sx9jrywf4x4skzqgcwaehxw309aex2mrp0yhxwatvw4nh2mr49ekk7egzyzm7669svt0xkjsju50a22zurc0qa589z2xd4yatzx6p2z64a5e0cqcyqqq823cnfh95cKind-30023 (Article)
Nostr promises censorship resistance through decentralization. Your identity lives in a keypair you control. Your notes carry cryptographic signatures no relay can forge. You choose which relays to use.
But there's a gap between the promise and the implementation. If you rely on third-party relays, you depend on their uptime, their retention policies, their willingness to serve your content. They can go offline, get banned, or decide your notes are no longer worth storing. Your query patterns are visible to every relay you connect to. Your data persists only as long as someone else chooses to keep it.
The fix is direct: own the relay.
If you operate the machine, there is no adversary to hide from. Your query patterns exist only in logs you control. Your data persists as long as you choose. No third party can ban you, go offline unexpectedly, or hand over records. The outbox model described in NIP-65 assumes users control their outbox relays. Running your own makes that assumption true.
Haven's Architecture
Haven, created by the bitvora team, packages everything you need for personal relay infrastructure in a single binary:
Private relay (/private): Auth-protected storage for drafts, eCash tokens, and data nobody else should access. No external reads or writes.
Chat relay (/chat): Web-of-trust filtered endpoint for DMs and group chats. Only contacts within your WoT can interact.
Inbox relay (/inbox): Receives notifications when you're tagged. Zaps, reactions, and replies land here, and Haven automatically pulls mentions from other relays.
Outbox relay (root path): Your public notes. Import historical content, blast new posts to other relays. You write, anyone reads.
Blossom media server: Self-hosted images and videos with shareable URLs.
The database is embedded (BadgerDB by default, LMDB optional), eliminating external dependencies. Smart features include Web of Trust spam filtering, automatic note import from other relays, cloud backup to S3-compatible storage, and blastr republishing.
VPS over home hosting
Running a relay at home exposes your residential IP address to the internet. Services like Shodan and Censys catalog open ports within hours. Your home network becomes visible to anyone who queries your relay URL. DDoS attacks can knock your household offline. Port forwarding punches holes in your router's firewall.
A VPS isolates this risk, keeping your home IP private while directing attacks at infrastructure designed for public exposure. The hosting provider handles physical security, power redundancy, and network uptime.
The cost is negligible. Hetzner offers 2 vCPU, 4GB RAM, and 40GB NVMe for roughly €4/month. Vultr and DigitalOcean start at $6/month. For privacy-focused hosting, Mynymbox (mynymbox.net) accepts Bitcoin and Lightning via self-hosted BTCPayServer, requires no personal information, and operates from privacy-friendly jurisdictions including the Netherlands, Finland, and Germany.
Haven's resource requirements are modest. Personal relay usage needs around 1GB RAM and minimal CPU. Text events are small; years of notes fit in a few gigabytes. NVMe storage helps if using LMDB.
Deployment Guide
The following assumes Ubuntu 24.04 on a fresh VPS. Adapt paths and package managers for other distributions.
Initial access and user setup
SSH into your server as root, then create a non-root user:
adduser haven
usermod -aG sudo haven
Copy your SSH public key to the new user:
mkdir -p /home/haven/.ssh
cp ~/.ssh/authorized_keys /home/haven/.ssh/
chown -R haven:haven /home/haven/.ssh
chmod 700 /home/haven/.ssh
chmod 600 /home/haven/.ssh/authorized_keys
SSH Hardening
Edit /etc/ssh/sshd_config:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
X11Forwarding no
Restart SSH:
systemctl restart sshd
Before disconnecting, verify you can log in as the new user from another terminal.
Firewall Configuration
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
System Updates
apt update && apt upgrade -y
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
Download and configure Haven
Switch to the haven user:
su - haven
mkdir haven && cd haven
Download the latest release from GitHub:
curl -sL https://api.github.com/repos/bitvora/haven/releases/latest | grep "browser_download_url.*linux_amd64" | cut -d '"' -f 4 | xargs curl -L -o haven.tar.gz
tar -xzf haven.tar.gz
Create configuration files:
cp .env.example .env
cp relays_import.example.json relays_import.json
cp relays_blastr.example.json relays_blastr.json
Edit .env with your settings:
RELAY_NAME="Your Relay Name"
RELAY_PUBKEY="your_hex_pubkey"
RELAY_DESCRIPTION="Personal relay"
RELAY_URL="wss://relay.yourdomain.com"
Your hex pubkey can be derived from your npub using any Nostr tool or library.
Create systemd service
Create /etc/systemd/system/haven.service:
[Unit]
Description=Haven Relay
After=network.target
[Service]
ExecStart=/home/haven/haven/haven
WorkingDirectory=/home/haven/haven
User=haven
Group=haven
Restart=always
MemoryLimit=1000M
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable haven
sudo systemctl start haven
Verify it's running:
sudo systemctl status haven
Reverse proxy with Caddy
Caddy handles TLS automatically:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf ' https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf ' https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
Edit /etc/caddy/Caddyfile:
relay.yourdomain.com {
reverse_proxy localhost:3355 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
request_body {
max_size 100MB
}
}
Reload Caddy:
sudo systemctl reload caddy
Ensure your domain's A record points to the VPS IP before Caddy attempts certificate issuance.
Import historical notes
After initial setup, import your existing notes:
sudo systemctl stop haven
cd /home/haven/haven
./haven --import
sudo systemctl start haven
Verify Operation
Your relay endpoints:
wss://relay.yourdomain.com(outbox + Blossom)wss://relay.yourdomain.com/privatewss://relay.yourdomain.com/chatwss://relay.yourdomain.com/inbox
Test with any Nostr client by adding your relay URL to your relay list. Update your NIP-65 relay list (kind 10002) to advertise your new outbox.
What you've built
Your notes now persist on infrastructure you control. Query patterns exist only in your logs. The inbox relay receives mentions automatically. The outbox blasts your content to the broader network. Web of trust filtering keeps spam out of your DMs.
The outbox model works better when you control your outbox. Now you do.
原始 JSON
{
"kind": 30023,
"id": "4907af08add071d6117fa278367987145eb013ecfd883497f5286b161056ee27",
"pubkey": "b7ed68b062de6b4a12e51fd5285c1e1e0ed0e5128cda93ab11b4150b55ed32fc",
"created_at": 1777543606,
"tags": [
[
"d",
"9e55cc601d2955aa"
],
[
"image",
"https://image.nostr.build/7bb196d9d812a82f5aa1fd4ecb1e3ef720f5bc75de8e855056ac9319ae5245e4.jpg"
],
[
"title",
"Own Your Outbox: Running Haven as Your Personal Nostr Relay"
],
[
"summary",
"Your relay, your rules. Haven bundles four relay functions into one binary, easily deployable on a cheap VPS in an afternoon."
],
[
"published_at",
"1766940394"
],
[
"t",
"nostr"
],
[
"t",
"relay"
],
[
"t",
"self-sovereignty"
],
[
"t",
"decentralization"
],
[
"t",
"wot"
],
[
"t",
"blossom"
],
[
"t",
"privacy"
],
[
"t",
"austrian-economics"
],
[
"t",
"freedom-tech"
],
[
"t",
"haven"
],
[
"t",
"outbox"
]
],
"content": "Nostr promises censorship resistance through decentralization. Your identity lives in a keypair you control. Your notes carry cryptographic signatures no relay can forge. You choose which relays to use.\n\nBut there's a gap between the promise and the implementation. If you rely on third-party relays, you depend on their uptime, their retention policies, their willingness to serve your content. They can go offline, get banned, or decide your notes are no longer worth storing. Your query patterns are visible to every relay you connect to. Your data persists only as long as someone else chooses to keep it.\n\nThe fix is direct: own the relay.\n\nIf you operate the machine, there is no adversary to hide from. Your query patterns exist only in logs you control. Your data persists as long as you choose. No third party can ban you, go offline unexpectedly, or hand over records. The outbox model described in NIP-65 assumes users control their outbox relays. Running your own makes that assumption true.\n\n## Haven's Architecture\n\nHaven, created by the bitvora team, packages everything you need for personal relay infrastructure in a single binary:\n\n**Private relay** (`/private`): Auth-protected storage for drafts, eCash tokens, and data nobody else should access. No external reads or writes.\n\n**Chat relay** (`/chat`): Web-of-trust filtered endpoint for DMs and group chats. Only contacts within your WoT can interact.\n\n**Inbox relay** (`/inbox`): Receives notifications when you're tagged. Zaps, reactions, and replies land here, and Haven automatically pulls mentions from other relays.\n\n**Outbox relay** (root path): Your public notes. Import historical content, blast new posts to other relays. You write, anyone reads.\n\n**Blossom media server**: Self-hosted images and videos with shareable URLs.\n\nThe database is embedded (BadgerDB by default, LMDB optional), eliminating external dependencies. Smart features include Web of Trust spam filtering, automatic note import from other relays, cloud backup to S3-compatible storage, and blastr republishing.\n\n## VPS over home hosting\n\nRunning a relay at home exposes your residential IP address to the internet. Services like Shodan and Censys catalog open ports within hours. Your home network becomes visible to anyone who queries your relay URL. DDoS attacks can knock your household offline. Port forwarding punches holes in your router's firewall.\n\nA VPS isolates this risk, keeping your home IP private while directing attacks at infrastructure designed for public exposure. The hosting provider handles physical security, power redundancy, and network uptime.\n\nThe cost is negligible. Hetzner offers 2 vCPU, 4GB RAM, and 40GB NVMe for roughly €4/month. Vultr and DigitalOcean start at $6/month. For privacy-focused hosting, Mynymbox (mynymbox.net) accepts Bitcoin and Lightning via self-hosted BTCPayServer, requires no personal information, and operates from privacy-friendly jurisdictions including the Netherlands, Finland, and Germany.\n\nHaven's resource requirements are modest. Personal relay usage needs around 1GB RAM and minimal CPU. Text events are small; years of notes fit in a few gigabytes. NVMe storage helps if using LMDB.\n\n## Deployment Guide\n\nThe following assumes Ubuntu 24.04 on a fresh VPS. Adapt paths and package managers for other distributions.\n\n### Initial access and user setup\n\nSSH into your server as root, then create a non-root user:\n\n```bash\nadduser haven\nusermod -aG sudo haven\n```\n\nCopy your SSH public key to the new user:\n\n```bash\nmkdir -p /home/haven/.ssh\ncp ~/.ssh/authorized_keys /home/haven/.ssh/\nchown -R haven:haven /home/haven/.ssh\nchmod 700 /home/haven/.ssh\nchmod 600 /home/haven/.ssh/authorized_keys\n```\n\n### SSH Hardening\n\nEdit `/etc/ssh/sshd_config`:\n\n```\nPermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nMaxAuthTries 3\nX11Forwarding no\n```\n\nRestart SSH:\n\n```bash\nsystemctl restart sshd\n```\n\nBefore disconnecting, verify you can log in as the new user from another terminal.\n\n### Firewall Configuration\n\n```bash\nufw default deny incoming\nufw default allow outgoing\nufw allow ssh\nufw allow 80/tcp\nufw allow 443/tcp\nufw enable\n```\n\n### System Updates\n\n```bash\napt update \u0026\u0026 apt upgrade -y\napt install -y unattended-upgrades\ndpkg-reconfigure -plow unattended-upgrades\n```\n\n### Download and configure Haven\n\nSwitch to the haven user:\n\n```bash\nsu - haven\nmkdir haven \u0026\u0026 cd haven\n```\n\nDownload the latest release from GitHub:\n\n```bash\ncurl -sL https://api.github.com/repos/bitvora/haven/releases/latest | grep \"browser_download_url.*linux_amd64\" | cut -d '\"' -f 4 | xargs curl -L -o haven.tar.gz\ntar -xzf haven.tar.gz\n```\n\nCreate configuration files:\n\n```bash\ncp .env.example .env\ncp relays_import.example.json relays_import.json\ncp relays_blastr.example.json relays_blastr.json\n```\n\nEdit `.env` with your settings:\n\n```\nRELAY_NAME=\"Your Relay Name\"\nRELAY_PUBKEY=\"your_hex_pubkey\"\nRELAY_DESCRIPTION=\"Personal relay\"\nRELAY_URL=\"wss://relay.yourdomain.com\"\n```\n\nYour hex pubkey can be derived from your npub using any Nostr tool or library.\n\n### Create systemd service\n\nCreate `/etc/systemd/system/haven.service`:\n\n```ini\n[Unit]\nDescription=Haven Relay\nAfter=network.target\n\n[Service]\nExecStart=/home/haven/haven/haven\nWorkingDirectory=/home/haven/haven\nUser=haven\nGroup=haven\nRestart=always\nMemoryLimit=1000M\n\n[Install]\nWantedBy=multi-user.target\n```\n\nEnable and start:\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl enable haven\nsudo systemctl start haven\n```\n\nVerify it's running:\n\n```bash\nsudo systemctl status haven\n```\n\n### Reverse proxy with Caddy\n\nCaddy handles TLS automatically:\n\n```bash\nsudo apt install -y debian-keyring debian-archive-keyring apt-transport-https\ncurl -1sLf ' https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg\ncurl -1sLf ' https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list\nsudo apt update\nsudo apt install caddy\n```\n\nEdit `/etc/caddy/Caddyfile`:\n\n```\nrelay.yourdomain.com {\n reverse_proxy localhost:3355 {\n header_up Host {host}\n header_up X-Real-IP {remote_host}\n header_up X-Forwarded-For {remote_host}\n header_up X-Forwarded-Proto {scheme}\n }\n request_body {\n max_size 100MB\n }\n}\n```\n\nReload Caddy:\n\n```bash\nsudo systemctl reload caddy\n```\n\nEnsure your domain's A record points to the VPS IP before Caddy attempts certificate issuance.\n\n### Import historical notes\n\nAfter initial setup, import your existing notes:\n\n```bash\nsudo systemctl stop haven\ncd /home/haven/haven\n./haven --import\nsudo systemctl start haven\n```\n\n### Verify Operation\n\nYour relay endpoints:\n\n- `wss://relay.yourdomain.com` (outbox + Blossom)\n- `wss://relay.yourdomain.com/private`\n- `wss://relay.yourdomain.com/chat`\n- `wss://relay.yourdomain.com/inbox`\n\nTest with any Nostr client by adding your relay URL to your relay list. Update your NIP-65 relay list (kind 10002) to advertise your new outbox.\n\n## What you've built\n\nYour notes now persist on infrastructure you control. Query patterns exist only in your logs. The inbox relay receives mentions automatically. The outbox blasts your content to the broader network. Web of trust filtering keeps spam out of your DMs.\n\nThe outbox model works better when you control your outbox. Now you do.",
"sig": "6f0b879af07882f686ec93e8573d5b030efef8409ebb74d068a492b990a34560eb2fe654e17878fbe814c2392f74c8c2161647189d3b8d5c392fa29b294aab52"
}