数据库+redis+meilisearch+s3+EQURL 配置全部走环境变量,不在代码层硬编码

This commit is contained in:
eafonyang
2026-07-13 14:16:05 +08:00
parent c1547f9a8f
commit 4f1da3675b
9 changed files with 80 additions and 215 deletions
+31 -20
View File
@@ -1,35 +1,46 @@
# Server
APP_ENV=development
APP_ENV=production
APP_HOST=0.0.0.0
APP_PORT=8080
# Gin mode: debug | release | test
GIN_MODE=debug
GIN_MODE=release
# Database (development reads from env, default host 192.168.9.127)
DATABASE_HOST=192.168.9.127
# Database
DATABASE_HOST=database-1.chmuueamo72p.eu-central-1.rds.amazonaws.com
DATABASE_PORT=3306
DATABASE_NAME=audio
DATABASE_USER=root
DATABASE_PASSWORD=root123
DATABASE_PASSWORD="young9#!UJsD219921031"
# Meilisearch (development defaults apply when APP_ENV=development and vars are unset)
# MEILISEARCH_HOST=http://ec2-18-184-205-87.eu-central-1.compute.amazonaws.com:7700
# MEILISEARCH_API_KEY=your-api-key
# MEILISEARCH_INDEX=models
# Meilisearch
MEILISEARCH_HOST=http://ip-172-31-13-240.eu-central-1.compute.internal:7700
MEILISEARCH_API_KEY="young9#!UJsD219921031"
MEILISEARCH_INDEX=models
# Redis (development reads from env, default host 192.168.9.127)
REDIS_HOST=192.168.9.127
# Redis
REDIS_HOST=172.31.13.240
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_PASSWORD=eafon123!
REDIS_DATABASE=1
# Share code TTL (bare number = minutes; suffix: m/h/d), e.g. 30, 30m, 24h, 30d
SHARE_CODE_TTL_MIN=30
# SHARE_CODE_MAX_PER_MAC=1
# Equalize API
EQ_API_URL=http://172.31.18.70:8000/equalize
EQ_EXTERNAL_API_URL=https://autoeq.app/equalize
# S3 (local development only; production uses EC2 IAM role)
# AWS_REGION=eu-central-1
# S3_BUCKET=luxsin-app-bucket
# AWS_ACCESS_KEY_ID=your-access-key-id
# AWS_SECRET_ACCESS_KEY=your-secret-access-key
# Share code TTL (bare number = minutes; suffix: m/h/d), e.g. 30, 30m, 24h, 30d
#一个用户在有效期内至多可以创建多少个分享码
SHARE_CODE_MAX_PER_MAC=10
#分享码有效期
SHARE_CODE_TTL_MIN=30d
# S3 (生产环境使用 EC2 IAM role 时,可不设置 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY)
AWS_REGION=eu-central-1
S3_BUCKET=luxsin-app-bucket
AWS_ACCESS_KEY_ID=AKIAVMFK45I6P3TNI3VJ
AWS_SECRET_ACCESS_KEY=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
# Persist tasks
ENABLE_PERSIST_TASK=false
ENABLE_IMPEDANCE_PERSIST_TASK=false
-19
View File
@@ -1,19 +0,0 @@
APP_ENV=production
APP_HOST=0.0.0.0
APP_PORT=8080
GIN_MODE=release
# Production uses built-in RDS host when DATABASE_HOST is unset.
# Password must be set via environment variable (never commit real password).
# jdbc:mysql://database-1.chmuueamo72p.eu-central-1.rds.amazonaws.com:3306/audio?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
# young9#!UJsD219921031
# root
DATABASE_PASSWORD=your-production-password
# S3 (uses EC2 IAM role; do not set access keys in production)
AWS_REGION=eu-central-1
S3_BUCKET=luxsin-app-bucket
# Share code TTL (bare number = minutes; suffix: m/h/d), e.g. 30, 30m, 24h, 30d
SHARE_CODE_TTL_MIN=30
+2 -13
View File
@@ -7,19 +7,8 @@ services:
restart: always
ports:
- "8084:8080"
environment:
- APP_ENV=production
- APP_HOST=0.0.0.0
- APP_PORT=8080
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
- REDIS_PASSWORD=${REDIS_PASSWORD:-eafon123!}
- MEILISEARCH_API_KEY=${MEILISEARCH_API_KEY:-young9#!UJsD219921031}
- ENABLE_PERSIST_TASK=false
- ENABLE_IMPEDANCE_PERSIST_TASK=false
- AWS_REGION=eu-central-1
- S3_BUCKET=luxsin-app-bucket
- SHARE_CODE_MAX_PER_MAC=${SHARE_CODE_MAX_PER_MAC:-1}
- SHARE_CODE_TTL_MIN=${SHARE_CODE_TTL_MIN:-30}
env_file:
- .env
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:8080/api/v1/health"]
interval: 30s
+24 -24
View File
@@ -8,18 +8,18 @@ import (
)
type Config struct {
Env string
Host string
Port int
Database DatabaseConfig
Meilisearch MeilisearchConfig
Redis RedisConfig
Equalize EqualizeConfig
S3 S3Config
Env string
Host string
Port int
Database DatabaseConfig
Meilisearch MeilisearchConfig
Redis RedisConfig
Equalize EqualizeConfig
S3 S3Config
EnablePersistTask bool
EnableImpedancePersistTask bool
ShareCodeMaxPerMac int
ShareCodeTTL time.Duration
ShareCodeTTL time.Duration
}
func Load() (*Config, error) {
@@ -30,26 +30,26 @@ func Load() (*Config, error) {
env := getEnv("APP_ENV", "development")
db, err := loadDatabase(env)
db, err := loadDatabase()
if err != nil {
return nil, err
}
if err := db.validate(env); err != nil {
if err := db.validate(); err != nil {
return nil, err
}
ms := loadMeilisearch(env)
ms := loadMeilisearch()
if err := ms.validate(); err != nil {
return nil, err
}
rd := loadRedis(env)
rd := loadRedis()
if err := rd.validate(); err != nil {
return nil, err
}
eq := loadEqualize(env)
s3cfg := loadS3(env)
eq := loadEqualize()
s3cfg := loadS3()
shareCodeTTL, err := parseShareCodeTTL(getEnv("SHARE_CODE_TTL_MIN", "30"))
if err != nil {
@@ -57,18 +57,18 @@ func Load() (*Config, error) {
}
return &Config{
Env: env,
Host: getEnv("APP_HOST", "0.0.0.0"),
Port: port,
Database: db,
Meilisearch: ms,
Redis: rd,
Equalize: eq,
S3: s3cfg,
Env: env,
Host: getEnv("APP_HOST", "0.0.0.0"),
Port: port,
Database: db,
Meilisearch: ms,
Redis: rd,
Equalize: eq,
S3: s3cfg,
EnablePersistTask: getEnv("ENABLE_PERSIST_TASK", "false") == "true",
EnableImpedancePersistTask: getEnv("ENABLE_IMPEDANCE_PERSIST_TASK", "false") == "true",
ShareCodeMaxPerMac: getEnvInt("SHARE_CODE_MAX_PER_MAC", 1),
ShareCodeTTL: shareCodeTTL,
ShareCodeTTL: shareCodeTTL,
}, nil
}
+4 -37
View File
@@ -2,7 +2,6 @@ package config
import (
"fmt"
"os"
"strconv"
)
@@ -14,50 +13,21 @@ type DatabaseConfig struct {
Password string
}
func loadDatabase(env string) (DatabaseConfig, error) {
switch env {
case "production":
if os.Getenv("DATABASE_HOST") != "" {
return databaseFromEnv()
}
return DatabaseConfig{
Host: "database-1.chmuueamo72p.eu-central-1.rds.amazonaws.com",
Port: 3306,
Name: "audio",
User: "root",
Password: os.Getenv("DATABASE_PASSWORD"),
}, nil
default:
port, err := strconv.Atoi(getEnv("DATABASE_PORT", "3306"))
if err != nil {
return DatabaseConfig{}, fmt.Errorf("invalid DATABASE_PORT: %w", err)
}
return DatabaseConfig{
Host: getEnv("DATABASE_HOST", "192.168.9.127"),
Port: port,
Name: getEnv("DATABASE_NAME", "audio"),
User: getEnv("DATABASE_USER", "root"),
Password: getEnv("DATABASE_PASSWORD", "root123"),
}, nil
}
}
func databaseFromEnv() (DatabaseConfig, error) {
func loadDatabase() (DatabaseConfig, error) {
port, err := strconv.Atoi(getEnv("DATABASE_PORT", "3306"))
if err != nil {
return DatabaseConfig{}, fmt.Errorf("invalid DATABASE_PORT: %w", err)
}
return DatabaseConfig{
Host: os.Getenv("DATABASE_HOST"),
Host: getEnv("DATABASE_HOST", ""),
Port: port,
Name: getEnv("DATABASE_NAME", "audio"),
User: getEnv("DATABASE_USER", "root"),
Password: os.Getenv("DATABASE_PASSWORD"),
Password: getEnv("DATABASE_PASSWORD", ""),
}, nil
}
func (d DatabaseConfig) validate(env string) error {
func (d DatabaseConfig) validate() error {
if d.Host == "" {
return fmt.Errorf("database host is required")
}
@@ -67,8 +37,5 @@ func (d DatabaseConfig) validate(env string) error {
if d.User == "" {
return fmt.Errorf("database user is required")
}
if env == "production" && d.Password == "" {
return fmt.Errorf("DATABASE_PASSWORD is required in production")
}
return nil
}
+4 -24
View File
@@ -1,33 +1,13 @@
package config
import "os"
const defaultExternalEQAPIURL = "https://autoeq.app/equalize"
type EqualizeConfig struct {
APIURL string // 内网 EQ 接口(正式环境 Eafonyoung 源使用)
ExternalAPIURL string // 公网 EQ 接口(正式环境非 Eafonyoung 源使用)
}
func loadEqualize(env string) EqualizeConfig {
external := getEnv("EQ_EXTERNAL_API_URL", defaultExternalEQAPIURL)
if os.Getenv("EQ_API_URL") != "" {
return EqualizeConfig{
APIURL: os.Getenv("EQ_API_URL"),
ExternalAPIURL: external,
}
}
switch env {
case "production":
return EqualizeConfig{
APIURL: "http://172.31.18.70:8000/equalize",
ExternalAPIURL: external,
}
default:
return EqualizeConfig{
APIURL: defaultExternalEQAPIURL,
ExternalAPIURL: external,
}
func loadEqualize() EqualizeConfig {
return EqualizeConfig{
APIURL: getEnv("EQ_API_URL", ""),
ExternalAPIURL: getEnv("EQ_EXTERNAL_API_URL", "https://autoeq.app/equalize"),
}
}
+5 -23
View File
@@ -2,7 +2,6 @@ package config
import (
"fmt"
"os"
)
type MeilisearchConfig struct {
@@ -11,28 +10,11 @@ type MeilisearchConfig struct {
Index string
}
func loadMeilisearch(env string) MeilisearchConfig {
if os.Getenv("MEILISEARCH_HOST") != "" {
return MeilisearchConfig{
Host: os.Getenv("MEILISEARCH_HOST"),
APIKey: os.Getenv("MEILISEARCH_API_KEY"),
Index: getEnv("MEILISEARCH_INDEX", "models"),
}
}
switch env {
case "production":
return MeilisearchConfig{
Host: "http://ip-172-31-22-170.eu-central-1.compute.internal:7700",
APIKey: getEnv("MEILISEARCH_API_KEY", "young9#!UJsD219921031"),
Index: "models",
}
default:
return MeilisearchConfig{
Host: "http://ec2-18-184-205-87.eu-central-1.compute.amazonaws.com:7700",
APIKey: getEnv("MEILISEARCH_API_KEY", "young9#!UJsD219921031"),
Index: "models",
}
func loadMeilisearch() MeilisearchConfig {
return MeilisearchConfig{
Host: getEnv("MEILISEARCH_HOST", ""),
APIKey: getEnv("MEILISEARCH_API_KEY", ""),
Index: getEnv("MEILISEARCH_INDEX", "models"),
}
}
+4 -30
View File
@@ -2,7 +2,6 @@ package config
import (
"fmt"
"os"
"strconv"
)
@@ -13,38 +12,13 @@ type RedisConfig struct {
Database int
}
func loadRedis(env string) RedisConfig {
switch env {
case "production":
if os.Getenv("REDIS_HOST") != "" {
return redisFromEnv("16279")
}
return RedisConfig{
Host: "172.31.38.162",
Port: 16279,
Password: getEnv("REDIS_PASSWORD", "eafon123!"),
Database: 1,
}
default:
port, _ := strconv.Atoi(getEnv("REDIS_PORT", "6379"))
db, _ := strconv.Atoi(getEnv("REDIS_DATABASE", "1"))
return RedisConfig{
Host: getEnv("REDIS_HOST", "192.168.9.127"),
Port: port,
Password: getEnv("REDIS_PASSWORD", ""),
Database: db,
}
}
}
func redisFromEnv(defaultPort string) RedisConfig {
port, _ := strconv.Atoi(getEnv("REDIS_PORT", defaultPort))
func loadRedis() RedisConfig {
port, _ := strconv.Atoi(getEnv("REDIS_PORT", "6379"))
db, _ := strconv.Atoi(getEnv("REDIS_DATABASE", "1"))
return RedisConfig{
Host: os.Getenv("REDIS_HOST"),
Host: getEnv("REDIS_HOST", ""),
Port: port,
Password: os.Getenv("REDIS_PASSWORD"),
Password: getEnv("REDIS_PASSWORD", ""),
Database: db,
}
}
+6 -25
View File
@@ -1,7 +1,5 @@
package config
import "os"
type S3Config struct {
Bucket string
Region string
@@ -9,28 +7,11 @@ type S3Config struct {
SecretAccessKey string
}
func loadS3(env string) S3Config {
if os.Getenv("AWS_ACCESS_KEY_ID") != "" || os.Getenv("AWS_SECRET_ACCESS_KEY") != "" {
return S3Config{
Bucket: getEnv("S3_BUCKET", "luxsin-app-bucket"),
Region: getEnv("AWS_REGION", "eu-central-1"),
AccessKeyID: os.Getenv("AWS_ACCESS_KEY_ID"),
SecretAccessKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
}
}
switch env {
case "production":
return S3Config{
Bucket: getEnv("S3_BUCKET", "luxsin-app-bucket"),
Region: getEnv("AWS_REGION", "eu-central-1"),
}
default:
return S3Config{
Bucket: getEnv("S3_BUCKET", "luxsin-app-bucket"),
Region: getEnv("AWS_REGION", "eu-central-1"),
AccessKeyID: "AKIAVMFK45I6P3TNI3VJ",
SecretAccessKey: "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",
}
func loadS3() S3Config {
return S3Config{
Bucket: getEnv("S3_BUCKET", ""),
Region: getEnv("AWS_REGION", "eu-central-1"),
AccessKeyID: getEnv("AWS_ACCESS_KEY_ID", ""),
SecretAccessKey: getEnv("AWS_SECRET_ACCESS_KEY", ""),
}
}