s3-orchestrator

config

import "github.com/afreidah/s3-orchestrator/internal/config"

Package config provides YAML configuration loading with environment variable expansion, validation, and hot-reload support via SIGHUP.

Index

Constants

CredentialSourceStatic and friends enumerate the supported credential_source values.

const (
    // CredentialSourceStatic uses access_key_id / secret_access_key from the config (current default behaviour).
    CredentialSourceStatic = "static"
    // CredentialSourceDefaultChain resolves credentials via the AWS SDK default chain (env, IMDS, SSO, ~/.aws, STS).
    CredentialSourceDefaultChain = "default_chain"
)

Variables

Loader-level wrapping errors (LoadConfig).

var (
    ErrReadConfigFile = errors.New("read config file")
    ErrParseConfig    = errors.New("parse config")
    ErrInvalidConfig  = errors.New("invalid config")
)

Bucket validation errors.

var (
    ErrNoBuckets           = errors.New("at least one bucket is required")
    ErrBucketNameRequired  = errors.New("bucket name is required")
    ErrBucketNameHasSlash  = errors.New("bucket name must not contain '/'")
    ErrDuplicateBucketName = errors.New("duplicate bucket name")
    ErrNoCredential        = errors.New("at least one credential is required")
    ErrInvalidCredential   = errors.New("must have access_key_id+secret_access_key or token")
    ErrDuplicateCredential = errors.New("duplicate access_key_id")
    ErrNegativeMaxUploads  = errors.New("max_multipart_uploads must be >= 0")
)

Backend validation errors.

var (
    ErrNoBackends          = errors.New("at least one backend is required")
    ErrDuplicateBackend    = errors.New("duplicate backend name")
    ErrEndpointRequired    = errors.New("endpoint is required")
    ErrBackendBucketReqd   = errors.New("bucket is required")
    ErrAccessKeyIDReqd     = errors.New("access_key_id is required")
    ErrSecretAccessKeyReqd = errors.New("secret_access_key is required")
    ErrNegativeQuota       = errors.New("quota_bytes must not be negative")
    ErrNegativeMaxObject   = errors.New("max_object_size must not be negative")
    ErrNegativeAPILimit    = errors.New("api_request_limit must not be negative")
    ErrNegativeEgress      = errors.New("egress_byte_limit must not be negative")
    ErrNegativeIngress     = errors.New("ingress_byte_limit must not be negative")
    // ErrInvalidCredentialSource: unknown credential_source value (allowed: "static", "default_chain").
    ErrInvalidCredentialSource = errors.New(`credential_source must be "static" or "default_chain"`)
    // ErrCredentialsWithDefaultChain: static keys present alongside credential_source=default_chain.
    ErrCredentialsWithDefaultChain = errors.New("access_key_id/secret_access_key must be empty when credential_source is default_chain")
)

Server and TLS errors.

var (
    ErrInvalidTLSConfig  = errors.New("both cert_file and key_file are required for TLS")
    ErrInvalidTLSVersion = errors.New("invalid TLS min_version")
    ErrInvalidLogLevel   = errors.New("invalid log_level")
)

UI / auth errors.

var (
    ErrAdminAuthIncomplete = errors.New("admin_key and admin_secret must both be set (or both empty)")
    ErrSessionSecretReqd   = errors.New("session_secret is required when UI is enabled")
)

Rate limit errors.

var (
    ErrInvalidCIDR               = errors.New("invalid CIDR in trusted_proxies")
    ErrRateLimitRPSNotPositive   = errors.New("rate_limit.requests_per_sec must be positive")
    ErrRateLimitBurstNotPositive = errors.New("rate_limit.burst must be positive")
)

Encryption errors.

var (
    ErrInvalidChunkSize     = errors.New("encryption.chunk_size must be between 4096 (4KB) and 1048576 (1MB)")
    ErrChunkSizeNotPowerOf2 = errors.New("encryption.chunk_size must be a power of 2")
    ErrKeySourceRequired    = errors.New("encryption: exactly one of master_key, master_key_file, or vault is required")
    ErrMultipleKeySources   = errors.New("encryption: only one of master_key, master_key_file, or vault may be set")
    ErrInvalidBase64Key     = errors.New("invalid base64 key material")
    ErrInvalidKeyLength     = errors.New("key must be 256 bits (32 bytes)")
    ErrInvalidKeyFile       = errors.New("invalid master_key_file")
    ErrPreviousKeyInvalid   = errors.New("previous_keys entry invalid")
    ErrVaultAddressRequired = errors.New("encryption.vault.address is required")
    ErrVaultTokenRequired   = errors.New("encryption.vault: one of token or token_file is required")
    ErrVaultTokenAmbiguous  = errors.New("encryption.vault: only one of token or token_file may be set")
    ErrVaultKeyNameRequired = errors.New("encryption.vault.key_name is required")
)

Redis / counter errors.

var (
    ErrRedisAddressRequired        = errors.New("redis.address is required when redis section is present")
    ErrRedisFailureThresholdNotPos = errors.New("redis.failure_threshold must be positive")
    ErrRedisOpenTimeoutNotPos      = errors.New("redis.open_timeout must be positive")
)

Notifications errors.

var (
    ErrNotificationURLRequired    = errors.New("notifications endpoint url is required")
    ErrNotificationEventsRequired = errors.New("notifications endpoint requires at least one event pattern")
)

Lifecycle errors.

var (
    ErrLifecyclePrefixRequired = errors.New("lifecycle.rules: prefix must not be empty (would match all objects)")
    ErrInvalidExpiration       = errors.New("lifecycle.rules: expiration_days must be positive")
    ErrDuplicatePrefix         = errors.New("duplicate prefix")
)

Rebalance / replication errors.

var (
    ErrInvalidRebalanceStrategy   = errors.New("rebalance.strategy must be 'pack' or 'spread'")
    ErrRebalanceIntervalNotPos    = errors.New("rebalance.interval must be positive")
    ErrRebalanceBatchNotPos       = errors.New("rebalance.batch_size must be positive")
    ErrRebalanceThresholdRange    = errors.New("rebalance.threshold must be between 0 and 1")
    ErrRebalanceConcurrencyNotPos = errors.New("rebalance.concurrency must be positive")
    ErrReplicationFactorMin       = errors.New("replication.factor must be at least 1")
    ErrReplicationFactorTooLarge  = errors.New("replication.factor exceeds number of backends")
    ErrReplicationIntervalNotPos  = errors.New("replication.worker_interval must be positive")
    ErrReplicationBatchNotPos     = errors.New("replication.batch_size must be positive")
    ErrInvalidRoutingStrategy     = errors.New("routing_strategy must be 'pack' or 'spread'")
    ErrQuotaMixNotAllowed         = errors.New("cannot mix unlimited (quota_bytes: 0) and quota-limited backends")
    ErrUnlimitedNeedsReplication  = errors.New("multiple backends with unlimited quota require replication.factor >= 2")
)

Usage flush / adaptive errors.

var (
    ErrUsageFlushFastInterval   = errors.New("usage_flush.fast_interval must be less than interval")
    ErrUsageFlushThresholdRange = errors.New("usage_flush.adaptive_threshold must be between 0 and 1")
)

Cache / storage misc.

var (
    ErrCacheMaxSizeNotPositive      = errors.New("cache.max_size must be positive")
    ErrCacheMaxObjectNotPositive    = errors.New("cache.max_object_size must be positive")
    ErrCacheMaxObjectExceedsMaxSize = errors.New("cache.max_object_size cannot exceed cache.max_size")
)

Telemetry errors.

var (
    ErrTracingEndpointRequired = errors.New("telemetry.tracing.endpoint is required when tracing is enabled")
)

func NonReloadableFieldsChanged

func NonReloadableFieldsChanged(old, new *Config) []string

NonReloadableFieldsChanged compares two configs and returns a list of non-reloadable field descriptions that differ. Used by the SIGHUP handler to warn about changes that require a restart.

func ParseLogLevel

func ParseLogLevel(s string) slog.Level

ParseLogLevel maps a log level string to a slog.Level. Returns slog.LevelInfo for unrecognized values. Callers should validate via SetDefaultsAndValidate before calling this function.

type BackendCircuitBreakerConfig

BackendCircuitBreakerConfig holds settings for per-backend circuit breakers. When a backend is unreachable or returns errors (e.g. expired credentials), the circuit opens and the backend is excluded from request routing until recovery is detected via a probe request.

type BackendCircuitBreakerConfig struct {
    Enabled          bool          `yaml:"enabled"`           // Enable per-backend circuit breakers (default: false)
    FailureThreshold int           `yaml:"failure_threshold"` // Consecutive failures before opening (default: 5)
    OpenTimeout      time.Duration `yaml:"open_timeout"`      // Delay before probing recovery (default: 5m)
}

type BackendConfig

BackendConfig holds configuration for an S3-compatible storage backend.

type BackendConfig struct {
    Name            string `yaml:"name"`              // Identifier for metrics/tracing
    Endpoint        string `yaml:"endpoint"`          // S3-compatible endpoint URL
    Region          string `yaml:"region"`            // AWS region or equivalent
    Bucket          string `yaml:"bucket"`            // Target bucket name
    AccessKeyID     string `yaml:"access_key_id"`     // AWS access key ID (required when credential_source is "static")
    SecretAccessKey string `yaml:"secret_access_key"` // AWS secret access key (required when credential_source is "static")
    // CredentialSource selects how credentials are resolved: "static" (default, uses keys above) or "default_chain" (AWS SDK chain: env, IMDS, SSO, STS).
    CredentialSource string `yaml:"credential_source"`
    ForcePathStyle   bool   `yaml:"force_path_style"`   // Use path-style URLs
    UnsignedPayload  *bool  `yaml:"unsigned_payload"`   // Skip SigV4 payload hash to stream uploads without buffering (default: true)
    DisableChecksum  bool   `yaml:"disable_checksum"`   // Disable SDK default checksums for GCS and other providers that reject them (default: false)
    StripSDKHeaders  bool   `yaml:"strip_sdk_headers"`  // Remove SDK v2 headers (amz-sdk-*, accept-encoding, x-id) before signing for GCS compatibility (default: false)
    QuotaBytes       int64  `yaml:"quota_bytes"`        // Maximum bytes allowed on this backend (0 = unlimited)
    MaxObjectSize    int64  `yaml:"max_object_size"`    // Maximum size of a single object in bytes (0 = unlimited)
    APIRequestLimit  int64  `yaml:"api_request_limit"`  // Monthly API request limit (0 = unlimited)
    EgressByteLimit  int64  `yaml:"egress_byte_limit"`  // Monthly egress byte limit (0 = unlimited)
    IngressByteLimit int64  `yaml:"ingress_byte_limit"` // Monthly ingress byte limit (0 = unlimited)
}

type BucketConfig

BucketConfig defines a virtual bucket with one or more credential sets. Multiple services can share a bucket by each having their own credentials.

type BucketConfig struct {
    Name                string             `yaml:"name"`
    Credentials         []CredentialConfig `yaml:"credentials"`
    MaxMultipartUploads int                `yaml:"max_multipart_uploads"` // Max active multipart uploads per bucket (0 = unlimited)
}

type CacheConfig

CacheConfig holds settings for the object data cache.

type CacheConfig struct {
    Enabled       bool          `yaml:"enabled"`         // Enable the object data cache (default: false)
    MaxSize       string        `yaml:"max_size"`        // Maximum total cache size (e.g., "256MB", "1GB")
    MaxObjectSize string        `yaml:"max_object_size"` // Maximum cacheable object size (e.g., "10MB"); 0 = no limit
    TTL           time.Duration `yaml:"ttl"`             // Time before a cached entry expires (default: 5m)

    // Parsed values (not from YAML)
    MaxSizeBytes       int64 `yaml:"-"`
    MaxObjectSizeBytes int64 `yaml:"-"`
}

type CircuitBreakerConfig

CircuitBreakerConfig holds settings for the database circuit breaker. When the database becomes unreachable, the proxy enters degraded mode: reads broadcast to all backends, writes return 503.

type CircuitBreakerConfig struct {
    FailureThreshold  int           `yaml:"failure_threshold"`  // Consecutive failures before opening (default: 3)
    OpenTimeout       time.Duration `yaml:"open_timeout"`       // Delay before probing recovery (default: 15s)
    CacheTTL          time.Duration `yaml:"cache_ttl"`          // TTL for key->backend cache during degraded reads (default: 60s)
    ParallelBroadcast bool          `yaml:"parallel_broadcast"` // Fan-out reads to all backends in parallel during degraded mode (default: false)
    // DegradedBroadcastParallelism caps the number of backends probed
    // concurrently during a parallel degraded-mode broadcast. 0 means no
    // cap (every configured backend is probed at once, the historical
    // behaviour). With a positive value, probes run as a rolling window:
    // the first N are launched immediately, and each failure replenishes
    // the next pending backend so at most N goroutines are in flight at
    // any time. Only meaningful when ParallelBroadcast is true.
    DegradedBroadcastParallelism int `yaml:"degraded_broadcast_parallelism"`
    // DegradedReadsEnabled opts out of degraded-mode broadcasts (default true; set false to fail fast on DB outage).
    DegradedReadsEnabled *bool `yaml:"degraded_reads_enabled"`
}

type CleanupQueueConfig

CleanupQueueConfig holds settings for the background orphan cleanup worker and multipart upload housekeeping.

ClaimGracePeriod controls how long a per-row claim stamp held by an instance remains exclusive before another instance is allowed to reclaim the row. A short value lets a crashed worker’s rows recover quickly at the cost of a higher chance of duplicate processing if a real worker is merely slow; a long value is the inverse trade-off. The 5-minute default covers the realistic worst case for a single backend DELETE plus its retry budget within one tick. Hot-reloadable.

type CleanupQueueConfig struct {
    Concurrency           int           `yaml:"concurrency"`             // Parallel cleanup deletions (default: 10)
    MultipartStaleTimeout time.Duration `yaml:"multipart_stale_timeout"` // Abandon multipart uploads older than this (default: 24h)
    ClaimGracePeriod      time.Duration `yaml:"claim_grace_period"`      // Reclaim stale per-row claims older than this (default: 5m)
}

type Config

Config holds the complete service configuration.

type Config struct {
    Server                ServerConfig                `yaml:"server"`
    Buckets               []BucketConfig              `yaml:"buckets"`
    Database              DatabaseConfig              `yaml:"database"`
    Backends              []BackendConfig             `yaml:"backends"`
    Telemetry             TelemetryConfig             `yaml:"telemetry"`
    Rebalance             RebalanceConfig             `yaml:"rebalance"`
    Replication           ReplicationConfig           `yaml:"replication"`
    RateLimit             RateLimitConfig             `yaml:"rate_limit"`
    CircuitBreaker        CircuitBreakerConfig        `yaml:"circuit_breaker"`
    BackendCircuitBreaker BackendCircuitBreakerConfig `yaml:"backend_circuit_breaker"`
    Encryption            EncryptionConfig            `yaml:"encryption"`
    UI                    UIConfig                    `yaml:"ui"`
    CleanupQueue          CleanupQueueConfig          `yaml:"cleanup_queue"`
    WritePath             WritePathConfig             `yaml:"write_path"`
    UsageFlush            UsageFlushConfig            `yaml:"usage_flush"`
    Lifecycle             LifecycleConfig             `yaml:"lifecycle"`
    Reconcile             ReconcileConfig             `yaml:"reconcile"`
    Integrity             IntegrityConfig             `yaml:"integrity"`
    Cache                 CacheConfig                 `yaml:"cache"`
    Redis                 *RedisConfig                `yaml:"redis"`
    Notifications         NotificationConfig          `yaml:"notifications"`
    RoutingStrategy       RoutingStrategy             `yaml:"routing_strategy"` // "pack" (default) or "spread"
}

func LoadConfig

func LoadConfig(path string) (*Config, error)

LoadConfig reads and parses the configuration file with environment variable expansion. Returns an error if the file cannot be read, parsed, or validated.

func (*Config) SetDefaultsAndValidate

func (c *Config) SetDefaultsAndValidate() error

SetDefaultsAndValidate applies default values for optional fields and checks that all required configuration values are present. Delegates to per-type validators and performs cross-field validation.

type CredentialConfig

CredentialConfig holds a single set of client credentials for accessing a virtual bucket. Supports SigV4 (access_key_id + secret_access_key) or legacy token auth.

type CredentialConfig struct {
    AccessKeyID     string `yaml:"access_key_id"`
    SecretAccessKey string `yaml:"secret_access_key"`
    Token           string `yaml:"token"`
}

type DatabaseConfig

DatabaseConfig holds metadata store connection settings. The Driver field selects between “sqlite” (embedded, zero-dependency default) and “postgres” (required for multi-instance deployments).

type DatabaseConfig struct {
    Driver          string        `yaml:"driver"` // "sqlite" or "postgres" (default: inferred from config)
    Path            string        `yaml:"path"`   // SQLite file path (default: "s3-orchestrator.db")
    Host            string        `yaml:"host"`
    Port            int           `yaml:"port"`
    Database        string        `yaml:"database"`
    User            string        `yaml:"user"`
    Password        string        `yaml:"password"` //nolint:gosec // G117: config struct field, not a hardcoded credential
    SSLMode         string        `yaml:"ssl_mode"`
    MaxConns        int32         `yaml:"max_conns"`         // Max pool connections (default: 50; size to 2-3x max concurrent requests)
    MinConns        int32         `yaml:"min_conns"`         // Min idle connections (default: 5)
    MaxConnLifetime time.Duration `yaml:"max_conn_lifetime"` // Max connection age (default: 5m)
}

func (*DatabaseConfig) ConnectionString

func (c *DatabaseConfig) ConnectionString() string

ConnectionString returns a PostgreSQL connection URI with properly escaped credentials, safe for passwords containing special characters.

type EncryptionConfig

EncryptionConfig holds settings for server-side envelope encryption. When enabled, objects are encrypted with per-object DEKs using chunked AES-256-GCM before being stored on backends. Exactly one key source (master_key, master_key_file, or vault) must be configured.

type EncryptionConfig struct {
    Enabled       bool                `yaml:"enabled"`
    ChunkSize     int                 `yaml:"chunk_size"`      // Plaintext bytes per chunk (default: 65536, range: 4KB-1MB, must be power of 2)
    MasterKey     string              `yaml:"master_key"`      // Base64-encoded 256-bit key (inline or via env var)
    MasterKeyFile string              `yaml:"master_key_file"` // Path to file containing raw 32-byte key
    Vault         *VaultTransitConfig `yaml:"vault"`           // Vault Transit key management
    PreviousKeys  []string            `yaml:"previous_keys"`   // Base64-encoded previous master keys for rotation (unwrap only)
}

type IntegrityConfig

IntegrityConfig holds settings for object integrity verification. When enabled, objects are checksummed on write and optionally verified on read and during replication.

type IntegrityConfig struct {
    Enabled           bool          `yaml:"enabled"`             // Enable integrity verification (default: false)
    VerifyOnRead      bool          `yaml:"verify_on_read"`      // Hash-check every GET response (default: false)
    VerifyOnReplicate *bool         `yaml:"verify_on_replicate"` // Hash-check before recording a replica (default: true when enabled)
    ScrubberInterval  time.Duration `yaml:"scrubber_interval"`   // Background verification interval (0 = disabled)
    ScrubberBatchSize int           `yaml:"scrubber_batch_size"` // Objects per scrub cycle (default: 100)
}

func (*IntegrityConfig) ShouldVerifyOnReplicate

func (ic *IntegrityConfig) ShouldVerifyOnReplicate() bool

ShouldVerifyOnReplicate returns whether replication copies should be hash-verified. Defaults to true when integrity is enabled.

type LifecycleConfig

LifecycleConfig holds rules for automatic object expiration. Objects matching a rule’s prefix that are older than expiration_days are deleted by a background worker. Empty rules list disables lifecycle processing.

type LifecycleConfig struct {
    Rules     []LifecycleRule `yaml:"rules"`
    BatchSize int             `yaml:"batch_size"` // objects per DB query (default 100)
}

type LifecycleRule

LifecycleRule defines a single object expiration rule.

type LifecycleRule struct {
    Prefix         string `yaml:"prefix"`
    ExpirationDays int    `yaml:"expiration_days"`
}

type MetricsConfig

MetricsConfig holds Prometheus metrics settings.

Pprof is opt-in and off by default. The net/http/pprof handlers expose deep runtime state (de-anonymized stack frames, command-line flags, on-demand CPU profiles that double as DoS amplifiers), so production deployments should leave Pprof false. When enabled, it is only mounted on the dedicated metrics listener (Listen must be set) - never on the main S3 listener.

type MetricsConfig struct {
    Enabled bool   `yaml:"enabled"`
    Path    string `yaml:"path"`
    Listen  string `yaml:"listen"` // Separate listener address (e.g. "127.0.0.1:9091"); if empty, metrics are served on the main listener
    Pprof   bool   `yaml:"pprof"`  // Mount /debug/pprof/* on the metrics listener. Off by default; requires Listen to be set.
}

type NotificationConfig

NotificationConfig holds the list of webhook endpoints for event delivery. An empty Endpoints slice disables notifications entirely.

type NotificationConfig struct {
    Endpoints []NotificationEndpoint `yaml:"endpoints"`
}

type NotificationEndpoint

NotificationEndpoint configures a single webhook destination.

type NotificationEndpoint struct {
    URL        string        `yaml:"url"`         // Webhook URL (required)
    Events     []string      `yaml:"events"`      // Event type patterns with wildcard support (required)
    Prefix     string        `yaml:"prefix"`      // Only emit data events for keys matching this prefix (optional)
    Secret     string        `yaml:"secret"`      //nolint:gosec // G117: config struct, not a hardcoded credential
    Timeout    time.Duration `yaml:"timeout"`     // HTTP request timeout (default: 5s)
    MaxRetries int           `yaml:"max_retries"` // Delivery attempts before dropping (default: 3)
}

type PendingPatternConfig

PendingPatternConfig configures the pending-row pattern used by the write path to avoid losing the prior copy of an overwritten key when the metadata commit fails.

type PendingPatternConfig struct {
    Enabled    *bool         `yaml:"enabled"`     // Default: true. Set to false to disable.
    ReaperTick time.Duration `yaml:"reaper_tick"` // How often the reaper resolves abandoned intents (default: 1m)
    MinAge     time.Duration `yaml:"min_age"`     // Don't reap intents younger than this  -  guards in-flight PUTs (default: 5m)
    BatchSize  int           `yaml:"batch_size"`  // Max intents resolved per tick (default: 50)
}

func (*PendingPatternConfig) IsEnabled

func (p *PendingPatternConfig) IsEnabled() bool

IsEnabled returns true unless the operator has explicitly disabled the pending pattern. The pointer-typed Enabled field lets the YAML loader distinguish “absent” (default true) from “explicitly false”.

type RateLimitConfig

RateLimitConfig holds per-IP rate limiting settings. Disabled by default.

type RateLimitConfig struct {
    Enabled         bool          `yaml:"enabled"`
    RequestsPerSec  float64       `yaml:"requests_per_sec"` // Token refill rate (default: 100)
    Burst           int           `yaml:"burst"`            // Max burst size (default: 200)
    TrustedProxies  []string      `yaml:"trusted_proxies"`  // CIDRs whose X-Forwarded-For is trusted (e.g. ["10.0.0.0/8", "172.16.0.0/12"])
    CleanupInterval time.Duration `yaml:"cleanup_interval"` // How often stale entries are evicted (default: 1m)
    CleanupMaxAge   time.Duration `yaml:"cleanup_max_age"`  // Entries older than this are evicted (default: 5m)
}

type RebalanceConfig

RebalanceConfig holds settings for the periodic backend rebalancer. Disabled by default to avoid unexpected API calls and egress charges.

type RebalanceConfig struct {
    Enabled     bool          `yaml:"enabled"`
    Strategy    string        `yaml:"strategy"` // "pack" or "spread"
    Interval    time.Duration `yaml:"interval"`
    BatchSize   int           `yaml:"batch_size"`
    Threshold   float64       `yaml:"threshold"`   // min utilization spread to trigger
    Concurrency int           `yaml:"concurrency"` // parallel moves (default: 5)
}

type ReconcileConfig

ReconcileConfig controls the background orphan reconciler that periodically scans backends and imports untracked objects into the metadata database. Disabled by default.

type ReconcileConfig struct {
    Enabled  bool          `yaml:"enabled"`
    Interval time.Duration `yaml:"interval"` // How often to run (default: 24h)
}

type RedisConfig

RedisConfig holds optional Redis connection settings for shared usage counters in multi-instance deployments. When omitted, counters are stored in local memory (single-instance default).

type RedisConfig struct {
    Address          string        `yaml:"address"`           // Redis address (host:port)
    Password         string        `yaml:"password"`          //nolint:gosec // G117: config struct, not a hardcoded credential
    DB               int           `yaml:"db"`                // Redis database number (default: 0)
    TLS              bool          `yaml:"tls"`               // Use TLS for Redis connection
    KeyPrefix        string        `yaml:"key_prefix"`        // Key prefix for namespacing (default: "s3orch")
    FailureThreshold int           `yaml:"failure_threshold"` // Consecutive failures before circuit opens (default: 3)
    OpenTimeout      time.Duration `yaml:"open_timeout"`      // Delay before probing recovery (default: 15s)
}

type ReplicationConfig

ReplicationConfig holds settings for the background replication worker. When factor is 1, replication is disabled and behavior is identical to the single-copy default.

type ReplicationConfig struct {
    Factor             int           `yaml:"factor"`
    WorkerInterval     time.Duration `yaml:"worker_interval"`
    BatchSize          int           `yaml:"batch_size"`
    Concurrency        int           `yaml:"concurrency"`         // Parallel object replications (default: 5)
    UnhealthyThreshold time.Duration `yaml:"unhealthy_threshold"` // Grace period before replacing copies on circuit-broken backends (default: 10m)
}

type RoutingStrategy

RoutingStrategy determines how write operations select a target backend.

type RoutingStrategy string

RoutingPack and related constants used by this package.

const (
    // RoutingPack fills backends in order, returning the first with space.
    RoutingPack RoutingStrategy = "pack"

    // RoutingSpread distributes writes across backends by utilization ratio.
    RoutingSpread RoutingStrategy = "spread"
)

type ServerConfig

ServerConfig holds HTTP server settings.

type ServerConfig struct {
    ListenAddr            string        `yaml:"listen_addr"`
    LogLevel              string        `yaml:"log_level"`               // Log level: debug, info, warn, error (default: info)
    MaxObjectSize         int64         `yaml:"max_object_size"`         // Max upload size in bytes (default: 5GB)
    MaxConcurrentRequests int           `yaml:"max_concurrent_requests"` // Max concurrent S3 requests (default: 1000)
    MaxConcurrentReads    int           `yaml:"max_concurrent_reads"`    // Max concurrent read requests (0 = use global limit)
    MaxConcurrentWrites   int           `yaml:"max_concurrent_writes"`   // Max concurrent write requests (0 = use global limit)
    LoadShedThreshold     float64       `yaml:"load_shed_threshold"`     // Active shedding threshold (0.0-1.0, 0 = disabled)
    AdmissionWait         time.Duration `yaml:"admission_wait"`          // Brief wait before rejection (0 = instant reject)
    BackendTimeout        time.Duration `yaml:"backend_timeout"`         // Per-operation timeout for backend S3 calls (default: 30s)
    ReadHeaderTimeout     time.Duration `yaml:"read_header_timeout"`     // Max time to read request headers (default: 10s)
    ReadTimeout           time.Duration `yaml:"read_timeout"`            // Max time to read entire request including body (default: 5m)
    WriteTimeout          time.Duration `yaml:"write_timeout"`           // Max time to write response (default: 5m)
    IdleTimeout           time.Duration `yaml:"idle_timeout"`            // Max time to wait for next request on keep-alive (default: 120s)
    ShutdownDelay         time.Duration `yaml:"shutdown_delay"`          // Delay before HTTP drain on SIGTERM for LB deregistration (default: 0)
    TLS                   TLSConfig     `yaml:"tls"`
}

type TLSConfig

TLSConfig holds optional TLS settings for the HTTP server. When CertFile and KeyFile are both set, the server listens with TLS. When both are empty, the server runs plain HTTP for backward compatibility.

type TLSConfig struct {
    CertFile     string `yaml:"cert_file"`      // Path to PEM-encoded certificate (or chain)
    KeyFile      string `yaml:"key_file"`       // Path to PEM-encoded private key
    MinVersion   string `yaml:"min_version"`    // Minimum TLS version: "1.2" (default) or "1.3"
    ClientCAFile string `yaml:"client_ca_file"` // Path to CA bundle for client certificate verification (mTLS)
}

type TelemetryConfig

TelemetryConfig holds observability settings.

type TelemetryConfig struct {
    Metrics MetricsConfig `yaml:"metrics"`
    Tracing TracingConfig `yaml:"tracing"`
}

type TracingConfig

TracingConfig holds OpenTelemetry tracing settings.

type TracingConfig struct {
    Enabled    bool    `yaml:"enabled"`
    Endpoint   string  `yaml:"endpoint"`
    SampleRate float64 `yaml:"sample_rate"`
    Insecure   bool    `yaml:"insecure"` // Use insecure connection (no TLS)
}

type UIConfig

UIConfig holds settings for the built-in web dashboard. Disabled by default.

type UIConfig struct {
    Enabled            bool   `yaml:"enabled"`
    Path               string `yaml:"path"`                 // URL prefix for the dashboard (default: "/ui")
    AdminKey           string `yaml:"admin_key"`            // Access key for dashboard login
    AdminSecret        string `yaml:"admin_secret"`         // Secret key for dashboard login (plaintext or bcrypt hash)
    AdminToken         string `yaml:"admin_token"`          // Separate token for admin API (defaults to admin_key if empty)
    SessionSecret      string `yaml:"session_secret"`       //nolint:gosec // G117: config struct, not a hardcoded credential  -  HMAC key for session cookie derivation (independent of admin_secret)
    ForceSecureCookies bool   `yaml:"force_secure_cookies"` // Always set Secure flag on session cookies (use behind TLS-terminating proxy)
}

type UsageFlushConfig

UsageFlushConfig holds settings for the periodic usage counter flush to the database. When adaptive flushing is enabled, the flush interval shortens automatically when any backend approaches a usage limit.

type UsageFlushConfig struct {
    Interval          time.Duration `yaml:"interval"`           // Base flush interval (default: 30s)
    AdaptiveEnabled   bool          `yaml:"adaptive_enabled"`   // Shorten interval near limits
    AdaptiveThreshold float64       `yaml:"adaptive_threshold"` // Ratio to trigger fast flush (default: 0.8)
    FastInterval      time.Duration `yaml:"fast_interval"`      // Interval when near limits (default: 5s)
}

type VaultTransitConfig

VaultTransitConfig holds settings for HashiCorp Vault Transit key management.

type VaultTransitConfig struct {
    Address       string        `yaml:"address"`        // Vault server URL
    Token         string        `yaml:"token"`          // Vault token (or via env var)
    TokenFile     string        `yaml:"token_file"`     // Path to file containing Vault token (re-read on each renewal tick; for Nomad workload identity)
    KeyName       string        `yaml:"key_name"`       // Transit key name
    MountPath     string        `yaml:"mount_path"`     // Transit mount path (default: "transit")
    CACert        string        `yaml:"ca_cert"`        // Path to PEM CA certificate for TLS verification
    RenewInterval time.Duration `yaml:"renew_interval"` // Token renewal check interval (default: 5m)
}

type WritePathConfig

WritePathConfig gates write-path correctness features. The pending-row pattern (PUT-before-COMMIT intent tracking) is on by default; operators can disable it to fall back to the legacy delete-on-record-failure path, which trades data-loss safety for one fewer round-trip per PUT.

type WritePathConfig struct {
    PendingPattern PendingPatternConfig `yaml:"pending_pattern"`
}

Generated by gomarkdoc