diff options
| author | bndw <ben@bdw.to> | 2026-02-14 12:14:19 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-02-14 12:14:19 -0800 |
| commit | ea4f508f5ee91b370c6912cde26b1a432380d037 (patch) | |
| tree | 79081398bc0da1db76c28de6de04ed88a5e53bc3 /internal/config | |
| parent | 4fc493e6d8cc20137f920f8647e39fc5051bb245 (diff) | |
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.
Diffstat (limited to 'internal/config')
| -rw-r--r-- | internal/config/config.go | 75 |
1 files changed, 61 insertions, 14 deletions
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 ( | |||
| 7 | "time" | 7 | "time" |
| 8 | 8 | ||
| 9 | "gopkg.in/yaml.v3" | 9 | "gopkg.in/yaml.v3" |
| 10 | "northwest.io/muxstr/internal/auth" | ||
| 11 | "northwest.io/muxstr/internal/metrics" | ||
| 12 | "northwest.io/muxstr/internal/ratelimit" | ||
| 10 | "northwest.io/nostr" | 13 | "northwest.io/nostr" |
| 11 | ) | 14 | ) |
| 12 | 15 | ||
| @@ -33,18 +36,10 @@ type DatabaseConfig struct { | |||
| 33 | } | 36 | } |
| 34 | 37 | ||
| 35 | type AuthConfig struct { | 38 | type AuthConfig struct { |
| 36 | Read AuthOperationConfig `yaml:"read"` | 39 | Read auth.AuthOperationConfig `yaml:"read"` |
| 37 | Write AuthOperationConfig `yaml:"write"` | 40 | Write auth.AuthOperationConfig `yaml:"write"` |
| 38 | TimestampWindow int64 `yaml:"timestamp_window"` | 41 | TimestampWindow int64 `yaml:"timestamp_window"` |
| 39 | SkipMethods []string `yaml:"skip_methods"` | 42 | SkipMethods []string `yaml:"skip_methods"` |
| 40 | } | ||
| 41 | |||
| 42 | // AuthOperationConfig configures auth for read or write operations. | ||
| 43 | // Three states: disabled (allow all), enabled with empty list (require auth), | ||
| 44 | // enabled with npubs (whitelist only). Npubs normalized to hex at load time. | ||
| 45 | type AuthOperationConfig struct { | ||
| 46 | Enabled bool `yaml:"enabled"` | ||
| 47 | AllowedNpubs []string `yaml:"allowed_npubs"` | ||
| 48 | } | 43 | } |
| 49 | 44 | ||
| 50 | type RateLimitConfig struct { | 45 | type RateLimitConfig struct { |
| @@ -105,11 +100,11 @@ func Default() *Config { | |||
| 105 | Path: "relay.db", | 100 | Path: "relay.db", |
| 106 | }, | 101 | }, |
| 107 | Auth: AuthConfig{ | 102 | Auth: AuthConfig{ |
| 108 | Read: AuthOperationConfig{ | 103 | Read: auth.AuthOperationConfig{ |
| 109 | Enabled: false, | 104 | Enabled: false, |
| 110 | AllowedNpubs: nil, | 105 | AllowedNpubs: nil, |
| 111 | }, | 106 | }, |
| 112 | Write: AuthOperationConfig{ | 107 | Write: auth.AuthOperationConfig{ |
| 113 | Enabled: false, | 108 | Enabled: false, |
| 114 | AllowedNpubs: nil, | 109 | AllowedNpubs: nil, |
| 115 | }, | 110 | }, |
| @@ -349,3 +344,55 @@ func (c *Config) Save(filename string) error { | |||
| 349 | 344 | ||
| 350 | return nil | 345 | return nil |
| 351 | } | 346 | } |
| 347 | |||
| 348 | func (r *RateLimitConfig) ToRateLimiter() *ratelimit.Config { | ||
| 349 | rlConfig := &ratelimit.Config{ | ||
| 350 | RequestsPerSecond: r.DefaultRPS, | ||
| 351 | BurstSize: r.DefaultBurst, | ||
| 352 | IPRequestsPerSecond: r.IPRPS, | ||
| 353 | IPBurstSize: r.IPBurst, | ||
| 354 | SkipMethods: r.SkipMethods, | ||
| 355 | SkipUsers: r.SkipUsers, | ||
| 356 | CleanupInterval: r.CleanupInterval, | ||
| 357 | MaxIdleTime: r.MaxIdleTime, | ||
| 358 | } | ||
| 359 | |||
| 360 | if r.Methods != nil { | ||
| 361 | rlConfig.MethodLimits = make(map[string]ratelimit.MethodLimit, len(r.Methods)) | ||
| 362 | for method, limit := range r.Methods { | ||
| 363 | rlConfig.MethodLimits[method] = ratelimit.MethodLimit{ | ||
| 364 | RequestsPerSecond: limit.RPS, | ||
| 365 | BurstSize: limit.Burst, | ||
| 366 | } | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | if r.Users != nil { | ||
| 371 | rlConfig.UserLimits = make(map[string]ratelimit.UserLimit, len(r.Users)) | ||
| 372 | for user, limit := range r.Users { | ||
| 373 | userLimit := ratelimit.UserLimit{ | ||
| 374 | RequestsPerSecond: limit.RPS, | ||
| 375 | BurstSize: limit.Burst, | ||
| 376 | } | ||
| 377 | if limit.Methods != nil { | ||
| 378 | userLimit.MethodLimits = make(map[string]ratelimit.MethodLimit, len(limit.Methods)) | ||
| 379 | for method, methodLimit := range limit.Methods { | ||
| 380 | userLimit.MethodLimits[method] = ratelimit.MethodLimit{ | ||
| 381 | RequestsPerSecond: methodLimit.RPS, | ||
| 382 | BurstSize: methodLimit.Burst, | ||
| 383 | } | ||
| 384 | } | ||
| 385 | } | ||
| 386 | rlConfig.UserLimits[user] = userLimit | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | return rlConfig | ||
| 391 | } | ||
| 392 | |||
| 393 | func (m *MetricsConfig) ToMetrics() *metrics.Config { | ||
| 394 | return &metrics.Config{ | ||
| 395 | Namespace: m.Namespace, | ||
| 396 | Subsystem: m.Subsystem, | ||
| 397 | } | ||
| 398 | } | ||
