Skip to content

orveth/strfry-nix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

strfry-nix

NixOS module for strfry β€” a high-performance Nostr relay.

Features

  • πŸš€ Production-ready NixOS module
  • πŸ”’ Hardened systemd service configuration
  • πŸ”„ Built-in router support for syncing with remote relays
  • πŸ“¦ Minimal dependencies (strfry is in nixpkgs)
  • πŸ› οΈ Development shell for local testing

Quick Start

Local Development

Test strfry locally without NixOS:

# Clone this repo
git clone https://github.com/orveth/strfry-nix.git
cd strfry-nix

# Enter dev shell
nix develop

# Create test data directory
mkdir -p ./test-data

# Copy example config
cp strfry.conf.example strfry.conf

# Edit config to point to test-data
# (change db = "./test-data")

# Start relay
strfry --config=./strfry.conf relay

In another terminal, test the relay:

# Check relay info (NIP-11)
curl -H "Accept: application/nostr+json" http://localhost:7777

# Connect with websocat
websocat ws://localhost:7777

NixOS Integration

Add to your flake inputs:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    strfry-nix.url = "github:orveth/strfry-nix";
  };

  outputs = { self, nixpkgs, strfry-nix }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      modules = [
        strfry-nix.nixosModules.default
        {
          services.strfry = {
            enable = true;
            bind = "127.0.0.1";  # localhost-only
            port = 7777;
            
            info = {
              name = "My Relay";
              description = "Personal Nostr relay";
            };
          };
        }
      ];
    };
  };
}

Rebuild and start:

sudo nixos-rebuild switch
systemctl status strfry

Configuration

Basic Options

services.strfry = {
  enable = true;
  
  # Network
  bind = "127.0.0.1";  # Use "0.0.0.0" for external access
  port = 7777;
  
  # Storage
  dataDir = "/var/lib/strfry";
  dbSize = 10737418240;  # 10GB
  
  # Relay info (NIP-11)
  info = {
    name = "My Relay";
    description = "Personal Nostr relay";
    pubkey = "npub1...";  # Optional
    contact = "admin@example.com";  # Optional
  };
};

Event Policies

services.strfry.events = {
  maxEventSize = 65536;  # 64KB
  rejectEventsNewerThanSeconds = 900;  # 15 min in future
  rejectEventsOlderThanSeconds = 94608000;  # 3 years old
  maxNumTags = 2000;
  maxTagValSize = 1024;
};

Router Sync

Sync events from remote relays using the built-in router:

services.strfry.router = {
  enable = true;
  config = ''
    streams {
      public {
        dir = "down"
        urls = [
          "wss://relay.damus.io"
          "wss://nos.lol"
          "wss://relay.nostr.band"
        ]
      }
    }
  '';
};

Or use an external config file:

services.strfry.router = {
  enable = true;
  configFile = ./strfry-router.conf;
};

See strfry-router.conf.example for more options.

Reverse Proxy (nginx)

For external access with TLS:

services.nginx = {
  enable = true;
  virtualHosts."relay.example.com" = {
    enableACME = true;
    forceSSL = true;
    locations."/" = {
      proxyPass = "http://127.0.0.1:7777";
      proxyWebsockets = true;
      extraConfig = ''
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      '';
    };
  };
};

# Tell strfry to use the real IP header
services.strfry.realIpHeader = "x-real-ip";

Management Commands

# Check service status
systemctl status strfry
systemctl status strfry-router  # if router is enabled

# View logs
journalctl -u strfry -f
journalctl -u strfry-router -f

# Export all events
sudo -u strfry strfry export > backup.jsonl

# Import events
cat events.jsonl | sudo -u strfry strfry import

# One-time sync from remote relay
sudo -u strfry strfry sync wss://relay.damus.io --dir down

# Scan events matching filter
sudo -u strfry strfry scan '{"kinds":[1],"limit":10}'

Architecture

  • Storage: LMDB (single-file database, no external DB required)
  • Config: Generated from Nix options, stored in /nix/store
  • Data: Persistent in /var/lib/strfry (configurable)
  • User: strfry (isolated system user)
  • Hardening: Full systemd security lockdown

Security

The systemd service uses extensive hardening:

  • NoNewPrivileges, PrivateTmp, ProtectHome
  • ProtectSystem=strict with explicit ReadWritePaths
  • MemoryDenyWriteExecute, RestrictRealtime
  • RestrictNamespaces, LockPersonality
  • Limited to AF_INET, AF_INET6, AF_UNIX address families

For localhost-only relays, keep bind = "127.0.0.1" and skip nginx.

Troubleshooting

Relay won't start

Check logs:

journalctl -u strfry -n 50

Common issues:

  • Port already in use (ss -tulpn | grep 7777)
  • Permissions on dataDir (sudo chown -R strfry:strfry /var/lib/strfry)
  • Invalid config syntax (check strfry.conf.example)

Router not syncing

journalctl -u strfry-router -f

Check:

  • Remote relays are reachable (websocat wss://relay.damus.io)
  • Router config syntax (strfry-router.conf.example)
  • Main relay is running (systemctl status strfry)

Database size

Monitor size:

du -sh /var/lib/strfry

The dbSize option sets the LMDB maximum. Actual disk usage grows as needed.

Resources

License

MIT

Contributing

Issues and PRs welcome! This is a personal project but contributions are appreciated.

About

NixOS module for strfry Nostr relay

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages