// Package config читает конфигурацию сервиса из переменных окружения. package config import ( "fmt" "time" "github.com/caarlos0/env/v11" ) // API — конфигурация публичного сервиса api. type API struct { HTTPAddr string `env:"HTTP_ADDR" envDefault:":8080"` DatabaseURL string `env:"DATABASE_URL,required"` RedisURL string `env:"REDIS_URL,required"` LogLevel string `env:"LOG_LEVEL" envDefault:"info"` MigrateOnStart bool `env:"MIGRATE_ON_START" envDefault:"true"` ShutdownTimeout time.Duration `env:"SHUTDOWN_TIMEOUT" envDefault:"15s"` SupportedLocales []string `env:"SUPPORTED_LOCALES" envDefault:"ru,en" envSeparator:","` MinAndroidVersionCode int `env:"MIN_ANDROID_VERSION_CODE" envDefault:"0"` // JWTPrivateKey — Ed25519 (base64: 32-байтовый seed или 64-байтовый ключ). Пусто — случайный ключ // на время жизни процесса: после перезапуска всем придётся обновить access-токен (refresh остаётся). JWTPrivateKey string `env:"JWT_PRIVATE_KEY"` // JWTPreviousKeys — прежние ключи через запятую: токены, подписанные ими, ещё принимаются. JWTPreviousKeys []string `env:"JWT_PREVIOUS_KEYS" envSeparator:","` AccessTokenTTL time.Duration `env:"ACCESS_TOKEN_TTL" envDefault:"15m"` // CookieSecure — флаг Secure у refresh-cookie. Отключать только для разработки по http не на localhost. CookieSecure bool `env:"COOKIE_SECURE" envDefault:"true"` BootstrapAdminUsername string `env:"BOOTSTRAP_ADMIN_USERNAME" envDefault:"admin"` BootstrapAdminPassword string `env:"BOOTSTRAP_ADMIN_PASSWORD"` // LibraryRoot — точки монтирования NFS-хранилищ (общий каталог с storage-agent). LibraryRoot string `env:"LIBRARY_ROOT" envDefault:"/library"` // LibraryHostRoot — LIBRARY_HOST внутри контейнера: local-хранилища — его подпапки. LibraryHostRoot string `env:"LIBRARY_HOST_ROOT" envDefault:"/library-host"` StorageAgentURL string `env:"STORAGE_AGENT_URL" envDefault:"http://storage-agent:8090"` InternalToken string `env:"INTERNAL_TOKEN"` FFprobePath string `env:"FFPROBE_PATH" envDefault:"ffprobe"` // SigningKey — ключ подписи ссылок на обложки и стрим (base64, ≥ 16 байт). Пусто — случайный до перезапуска. SigningKey string `env:"STREAM_SIGNING_KEY"` CacheDir string `env:"CACHE_DIR" envDefault:"/cache"` FFmpegPath string `env:"FFMPEG_PATH" envDefault:"ffmpeg"` // XAccel — файлы отдаёт nginx по X-Accel-Redirect; false — для запуска api без nginx. XAccel bool `env:"X_ACCEL" envDefault:"true"` // TranscodeConcurrency — параллельных ffmpeg; 0 — половина ядер. TranscodeConcurrency int `env:"TRANSCODE_CONCURRENCY" envDefault:"0"` TranscodeCacheLimitGB int `env:"TRANSCODE_CACHE_LIMIT_GB" envDefault:"50"` RecommenderURL string `env:"RECOMMENDER_URL" envDefault:"http://recommender:8000"` MeiliURL string `env:"MEILI_URL" envDefault:"http://meilisearch:7700"` MeiliMasterKey string `env:"MEILI_MASTER_KEY"` // Самообновление Android: сервер читает релизы Gitea своим токеном и кэширует APK в UpdatesDir. GiteaURL string `env:"GITEA_URL"` GiteaRepo string `env:"GITEA_REPO"` GiteaToken string `env:"GITEA_TOKEN"` UpdatesDir string `env:"UPDATES_DIR" envDefault:"/updates"` } // StorageAgent — конфигурация внутреннего сервиса storage-agent. type StorageAgent struct { HTTPAddr string `env:"HTTP_ADDR" envDefault:":8090"` InternalToken string `env:"INTERNAL_TOKEN,required,notEmpty"` LibraryRoot string `env:"LIBRARY_ROOT" envDefault:"/library"` LogLevel string `env:"LOG_LEVEL" envDefault:"info"` ShutdownTimeout time.Duration `env:"SHUTDOWN_TIMEOUT" envDefault:"15s"` } // Load заполняет структуру конфигурации T из окружения. func Load[T any]() (T, error) { var cfg T if err := env.Parse(&cfg); err != nil { return cfg, fmt.Errorf("config: %w", err) } return cfg, nil }