Add NIP-05 identifier server for otherwhere.app
Dynamic lookup from nostr-rs-relay SQLite DB; runs as nostr-rs-relay user. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
288ce840ad
commit
d4b9b209c7
2 changed files with 100 additions and 0 deletions
99
modules/services/nip05.nix
Normal file
99
modules/services/nip05.nix
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
{ 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 pub_key, content FROM event
|
||||
WHERE kind = 0 AND (hidden IS NULL OR hidden = 0)
|
||||
GROUP BY pub_key
|
||||
HAVING created_at = MAX(created_at)
|
||||
""").fetchall()
|
||||
con.close()
|
||||
except Exception:
|
||||
self.send_response(500)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
names = {}
|
||||
relays = {}
|
||||
for pub_key, content in rows:
|
||||
try:
|
||||
meta = json.loads(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 `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>otherwhere.app</title></head><body><p>otherwhere.app</p></body></html>` 200
|
||||
}
|
||||
}
|
||||
'';
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue