fix: add health RPC handler, Nostr connect timeouts, atomic backup restore, nginx rate limits

- R1: Add health RPC endpoint with crash recovery status, uptime, and version
- R2: Wrap all 5 Nostr client.connect() calls in 10s timeout
- R3: Make backup restore atomic with staging dir and rollback on failure
- I1: Add rate limiting, body size, and proxy timeouts to unauthenticated nginx endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-21 01:02:16 +00:00
co-authored by Claude Opus 4.6
parent b5024c29df
commit c299199d37
7 changed files with 204 additions and 15 deletions
+17 -5
View File
@@ -16,7 +16,9 @@ use nostr_sdk::prelude::*;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
use std::path::Path;
use std::time::Duration;
use tokio::fs;
use tracing::warn;
const NOSTR_SECRET_FILE: &str = "nostr_secret";
@@ -121,7 +123,9 @@ pub async fn publish_presence(
for url in relays {
let _ = client.add_relay(url).await;
}
client.connect().await;
if tokio::time::timeout(Duration::from_secs(10), client.connect()).await.is_err() {
warn!("Nostr relay connection timed out after 10s, continuing anyway");
}
let builder = EventBuilder::new(Kind::Custom(30078), content)
.tag(Tag::identifier("archipelago-node"));
@@ -158,7 +162,9 @@ pub async fn discover_nodes(
for url in relays {
let _ = client.add_relay(url).await;
}
client.connect().await;
if tokio::time::timeout(Duration::from_secs(10), client.connect()).await.is_err() {
warn!("Nostr relay connection timed out after 10s, continuing anyway");
}
let filter = Filter::new()
.kind(Kind::Custom(30078))
@@ -259,7 +265,9 @@ pub async fn send_connect_request(
for url in relays {
let _ = client.add_relay(url).await;
}
client.connect().await;
if tokio::time::timeout(Duration::from_secs(10), client.connect()).await.is_err() {
warn!("Nostr relay connection timed out after 10s, continuing anyway");
}
// Kind 4 encrypted DM with p-tag for recipient
let builder = EventBuilder::new(Kind::EncryptedDirectMessage, encrypted)
@@ -319,7 +327,9 @@ pub async fn send_connect_response(
for url in relays {
let _ = client.add_relay(url).await;
}
client.connect().await;
if tokio::time::timeout(Duration::from_secs(10), client.connect()).await.is_err() {
warn!("Nostr relay connection timed out after 10s, continuing anyway");
}
let builder = EventBuilder::new(Kind::EncryptedDirectMessage, encrypted)
.tag(Tag::public_key(recipient_pk));
@@ -355,7 +365,9 @@ pub async fn poll_handshakes(
for url in relays {
let _ = client.add_relay(url).await;
}
client.connect().await;
if tokio::time::timeout(Duration::from_secs(10), client.connect()).await.is_err() {
warn!("Nostr relay connection timed out after 10s, continuing anyway");
}
// Query for encrypted DMs addressed to us
let mut filter = Filter::new()