# ✅ MinIO 内网化架构 - 最终配置 ## 架构变更总结 ### 变更日期 2025-11-23 ### 变更目标 - MinIO S3 对象存储改为仅内网访问 - 删除 MinIO 的所有 Traefik 公网路由 - 保留根路径 302 重定向到 `/group/` - 通过 Supabase Storage API 提供公网文件上传下载功能 --- ## 最终架构 ### 内网访问 (Tailscale VPN Required) | 服务 | 地址 | 用途 | |------|------|------| | MinIO S3 API | `http://100.64.0.2:9000` | 对象存储 API(管理员直接访问)| | MinIO Console | `http://100.64.0.2:9001` | Web 管理界面 | | Supabase Dashboard | `http://100.64.0.2:18000` | 数据库/后端管理 | ### 公网访问 (HTTPS) | 服务 | 地址 | 说明 | |------|------|------| | **根路径** | `https://amiap.hzau.edu.cn/` | 302 重定向到 `/group/` | | **课题组网站** | `https://amiap.hzau.edu.cn/group/` | Vue.js 前端 | | **Supabase Storage** | `https://amiap.hzau.edu.cn/supa/storage/v1/` | 文件上传下载 API ✅ | | **Supabase API** | `https://amiap.hzau.edu.cn/supa/` | Auth/REST/Realtime | | **ABM 数据库** | `https://amiap.hzau.edu.cn/ABM/` | WebSocket 项目 | --- ## 存储架构 ### 公网文件上传下载流程 ``` 用户/应用 ↓ HTTPS https://amiap.hzau.edu.cn/supa/storage/v1/ ↓ Traefik (去除 /supa 前缀) Kong Gateway (Supabase API 网关) ↓ 内部网络 Supabase Storage Service (Docker 内部) ↓ S3 协议 (http://minio:9000) MinIO 对象存储 ↓ 物理存储: /vol1/1000/s3 ``` **关键点**: - 用户**不直接**访问 MinIO - 所有公网访问通过 Supabase Storage API - MinIO 仅在 Docker 内部网络和 Tailscale 内网可访问 - 文件最终存储在 MinIO 容器 (`/vol1/1000/s3`) ### 内网直接访问(管理员) ``` 管理员 (Tailscale VPN) ↓ http://100.64.0.2:9000 (MinIO S3 API) http://100.64.0.2:9001 (MinIO Console) ↓ MinIO 容器 ↓ 物理存储: /vol1/1000/s3 ``` --- ## 配置变更详情 ### 1. docker-compose.s3.yml **删除的配置**: ```yaml # ❌ 已删除 labels: - "traefik.enable=true" - "traefik.http.routers.minio-s3.rule=..." - "traefik.http.services.minio-s3-svc...." # ... 所有 Traefik labels networks: - frontend # ❌ 不再连接到 Traefik 网络 ``` **保留/更新的配置**: ```yaml services: minio: ports: - "100.64.0.2:9000:9000" # ✓ 仅 Tailscale IP - "100.64.0.2:9001:9001" # ✓ 仅 Tailscale IP environment: MINIO_SERVER_URL: "http://100.64.0.2:9000" # ✓ 内网 URL MINIO_BROWSER_REDIRECT_URL: "http://100.64.0.2:9001" networks: - default # ✓ 仅 Supabase 内部网络 ``` ### 2. docker-compose.yml **修复的端口冲突**: ```yaml # Studio Dashboard studio: ports: - "100.64.0.2:18000:3000" # ✓ Tailscale 内网访问 # Kong API Gateway kong: # ✓ 不暴露端口,仅通过 Traefik 公网访问 # Kong 通过 Docker 内部网络与其他服务通信 ``` ### 3. Supabase Storage 配置 **Storage 通过内部网络连接 MinIO** (`docker-compose.yml`): ```yaml storage: environment: STORAGE_BACKEND: s3 GLOBAL_S3_ENDPOINT: http://minio:9000 # ✓ Docker 内部网络 GLOBAL_S3_BUCKET: stub AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER} AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD} ``` --- ## 验证测试 ### ✅ 测试结果 运行 `examples/test_https_storage.py`: ```bash cd /vol1/1000/docker_server/traefik/supabase-stack python3 examples/test_https_storage.py ``` **测试结果**: 5/5 通过 ✅ | 测试项 | 状态 | 说明 | |--------|------|------| | 列出 Buckets | ✅ | 发现 2 个 bucket | | 创建/确认 Bucket | ✅ | test-https 存在 | | 上传/更新文件 | ✅ | 79 bytes 上传成功 | | 下载文件 | ✅ | 内容完整 | | 生成签名 URL | ✅ | 临时链接可用 | ### 测试命令示例 ```bash # 测试根路径重定向 curl -I https://amiap.hzau.edu.cn # 期望: HTTP/2 302 + Location: /group/ # 测试 Supabase Storage API curl -I https://amiap.hzau.edu.cn/supa/storage/v1/bucket \ -H "apikey: YOUR_API_KEY" # 期望: HTTP/2 200 # 测试 MinIO 内网访问(需要 Tailscale) curl -I http://100.64.0.2:9000/minio/health/live # 期望: HTTP/1.1 200 OK # 测试 MinIO Console(需要 Tailscale) curl -I http://100.64.0.2:9001 # 期望: HTTP/1.1 200 OK + Server: MinIO Console ``` --- ## 安全优势 ### 1. 最小权限原则 - MinIO 不再暴露到公网 - 仅授权用户(Tailscale VPN)可直接访问 MinIO ### 2. 访问控制 - 公网访问必须通过 Supabase Storage API - 支持细粒度的权限控制(RLS) - 自动签名 URL,临时授权 ### 3. 攻击面减小 - 减少了公网暴露的端口和服务 - MinIO 管理界面仅内网可访问 - 降低了潜在的 DDoS 风险 --- ## 使用指南 ### 公网文件上传下载 **Python 示例**: ```python import requests BASE_URL = 'https://amiap.hzau.edu.cn/supa' API_KEY = 'your_anon_key' headers = { 'apikey': API_KEY, 'Authorization': f'Bearer {API_KEY}' } # 上传文件 with open('test.txt', 'rb') as f: response = requests.post( f'{BASE_URL}/storage/v1/object/bucket-name/file.txt', headers={**headers, 'Content-Type': 'text/plain'}, data=f ) # 下载文件 response = requests.get( f'{BASE_URL}/storage/v1/object/bucket-name/file.txt', headers=headers ) content = response.content ``` **JavaScript 示例**: ```javascript import { createClient } from '@supabase/supabase-js' const supabase = createClient( 'https://amiap.hzau.edu.cn/supa', 'your_anon_key' ) // 上传文件 const { data, error } = await supabase.storage .from('bucket-name') .upload('file.txt', file) // 下载文件 const { data: fileData } = await supabase.storage .from('bucket-name') .download('file.txt') ``` ### 内网管理(MinIO Console) 1. 连接 Tailscale VPN 2. 访问: `http://100.64.0.2:9001` 3. 登录凭证: - **用户名**: `bsxzZAJ3fvDquup` - **密码**: `c2dc1bca7aa4d0adc308f69b6d41eddfaa110a9572ad1b410d73ea0633523fe9` ### MinIO 命令行工具 (mc) ```bash # 配置别名 mc alias set myminio http://100.64.0.2:9000 \ bsxzZAJ3fvDquup \ c2dc1bca7aa4d0adc308f69b6d41eddfaa110a9572ad1b410d73ea0633523fe9 # 列出 buckets mc ls myminio # 上传文件 mc cp local-file.txt myminio/stub/ # 下载文件 mc cp myminio/stub/file.txt ./ ``` --- ## 故障排查 ### 问题: Supabase Storage API 返回 404 **检查**: ```bash # 1. 确认 Kong 运行正常 docker ps | grep kong # 2. 查看 Kong 日志 docker logs supabase-kong --tail 50 # 3. 测试 Kong 健康状态 docker inspect supabase-kong --format='{{.State.Health.Status}}' ``` ### 问题: MinIO 内网无法访问 **检查**: ```bash # 1. 确认 Tailscale 连接 tailscale status ping 100.64.0.2 # 2. 检查 MinIO 容器 docker ps | grep minio # 3. 查看端口绑定 docker port supabase-minio-1 ``` ### 问题: 文件上传失败 **检查**: ```bash # 1. 查看 Storage 日志 docker logs supabase-storage --tail 50 # 2. 确认 Storage 到 MinIO 的连接 docker exec supabase-storage ping -c 1 minio # 3. 检查 Storage 环境变量 docker exec supabase-storage env | grep -E "GLOBAL_S3|MINIO" ``` --- ## 相关文档 - `examples/test_https_storage.py` - Storage API 功能测试 - `MINIO_LOGIN_FIX.md` - MinIO Console 登录问题修复 - `INTERNAL_ACCESS_FIXED.md` - 内网访问配置 - `DEPLOYMENT_GUIDE.md` - 完整部署指南 --- **修改日期**: 2025-11-23 **架构版本**: v3.0 (MinIO 内网化) **状态**: ✅ 已验证,生产就绪 **测试**: 5/5 通过