diff --git a/deploy/.env.example b/deploy/.env.example index 8a597d4..4dc99ef 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -12,6 +12,14 @@ MYSQL_PASSWORD=root MYSQL_DATABASE=sundynix_pet # ── 外部 MinIO(对象存储 / 图片) ── +# ⚠️ 这是多个服务共用的 MinIO 实例(sundynix-agent / sundynix-plant 等也在用): +# 1) BUCKET 必须填本项目自己的桶,填错别的服务的桶会污染人家数据; +# 2) 强烈建议不要用 root 凭据,另开一个只能访问 sundynix-pet 的账号: +# mc admin user add pets-svc <强密码> +# mc admin policy create pets-only pets-only.json # 只授权 sundynix-pet +# mc admin policy attach pets-only --user pets-svc +# 3) 桶已存在时程序不会修改其访问策略;图片直链需要该桶为 public-read, +# 这一项由运维一次性配好。 # ENDPOINT 是「写入」用的 MinIO API 地址:内网直连、不带协议、不走 nginx。 # 公网等价地址是 162.14.122.200:3407(本机调试时可用,跨公网慢)。 MINIO_ENDPOINT=192.168.100.126:9000 diff --git a/pets-be/internal/storage/minio.go b/pets-be/internal/storage/minio.go index 09909ab..c7e7e6a 100644 --- a/pets-be/internal/storage/minio.go +++ b/pets-be/internal/storage/minio.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "log" "strings" "time" @@ -49,12 +50,18 @@ func (s *Storage) ensureBucket() error { if err != nil { return fmt.Errorf("bucket exists: %w", err) } - if !exists { - if err := s.client.MakeBucket(ctx, s.bucket, minio.MakeBucketOptions{}); err != nil { - return fmt.Errorf("make bucket: %w", err) - } + if exists { + // 桶已存在:绝不碰它的策略。MinIO 可能是多个服务共用的, + // 万一 bucket 配错(填成别的服务的桶),无条件改策略会把人家的桶 + // 悄悄变成全网可读。已存在的桶由运维一次性配好读权限。 + log.Printf("minio: 复用已存在的 bucket %q(不修改其访问策略)", s.bucket) + return nil } - // dev:设置公开只读策略,便于直接以 URL 访问对象 + + if err := s.client.MakeBucket(ctx, s.bucket, minio.MakeBucketOptions{}); err != nil { + return fmt.Errorf("make bucket: %w", err) + } + // 仅对「本服务刚创建」的桶设公开只读:小程序要用 URL 直接加载图片。 policy := fmt.Sprintf(`{ "Version": "2012-10-17", "Statement": [{ @@ -67,6 +74,7 @@ func (s *Storage) ensureBucket() error { if err := s.client.SetBucketPolicy(ctx, s.bucket, policy); err != nil { return fmt.Errorf("set bucket policy: %w", err) } + log.Printf("minio: 已创建 bucket %q 并设为公开只读(图片需可直链访问)", s.bucket) return nil }