package config import ( "encoding/base64" "fmt" "os" "strconv" ) type Config struct { HTTPAddr string DatabaseURL string AuthUser string AuthPass string EncKey []byte SessionSecret []byte WorkerConcurrency int } func Load() (Config, error) { c := Config{ HTTPAddr: getenv("HTTP_ADDR", ":8080"), DatabaseURL: os.Getenv("DATABASE_URL"), AuthUser: os.Getenv("AUTH_USER"), AuthPass: os.Getenv("AUTH_PASS"), SessionSecret: []byte(os.Getenv("SESSION_SECRET")), WorkerConcurrency: 4, } if v := os.Getenv("WORKER_CONCURRENCY"); v != "" { n, err := strconv.Atoi(v) if err != nil || n < 1 { return Config{}, fmt.Errorf("WORKER_CONCURRENCY invalid: %q", v) } c.WorkerConcurrency = n } for k, v := range map[string]string{ "DATABASE_URL": c.DatabaseURL, "AUTH_USER": c.AuthUser, "AUTH_PASS": c.AuthPass, "SESSION_SECRET": string(c.SessionSecret), } { if v == "" { return Config{}, fmt.Errorf("%s is required", k) } } key, err := base64.StdEncoding.DecodeString(os.Getenv("ENC_KEY")) if err != nil { return Config{}, fmt.Errorf("ENC_KEY must be base64: %w", err) } if len(key) != 32 { return Config{}, fmt.Errorf("ENC_KEY must decode to 32 bytes, got %d", len(key)) } c.EncKey = key return c, nil } func getenv(k, def string) string { if v := os.Getenv(k); v != "" { return v } return def }