package config import ( "os" "strings" "github.com/joho/godotenv" ) type Config struct { AppEnv string ServerPort string DatabaseURL string RedisURL string S3Endpoint string S3PublicEndpoint string S3AccessKey string S3SecretKey string S3Bucket string JWTSecret string JWTRefreshSecret string CloudPaymentsPublicID string CloudPaymentsAPISecret string AllowedOrigins []string } func Load() *Config { godotenv.Load() cfg := &Config{ AppEnv: getEnv("APP_ENV", "development"), ServerPort: getEnv("SERVER_PORT", "8080"), DatabaseURL: buildDatabaseURL(), RedisURL: buildRedisURL(), S3Endpoint: getEnv("S3_ENDPOINT", "http://localhost:9000"), S3PublicEndpoint: getEnv("S3_PUBLIC_ENDPOINT", "http://localhost:9000"), S3AccessKey: getEnv("S3_ACCESS_KEY", "photoplaces"), S3SecretKey: getSecret("S3_SECRET_KEY", "photoplaces_dev"), S3Bucket: getEnv("S3_BUCKET", "photoplaces"), JWTSecret: getSecret("JWT_SECRET", "dev-secret"), JWTRefreshSecret: getSecret("JWT_REFRESH_SECRET", "dev-refresh-secret"), CloudPaymentsPublicID: getEnv("CLOUDPAYMENTS_PUBLIC_ID", ""), CloudPaymentsAPISecret: getEnv("CLOUDPAYMENTS_API_SECRET", ""), AllowedOrigins: strings.Split(getEnv("ALLOWED_ORIGINS", "http://localhost:3000"), ","), } return cfg } func getEnv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } func getSecret(key, fallback string) string { // Try _FILE variant first (Docker secrets) if v := os.Getenv(key + "_FILE"); v != "" { content, err := os.ReadFile(v) if err == nil { return strings.TrimSpace(string(content)) } } // Fallback to env var if v := os.Getenv(key); v != "" { return v } return fallback } func buildDatabaseURL() string { // If DATABASE_URL is explicitly set, use it if v := os.Getenv("DATABASE_URL"); v != "" { return v } // Build from components with secret from file password := getSecret("DB_PASSWORD", "photoplaces_dev") return "postgres://photoplaces:" + password + "@postgres:5432/photoplaces?sslmode=disable" } func buildRedisURL() string { if v := os.Getenv("REDIS_URL"); v != "" { return v } password := getSecret("REDIS_PASSWORD", "") if password != "" { return "redis://:" + password + "@redis:6379/0" } return "redis://redis:6379/0" }