资讯详情

自建1TB免费S3对象存储:MinIO部署与避坑指南

📅 2026/10/9 8:20:45 | 华诺云谱 👁 阅读
自建1TB免费S3对象存储:MinIO部署与避坑指南
看到“1TB免费S3对象存储”这个标题很多人第一反应是哪家云厂商这么大方我直接把结论放在前面这里说的“免费”不是云厂商白送1TB容量而是用开源软件在你自己的一台机器加一块1TB硬盘上搭出一个完全兼容S3协议的对象存储服务。软件本身不收授权费存储容量由你的硬盘决定。整篇文章我想聊清楚三件事为什么值得自建、怎么一步步搭起来、实际使用中踩过哪些坑。如果你手里正好有一块闲置硬盘或者你是做物联网比如ESP32-S3的开发者这篇实操文应该能帮你省下不少云存储账单。1. 为什么我选择自建S3对象存储1.1 先搞懂对象存储是什么对象存储和传统文件系统有一个非常直观的区别传统文件系统是“目录树结构”你得先建文件夹、再往里放文件访问一个文件要给出完整路径对象存储是“扁平结构”一个桶Bucket里直接放对象Object每个对象有一个全局唯一的Key和一堆元数据Metadata。访问一个对象只需要“桶名Key”不需要关心数据具体存在哪块磁盘上、目录层级是什么。S3协议是这种对象存储的事实标准AWS最早定义了它后来几乎所有云厂商都做了兼容接口。这块为什么重要因为S3 API一旦兼容你的代码不需要绑定某个厂商。今天用自建MinIO明天想迁回云只要改一个Endpoint地址就行其他API调用几乎不用动。我用生活类比再解释一层对象存储像一个物流仓库每个桶就是独立的库房每个对象就是贴着订单号的包裹。你并不关心包裹被放在货架第几排你只需要告诉管理员“库房编号订单号”他就能帮你取出来。这种设计天然适合海量非结构化数据比如图片、视频、日志、固件包、传感器数据。1.2 “免费”是个伪命题但也是个真选项先泼一盆冷水主流的云对象存储厂商免费额度通常都很小。Cloudflare R2给10GB永久免费Backblaze B2给10GB免费额度AWS S3本身不设永久免费容量只有新用户12个月试用期里每个月5GB。这些都是真实存在的但都不够装下1TB数据。如果直接买1TB云对象存储按月付费的话哪怕是用冷存储级别一个月也得几十块钱热存储更贵。而且流量费往往另算尤其是下行流量从存储读到客户端很容易超过预期。这时候自建的价值就出来了——如果你手上正好有一台常年开机的设备NUC、旧笔记本、树莓派甚至一台云服务器再配一块1TB硬盘软件用MinIO这种开源方案授权费为零。硬件成本里一块1TB的机械硬盘或者SSD视品牌和介质大概几百块到上千块但这些是一次性投入不存在月租、流量费、请求费。当然我必须把话说完整所谓“免费”并不是零成本。电费、带宽、设备维护、数据丢失风险这些都要你自己承担。如果你的需求是“文件绝对不能丢”建议把自建存储当成“第二份数据”或“开发测试环境”生产环境还是老老实实用云厂商的SLA。1.3 为什么选MinIO而不是GlusterFS我搜索资料时发现很多人会提到GlusterFS也能提供对象存储还有Ceph也能做S3网关。实际用下来结论很明确单机1TB场景MinIO是四两拨千斤的选项。从定位上看GlusterFS是一个分布式文件系统它真正擅长的是把多台机器的磁盘聚合成一个超大文件系统对象存储只是它附带的一个S3网关能力。Ceph就更“重”了部署一套Ceph集群要至少三个节点MON、MGR、OSD、RGW这些角色摆弄一圈没有几天时间根本玩不起来。用这些大聪明去做1TB单机存储就像开着重型卡车去便利店买瓶水。MinIO则是专门为对象存储设计的尤其适合小规模部署。它的安装包只有一个二进制文件或者一个Docker镜像启动参数简单管理控制台自带了Web UI。更关键的是MinIO对S3协议的兼容度非常高AWS CLI、boto3、SDK这些主流工具都是开箱即用。最出名的特性是支持“桶级版本”和“生命周期规则”这对数据保护非常重要。我并不是说GlusterFS一无是处。如果你有至少三台服务器想拿便宜的硬件堆出一个分布式存储池那GlusterFS是值得研究的方案。如果只是想快速搭一个稳定、省心、兼容S3的对象存储先别折腾分布式把MinIO跑明白就够了。2. 动手前准备硬件、系统和数据盘2.1 硬件清单不需要顶配自建对象存储的硬件门槛低得惊人。我的推荐配置是这样一套一台Linux机器x86_64或者ARM64都行我实测过树莓派4跑MinIO也可以就是并发差一些内存至少2GBMinIO本身不占多少默认单机模式建议256MB到1GB就够跑接口服务但系统其他程序也要内存一块1TB数据盘SSD优先机械盘也能用但小对象读写会明显慢如果机器是Cloud云服务器注意数据盘要单独买别把系统盘塞满另外有个小建议数据盘和系统盘最好是分开的两块盘。系统盘崩了不影响数据数据盘满了也不拖累系统服务。我自己一开始图省事把MinIO的数据目录直接放在系统盘后来日志一涨存储马上告急又得停机迁移非常被动。2.2 操作系统与部署方式怎么选操作系统我推荐Ubuntu 22.04 LTS稳定性好、社区资料全、包管理器顺手后面挂载硬盘、配Nginx都是几行命令的事。别的发行版如Debian、CentOS也完全可以只是命令细节不同。部署MinIO有两种主流方式一种是下载官方二进制文件直接跑另一种是用Docker容器跑。这里我把两者做个对比对比项二进制部署Docker部署安装复杂度下载一个文件加执行权限需要先装Docker升级回滚手动替换二进制docker pull新镜像重建容器数据目录隔离手动指定挂载volume容器外不可见开机自启写systemd unit--restart unless-stopped资源占用更低几乎无额外开销多一层容器运行时占用略高我个人在单机场景更偏向Docker部署。原因是升级回滚太方便了镜像标签一换就完成版本迁移坏配置了直接重启容器回到上一个状态数据目录永远在我的宿主机/data/minio下面不会被容器搞乱。安装Docker本身很简单官方提供一键脚本但我不建议直接在服务器上执行来源不明的脚本。你在自己的机器上操作时可以按官方文档安装或者用系统自带的软件源确认好网络环境后再装。装完以后跑一下 docker --version能正常输出版本号就说明环境就位。2.3 数据盘格式化和挂载这一步很多人会跳过直接把数据目录建在“当前目录”下面结果系统一重装数据全没了这是最典型的新手事故。我的做法是这样的确认盘符。用 lsblk 或 fdisk -l 查看系统识别到的块设备确认你要用的那块盘是 /dev/sdb 还是 /dev/nvme0n1千万别搞错盘。如果是一块全新空盘用 parted 或 fdisk 创建分区表再创建一个分区。如果只是想把一个已有分区挂到专门目录则跳过分区步骤直接格式化。格式化文件系统我这里用的是ext4# 明确确认盘符是 /dev/sdb且盘上数据已备份 sudo mkfs.ext4 /dev/sdb1创建挂载点并挂载sudo mkdir -p /data sudo mount /dev/sdb1 /data设置开机自动挂载编辑 /etc/fstab在文件末尾加一行/dev/sdb1 /data ext4 defaults 0 2这一步完成后我建议再手动执行 mount -a 验证fstab配置没有语法错误否则重启时系统可能卡在挂载环节。fstab写错是会开不了机的所以强烈建议每改完一次就执行一次 mount -a看到不报错再重启。做完这些/data目录下再建一个minio专属数据目录也就是 /data/minio然后就可以进入部署环节了。3. 部署MinIO并验证S3协议3.1 准备数据目录和管理员账号MinIO的数据组织方式是“指定一个根数据目录里面自动按桶建子目录”。我们先把目录建好并清空sudo mkdir -p /data/minio然后规划管理员账号。MinIO启动时需要两个环境变量MINIO_ROOT_USER 和 MINIO_ROOT_PASSWORD。注意这里的账号名不是“邮箱”也不是“手机号”就是你自定义的AccessKey ID而密码就是SecretKey相当于整个存储系统的最高管理员凭证。密码规则我有一点建议长度至少16位包含大小写字母、数字和符号。这个账号一旦泄露等于把你的所有对象存储数据拱手让人所以不要用admin/123456这种组合。我是把密码放进一个单独的环境变量文件里不写进启动命令的历史记录。如果你用Docker方式之后新建容器时可以用 --env-file 指定变量文件这样history里也不会出现明文密码cat /data/minio.env EOF MINIO_ROOT_USERmyadmin MINIO_ROOT_PASSWORD这里写一个至少16位的高强度密码 EOF chmod 600 /data/minio.env这里插一句权限位 chmod 600 很重要否则其他系统用户可能能读到你的明文密钥。3.2 用Docker容器把MinIO跑起来数据目录环境变量都准备好了接下来是正式启动命令。我用的命令大致是这样docker run -d \ --name minio \ --restart unless-stopped \ -p 9000:9000 \ -p 9001:9001 \ --env-file /data/minio.env \ -v /data/minio:/data \ minio/minio server /data --console-address :9001逐条拆解一下-d 是后台运行容器--name minio 给容器命名--restart unless-stopped 表示Docker守护进程启动时自动拉起MinIO机器重启后存储服务能自愈-p 9000:9000 把容器的9000端口映射到宿主机9000是S3 API的默认端口所有SDK和命令行工具都走它-p 9001:9001 映射管理控制台端口浏览器访问 http://你的IP:9001 就能登录图形界面--env-file 读取刚才的安全变量文件-v /data/minio:/data 把宿主机的数据目录挂在容器内MinIO数据实际写在宿主机磁盘上minio/minio server /data 是镜像的启动命令--console-address 指定控制台监听端口不指定的话默认是随机端口烦得很运行完以后用 docker logs minio 看一下日志出现下面这样的输出就说明服务起来了Status: 1 Online, 0 Offline API: http://10.0.0.5:9000 http://127.0.0.1:9000 Console: http://10.0.0.5:9001 http://127.0.0.1:9001看到有“Online”字样就可以进入下一步验证。3.3 用mc和AWS CLI实测桶的读写装好了不代表真能用。我会至少用两种客户端各测一遍确保S3协议兼容性没问题而不是只有MinIO自己的Web界面能用。先装MinIO Clientmc。这是官方提供的命令行工具操作非常顺手wget https://dl.min.io/client/mc/release/linux-amd64/mc chmod x mc sudo mv mc /usr/local/bin/ mc alias set myminio http://127.0.0.1:9000 myadmin 你的密码mc alias set 的意思是把一个访问端点存成短名字后面命令都用 myminio 代替“地址账号密码”这一串信息。接着测试建桶和上传mc mb myminio/test-bucket echo hello minio test.txt mc cp test.txt myminio/test-bucket/test.txt mc ls myminio/test-bucket如果最后能看到 test.txt 对象出现说明MinIO的写入和列表查询都正常。再用AWS CLI验证一次。安装AWS CLI后不要用默认的configure交互流程而是走自定义Endpointaws configure --profile minio # 他会让你填Access Key ID、Secret Access Key、Region Name、Output format # Access Key ID填MINIO_ROOT_USER的值 # Secret Access Key填MINIO_ROOT_PASSWORD的值 # Region随便填比如us-east-1 # Output format填json然后列出桶aws --profile minio --endpoint-url http://127.0.0.1:9000 s3 ls如果能返回“test-bucket”说明AWS CLI这种被所有云厂商规范化的工具也能正常访问S3兼容性验证通过。3.4 用Nginx反向代理加上HTTPS如果MinIO只有内网访问或本机访问到上一步就可以收工了。但大部分场景下你会想从公网访问或者让ESP32-S3这类嵌入式设备连接上传。这里就有一个问题很多S3客户端默认要求TLS加密连接直接拿HTTP的IP地址去访问签名校验和证书检查都会失败。所以正确做法是给MinIO配一个域名用Nginx做反向代理并签一个Let‘s Encrypt的免费证书。Nginx反向代理的配置片段大概长这样域名 s3.example.com 替换成你自己的server { listen 443 ssl http2; server_name s3.example.com; ssl_certificate /etc/letsencrypt/live/s3.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/s3.example.com/privkey.pem; client_max_body_size 2g; location / { proxy_pass http://127.0.0.1:9000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }有个细节必须提MinIO在S3 API请求中会用 Host 头来判断你想访问哪个桶所以反向代理一定要把原始Host头透传过去也就是 proxy_set_header Host $host。如果这里写死了某个固定地址很多客户端会报签名错误排查半天找不到原因。证书签发可以用certbot域名解析先指向这台服务器然后运行sudo certbot --nginx -d s3.example.com一切顺利以后再把之前的AWS CLI测试命令改成 https://s3.example.comaws --profile minio --endpoint-url https://s3.example.com s3 ls能正常返回桶列表就说明公网HTTPS通道全通了。4. 常见问题与避坑实录4.1 客户端连不上先查这五件事自建MinIO过程中最磨人的问题就是“客户端报错连不上”。我遇到过的情况五花八门这里整理成一张排查速查表现象常见原因确认方法连接超时防火墙没放行9000端口curl -I http://IP:9000/minio/health/live容器启动即退出密码长度不够/数据目录权限不对docker logs minio签名不匹配(SignatureDoesNotMatch)客户端系统时间和服务器差太多检查服务器 date 命令输出找不到桶(NoSuchBucket)访问路径带了额外前缀或者桶名带下划线去看控制台里桶的准确名称证书校验失败客户端没安装你的自签名证书确认公网访问用标准Let‘s Encrypt证书这里单独说一下时间同步的问题。S3签名机制是基于HTTP请求的Date头或x-amz-date头做HMAC计算的如果客户端和服务器的时间偏差超过15分钟几乎必然报SignatureDoesNotMatch。服务器上记得开启NTP时间同步用 systemctl status systemd-timesyncd 能看到时间同步状态。别小看这个问题我至少有两次被它折磨到怀疑是网络问题。4.2 性能为什么上不去有读者试过以后跑来问我为什么上传大文件速度还可以但传几千个小文件就慢吞吞这个其实不怪MinIO而是S3协议本身的设计就是面向对象、面向并发的。单个请求的带宽和延迟就摆在那里要提升吞吐量必须走并发。几个提高性能的实际操作客户端并发上传比如用 mc cp --parallel 32 或者AWS CLI的 s3 cp --recursive 时配合合理的并发参数小文件并发数可以设到32或更高网络链路如果你在公网传输上行带宽是硬瓶颈别指望软件能把100Mbps上行变成1000Mbps磁盘类型机械盘适合顺序读写大文件SSD适合随机读写小对象。我后来把数据盘换成SSD同一个小文件列表上传场景速度差了好几倍MinIO默认线程池参数单机内存够大时可以调高 GOMAXPROCS 或磁盘并发相关的参数但新手阶段先用默认值就好还有一个新手容易踩的坑别把系统盘同时用于MinIO数据目录和Docker镜像层。镜像层写放大会影响系统盘IO反过来MinIO的数据读取也会抢系统资源。4.3 怎么让ESP32-S3这类嵌入式设备接入热词里有一堆ESP32-S3相关的问题比如“ESP32-S3核心板在PlatformIO软件中怎么选择开发板”“esp32 s3怎么看驱动装了”。这里正好结合我的场景说一句嵌入式设备经常需要把传感器数据、截图、固件日志上传到对象存储而MinIO提供的就是标准S3接口ESP32-S3完全能直接对接。以PlatformIO为例如果你用的是ESP32-S3 Super Mini板子在platformio.ini里选择开发板时可以选 esp32-s3-devkitc-1 作为基准板型然后靠build_flags指定你的晶振、PSRAM和USB CDC配置。这一步和对象存储关系不大但很多人就是卡在开发板选不对导致后面代码烧录都进行不下去。真正接对象存储时ESP32-S3通常不走重型的AWS SDK因为那种完整SDK对Flash和内存占用太夸张。更轻量的做法是用HTTP客户端直接发REST请求把数据作为对象Put进去。伪代码大概是这样#include WiFiClientSecure.h #include HTTPClient.h // endpoint填你Nginx代理后的地址 String endpoint https://s3.example.com/test-bucket/sensor-001.txt; void uploadToObjectStorage(String payload) { WiFiClientSecure client; client.setInsecure(); // 也可以设置证书指纹后面说 HTTPClient http; http.begin(client, endpoint); http.addHeader(Authorization, Bearer 你的签名串); http.addHeader(Content-Type, text/plain); int httpCode http.PUT(payload); if (httpCode 200) { Serial.println(Upload OK); } http.end(); }但是要注意S3的REST API要求对请求做签名Arduino代码里裸写签名逻辑比较烦。我建议直接在Arduino库管理器里搜索“minio”或“aws s3”相关的轻量库它们已经把签名、请求头、TLS这些杂活封装好了。关于TLS证书ESP32-S3固件里内置了完整CA根证书但如果你用的是自签证书就必须把证书指纹烧进去否则会一直握手失败这大概率就是很多人遇到的“ESP32-S3连不上服务器”的原因。4.4 数据安全与备份习惯最后一个章节想说一个比“怎么搭起来”更重要的事怎么保住数据。自建存储最尴尬的地方在于一旦硬盘坏了、机器中勒索病毒了、或者手滑删了桶你是没有后台客服可以找的。至少要做这几件事开启桶版本控制。MinIO支持bucket versioning执行 mc version enable myminio/test-bucket 以后每次覆盖或删除对象都会留下历史版本误删可以找回定期做异地镜像。用 mc mirror 把本地目录或另一个桶的数据同步到另一个位置的存储比如同步到一个偶尔开机的备份盘mc mirror --watch /data/backup myminio/test-bucket密钥最小化。不要所有客户端都拿管理员账号去连。在MinIO控制台里创建独立的AccessKey只给指定桶的读写权限其他桶全部拒绝控制台端口不要爆破。Management Console9001端口最好不要暴露到公网用防火墙限制只允许你的办公网IP访问或者直接用Nginx加一层身认证定期检查磁盘健康。smartctl 工具可以看机械盘的SMART信息及时发现坏道预警。SSD虽然没有坏道但也要关注剩余寿命我把这句话写在最后自建存储不等于自动备份文件只要只有一份就等于没有。哪怕硬件再便宜也不能替你把多副本策略和容灾恢复的事一起办了。用MinIO做1TB“免费”存储可以称得上体验极佳但数据的最后一道防线始终要你自己拉起来。后续还能怎么扩展在我自己的实际使用里1TB很快被测试环境、IoT上报数据和固件产物填到一半然后我就开始考虑怎么扩展了。MinIO有一个很自然的演进路径单机模式跑顺之后同一台机器可以加磁盘组成多磁盘单节点模式之后再加一台机器组成分布式集群。等你真正需要那一步的时候前面单机阶段磕磕绊绊踩过的坑都会变成你的经验优势迁移过程也会从容很多。另外如果你对GlusterFS感兴趣它和MinIO并不冲突。我可以把MinIO的数据目录放在GlusterFS挂载的卷上这样底层文件系统有冗余上层S3接口由MinIO负责。只是这个方案会额外消耗不少CPU和网络刚入门的读者不建议立刻尝试。对我个人而言这套“1TB免费S3对象存储”给我最大的收获并不是省下了每个月的云账单而是彻底理解了对象存储的请求模型、签名机制、桶权限这些概念。这些东西在云厂商的托管服务里是被隐藏起来的你花钱买到的只是“能用”不是“懂”。自己动手跑一遍以后再用任何云服务商的对象存储一眼就能看明白它到底在帮你做什么。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑