package config import ( "fmt" "os" "strconv" ) type Config struct { AdminToken string DeployRoot string ReleaseRoot string DBPath string MaxUploadSize int64 LogLevel string ReleasesToKeep int DisableFileDeleteOnUserRemove bool TLSCert string TLSKey string } func LoadConfig() (*Config, error) { cfg := &Config{ AdminToken: os.Getenv("ADMIN_TOKEN"), DeployRoot: getEnvOrDefault("DEPLOY_ROOT", "/var/www/docs"), ReleaseRoot: getEnvOrDefault("RELEASE_ROOT", "/var/www/deploys"), DBPath: getEnvOrDefault("DB_PATH", "/data/deployer.db"), MaxUploadSize: getEnvAsInt64("MAX_UPLOAD_SIZE", 104857600), LogLevel: getEnvOrDefault("LOG_LEVEL", "info"), ReleasesToKeep: getEnvAsInt("RELEASES_TO_KEEP", 5), DisableFileDeleteOnUserRemove: getEnvAsBool("DISABLE_FILE_DELETE_ON_USER_REMOVE", false), TLSCert: os.Getenv("TLS_CERT"), TLSKey: os.Getenv("TLS_KEY"), } if err := cfg.validate(); err != nil { return nil, err } return cfg, nil } func (c *Config) validate() error { if c.AdminToken == "" { return fmt.Errorf("ADMIN_TOKEN is required") } validLogLevels := map[string]bool{ "debug": true, "info": true, "warn": true, "error": true, } if !validLogLevels[c.LogLevel] { return fmt.Errorf("invalid LOG_LEVEL: %s (must be debug, info, warn, or error)", c.LogLevel) } if c.MaxUploadSize <= 0 { return fmt.Errorf("MAX_UPLOAD_SIZE must be positive") } if c.ReleasesToKeep < 1 { return fmt.Errorf("RELEASES_TO_KEEP must be at least 1") } return nil } func getEnvOrDefault(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } func getEnvAsInt(key string, defaultValue int) int { valueStr := os.Getenv(key) if valueStr == "" { return defaultValue } value, err := strconv.Atoi(valueStr) if err != nil { return defaultValue } return value } func getEnvAsInt64(key string, defaultValue int64) int64 { valueStr := os.Getenv(key) if valueStr == "" { return defaultValue } value, err := strconv.ParseInt(valueStr, 10, 64) if err != nil { return defaultValue } return value } func getEnvAsBool(key string, defaultValue bool) bool { valueStr := os.Getenv(key) if valueStr == "" { return defaultValue } value, err := strconv.ParseBool(valueStr) if err != nil { return defaultValue } return value }