Files
nostermd-relay/cmd/nostermd/config.go
T
rgoodall 294616642f
ci / build (push) Successful in 2m3s
ci / image (push) Successful in 1m4s
initial public relay build repo
2026-07-24 13:11:06 -04:00

75 lines
2.3 KiB
Go

package main
import (
"log"
"os"
"path/filepath"
"strconv"
"fiatjaf.com/nostr"
)
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
// envIntOr parses a non-negative integer env var, falling back on empty/invalid.
func envIntOr(key string, fallback int) int {
if v := os.Getenv(key); v != "" {
if n, err := strconv.Atoi(v); err == nil && n >= 0 {
return n
}
log.Printf("invalid %s=%q; using %d", key, v, fallback)
}
return fallback
}
// loadOrGenerateKey resolves the relay's signing identity, which signs the group
// metadata/admins/members events. A STABLE identity is required so those signed
// lists remain valid across restarts and re-deploys.
//
// - RELAY_SECRET_KEY set → use it (production path).
// - RELAY_ENV=production, unset → fatal. A fresh key each boot silently
// corrupts signed group rosters, so we refuse to start.
// - otherwise (dev) → persist a generated key under the data dir
// and reuse it, so even dev keeps a stable identity across restarts.
func loadOrGenerateKey(dataDir string) nostr.SecretKey {
if hex := os.Getenv("RELAY_SECRET_KEY"); hex != "" {
sk, err := nostr.SecretKeyFromHex(hex)
if err != nil {
log.Fatalf("invalid RELAY_SECRET_KEY: %v", err)
}
return sk
}
if isProduction() {
log.Fatal("RELAY_SECRET_KEY is required when RELAY_ENV=production " +
"(a fresh key each boot would corrupt signed group rosters). " +
"Generate one with: openssl rand -hex 32")
}
// Dev convenience: persist a generated key so restarts keep one identity.
keyPath := filepath.Join(dataDir, "relay.key")
if data, err := os.ReadFile(keyPath); err == nil {
if sk, err := nostr.SecretKeyFromHex(string(data)); err == nil {
log.Printf("using persisted dev relay identity from %s", keyPath)
return sk
}
log.Printf("ignoring unreadable %s; generating a new dev key", keyPath)
}
sk := nostr.Generate()
if err := os.WriteFile(keyPath, []byte(sk.Hex()), 0o600); err != nil {
log.Printf("could not persist dev relay key (%v); identity is ephemeral this run", err)
} else {
log.Printf("generated and persisted a dev relay identity at %s (set RELAY_SECRET_KEY for production)", keyPath)
}
return sk
}
func isProduction() bool {
return os.Getenv("RELAY_ENV") == "production"
}