{ pkgs, lib, ... }: let domains = [ "otherwhere.app" "www.otherwhere.app" ]; port = 8892; relayUrl = "wss://relay.otherwhere.app/"; dbPath = "/var/lib/nostr-rs-relay/nostr.db"; script = pkgs.writeText "nip05-server.py" '' import json, sqlite3 from http.server import HTTPServer, BaseHTTPRequestHandler from urllib.parse import urlparse, parse_qs DB_PATH = "${dbPath}" RELAY_URL = "${relayUrl}" PORT = ${toString port} class NIP05Handler(BaseHTTPRequestHandler): def do_GET(self): parsed = urlparse(self.path) if parsed.path != "/.well-known/nostr.json": self.send_response(404) self.end_headers() return params = parse_qs(parsed.query) name_filter = params.get("name", [None])[0] if name_filter: name_filter = name_filter.strip().lower() try: con = sqlite3.connect(f"file:{DB_PATH}?mode=ro", uri=True) rows = con.execute(""" SELECT author, content FROM event WHERE kind = 0 AND (hidden IS NULL OR hidden = 0) GROUP BY author HAVING created_at = MAX(created_at) """).fetchall() con.close() except Exception: self.send_response(500) self.end_headers() return names = {} relays = {} for author_blob, event_json in rows: try: event = json.loads(event_json) pub_key = event.get("pubkey", author_blob.hex()) meta = json.loads(event.get("content", "{}")) name = meta.get("name", "").strip().lower() if not name: continue if name_filter and name != name_filter: continue names[name] = pub_key relays[pub_key] = [RELAY_URL] except (json.JSONDecodeError, AttributeError): continue body = json.dumps({"names": names, "relays": relays}).encode() self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Content-Length", str(len(body))) self.end_headers() self.wfile.write(body) def log_message(self, fmt, *args): pass HTTPServer(("127.0.0.1", PORT), NIP05Handler).serve_forever() ''; in { systemd.services.nip05 = { description = "NIP-05 identifier server"; after = [ "network.target" "nostr-rs-relay.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; User = "nostr-rs-relay"; Group = "nostr-rs-relay"; ExecStart = "${pkgs.python3}/bin/python3 ${script}"; Restart = "on-failure"; RestartSec = 5; }; }; environment.etc."caddy/Caddyfile.d/nip05.caddyfile".text = '' ${lib.concatStringsSep ", " domains} { handle /.well-known/nostr.json { reverse_proxy localhost:${toString port} } handle { header Content-Type "text/html; charset=utf-8" respond `otherwhere.app

otherwhere.app

` 200 } } ''; }