From ea4f508f5ee91b370c6912cde26b1a432380d037 Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 14 Feb 2026 12:14:19 -0800 Subject: feat: integrate config system into relay main.go Add support for loading configuration from YAML file via -config flag. Wire up auth, rate limiting, and metrics interceptors based on config. Changes: - Add -config flag to relay command - Use config types directly in auth package (AuthOperationConfig) - Add conversion methods: RateLimitConfig.ToRateLimiter(), MetricsConfig.ToMetrics() - Add Metrics.Serve() method for prometheus HTTP endpoint - Update main.go to initialize interceptors from config - Fix type naming: OperationAuthConfig -> AuthOperationConfig for consistency Config now supports complete relay setup including auth read/write allowlists, rate limiting, and prometheus metrics. --- internal/config/config.go | 75 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 14 deletions(-) (limited to 'internal/config') diff --git a/internal/config/config.go b/internal/config/config.go index 36c8be5..dcceade 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,6 +7,9 @@ import ( "time" "gopkg.in/yaml.v3" + "northwest.io/muxstr/internal/auth" + "northwest.io/muxstr/internal/metrics" + "northwest.io/muxstr/internal/ratelimit" "northwest.io/nostr" ) @@ -33,18 +36,10 @@ type DatabaseConfig struct { } type AuthConfig struct { - Read AuthOperationConfig `yaml:"read"` - Write AuthOperationConfig `yaml:"write"` - TimestampWindow int64 `yaml:"timestamp_window"` - SkipMethods []string `yaml:"skip_methods"` -} - -// AuthOperationConfig configures auth for read or write operations. -// Three states: disabled (allow all), enabled with empty list (require auth), -// enabled with npubs (whitelist only). Npubs normalized to hex at load time. -type AuthOperationConfig struct { - Enabled bool `yaml:"enabled"` - AllowedNpubs []string `yaml:"allowed_npubs"` + Read auth.AuthOperationConfig `yaml:"read"` + Write auth.AuthOperationConfig `yaml:"write"` + TimestampWindow int64 `yaml:"timestamp_window"` + SkipMethods []string `yaml:"skip_methods"` } type RateLimitConfig struct { @@ -105,11 +100,11 @@ func Default() *Config { Path: "relay.db", }, Auth: AuthConfig{ - Read: AuthOperationConfig{ + Read: auth.AuthOperationConfig{ Enabled: false, AllowedNpubs: nil, }, - Write: AuthOperationConfig{ + Write: auth.AuthOperationConfig{ Enabled: false, AllowedNpubs: nil, }, @@ -349,3 +344,55 @@ func (c *Config) Save(filename string) error { return nil } + +func (r *RateLimitConfig) ToRateLimiter() *ratelimit.Config { + rlConfig := &ratelimit.Config{ + RequestsPerSecond: r.DefaultRPS, + BurstSize: r.DefaultBurst, + IPRequestsPerSecond: r.IPRPS, + IPBurstSize: r.IPBurst, + SkipMethods: r.SkipMethods, + SkipUsers: r.SkipUsers, + CleanupInterval: r.CleanupInterval, + MaxIdleTime: r.MaxIdleTime, + } + + if r.Methods != nil { + rlConfig.MethodLimits = make(map[string]ratelimit.MethodLimit, len(r.Methods)) + for method, limit := range r.Methods { + rlConfig.MethodLimits[method] = ratelimit.MethodLimit{ + RequestsPerSecond: limit.RPS, + BurstSize: limit.Burst, + } + } + } + + if r.Users != nil { + rlConfig.UserLimits = make(map[string]ratelimit.UserLimit, len(r.Users)) + for user, limit := range r.Users { + userLimit := ratelimit.UserLimit{ + RequestsPerSecond: limit.RPS, + BurstSize: limit.Burst, + } + if limit.Methods != nil { + userLimit.MethodLimits = make(map[string]ratelimit.MethodLimit, len(limit.Methods)) + for method, methodLimit := range limit.Methods { + userLimit.MethodLimits[method] = ratelimit.MethodLimit{ + RequestsPerSecond: methodLimit.RPS, + BurstSize: methodLimit.Burst, + } + } + } + rlConfig.UserLimits[user] = userLimit + } + } + + return rlConfig +} + +func (m *MetricsConfig) ToMetrics() *metrics.Config { + return &metrics.Config{ + Namespace: m.Namespace, + Subsystem: m.Subsystem, + } +} -- cgit v1.2.3