FEATURED · 精选文章

宝塔面板集成Rustfs自建S3对象存储:备份与踩坑指南

发布时间 / 2026/9/9 14:44:06
来源 / 创域科博编辑部
栏目 / 资讯中心
宝塔面板集成Rustfs自建S3对象存储:备份与踩坑指南 最近在帮朋友调一台阿里云的服务器环境是宝塔面板需求其实挺朴素几个小网站要定期备份还想把图片和附件从服务器本地盘挪到一个统一存储里。一开始想图省事直接用云厂商的对象存储但考虑到数据量不大、预算敏感我就把目光转向了自托管方案。折腾了一圈最后落在了 Rustfs 上。先说结论Rustfs 是一个用 Rust 写的轻量级对象存储服务兼容 S3 API单二进制部署很契合宝塔这种偏运维化的管理场景。不过宝塔面板本身没有官方的 Rustfs 集成入口所以整个接入过程基本是在命令行和面板之间反复横跳。这中间踩的坑不少有些坑特别隐蔽不写下来对不起这几天的折腾。这篇就把我在宝塔环境下用 Rustfs 的完整过程、配置细节和踩坑记录整理出来给想自建对象存储或者给宝塔找备份后端的兄弟做个参考。1. Rustfs 到底是个什么东西为什么我会在宝塔里折腾它1.1 一句话讲清楚 Rustfs 的定位Rustfs 本质上就是一个跑在你自己服务器上的对象存储服务。它对外提供 S3 兼容接口也就是说你用 AWS S3 SDK、boto3、rclone 这类工具时把 endpoint 指向自己的服务器就能像使用云对象存储一样读写文件。它和 MinIO 是同一类东西但 Rustfs 的特点是更轻。Rust 编译出来的单文件二进制不依赖 JVM对比 MinIO 或者 SeaweedFS 那套内存占用低特别适合 1C2G 甚至 1C1G 的小机器。我实测在 1 核 2G 的服务器上跑空闲内存占用大概一百多兆这个体量放在宝塔面板一起跑没什么压力。宝塔面板的角色则是服务器管理入口负责网站、数据库、计划任务、防火墙这些常规操作。把 Rustfs 跑在宝塔管理的机器上意味着你可以用宝塔来管理网站和数据库同时把备份产物、静态资源放到 Rustfs 里形成一个“网站存本地、备份和附件走对象存储”的结构。1.2 适合放在宝塔里的三个使用场景不是所有场景都需要在宝塔里塞一个 Rustfs我实际用下来觉得以下三类情况最合适。第一类是最常见的备份中转。宝塔自带的备份功能可以备份网站目录和数据库但默认备份到服务器本地盘。服务器磁盘就那么大备份多了就满而且同机备份一旦机器挂了数据一起没。把 Rustfs 作为备份后端宝塔计划任务定时把备份文件推到 Rustfs相当于给自己加了一道保险。第二类是静态资源存储。如果你的网站有大量图片、附件、上传文件扔在网站目录里既占空间又不方便迁移。用 Rustfs 存静态资源通过 S3 API 读写前端再配 CDN 或者 Nginx 反代把流量和磁盘压力都解耦了。第三类是开发和测试环境。本地或测试环境需要模拟 S3直接连 Rustfs 就行不用购买云服务。尤其用 boto3 做数据管道、批处理任务开发时先用 Rustfs 做 mock联调完再切到云端成本几乎为零。我自己主要是前两类。宝塔里挂了好几个站点数据库里还有 PostgreSQL备份策略一直很头疼这也是为什么我会把 Rustfs 和宝塔备份功能反复折腾的原因。2. 动手前必须规划清楚的三件事2.1 部署形态单目录文件服务还是完整对象存储Rustfs 可以切换一种偏向“目录挂载”的用法也可以当作完整对象存储服务用。这个必须在动手前想清楚因为后面很多坑都是从定位不清开始的。如果你只是想让几个程序能通过 S3 API 读写文件那完整对象存储模式就够了启动服务、创建 bucket、配好 access key/secret key程序通过 endpoint 访问。这个模式对宝塔的干扰最小端口独立文件路径也独立。如果你想把它当成本地磁盘的延伸比如直接把某个网站的上传目录映射到 Rustfs 管理的目录里那就要考虑更多权限宝塔的 www 用户能否读写、Nginx 反代配置、路径访问方式等。我的建议是初次上手先跑完整对象存储模式别一开始就让它接管网站目录不然权限和路径问题会让人头大。2.2 端口、数据目录和权限的预留Rustfs 默认会监听一个端口但具体端口一定要提前规划因为宝塔面板、Nginx、MySQL、PostgreSQL 都已经占用了不少端口。默认的 9000 端口很容易冲突尤其和宝塔装了 MinIO 或者其他对象存储插件的时候。我的建议是选一个不常被占用的端口比如 9001、9002 这类配置前先用命令确认端口没被占用netstat -tlnp | grep 9001如果输出为空说明这个端口目前是空闲的。数据目录建议单独规划不要塞在 /root 或者 /home 下面。我会单独建一个目录比如 /data/rustfs 或者 /opt/rustfs-data跟网站目录分开。权限上有个细节如果 Rustfs 以 root 身份运行它创建的文件默认 owner 是 root如果后面要让宝塔内的网站www 用户也能访问这些文件需要处理目录权限或者用 systemd 指定 Userwww。2.3 版本下载和二进制校验Rustfs 不是系统仓库里的软件在宝塔的软件商店里也没有。所以只能通过下载二进制的方式安装。去它的 GitHub releases 页面找对应平台的最新版本服务器一般是 linux-amd64 架构。下载后建议先做两件事第一确认文件确实是可执行的 ELF不是下载了个奇怪网页第二用./rustfs --version跑一下看看能否正常输出版本号这一步能提前发现缺动态库之类的问题。由于 Rust 编译的二进制多数是静态编译一般不会缺动态库但如果下载错了架构会直接提示 Exec format error很多人在这一步就卡住了。3. 完整实操从下载 Rustfs 到用宝塔管理它3.1 下载、解压、初始化目录我在服务器上的操作流程是这样的。先切换到 /opt 目录下载二进制cd /opt wget https://github.com/你的版本号/rustfs-linux-amd64.tar.gz tar -zxvf rustfs-linux-amd64.tar.gz mv rustfs-linux-amd64 /usr/local/bin/rustfs chmod x /usr/local/bin/rustfs之所以放到 /usr/local/bin是因为这个目录通常已经在 PATH 里方便直接用命令。放好后建议先跑一遍rustfs --version看到版本号输出后再准备数据目录mkdir -p /data/rustfs如果在宝塔面板的文件管理里操作记得把这两个目录都创建好后面配置直接填路径。3.2 用 systemd 托管 Rustfs 进程这里是我踩的第一个大坑。刚开始我直接在 SSH 里nohup ./rustfs 跑当时看着一切正常但服务器重启后 Rustfs 没了宝塔计划任务里也没法管理它。后来我改用 systemd 托管一劳永逸。在 /etc/systemd/system/ 下新建一个服务文件名字叫 rustfs.service[Unit] DescriptionRustfs Object Storage Afternetwork.target [Service] Typesimple Userroot Grouproot WorkingDirectory/data/rustfs ExecStart/usr/local/bin/rustfs --config /etc/rustfs/config.toml Restarton-failure RestartSec5 EnvironmentRUST_LOGinfo [Install] WantedBymulti-user.target注意到我用了--config /etc/rustfs/config.toml也就是说配置文件单独放。这样改配置不需要动服务文件也更清晰。写好后执行systemctl daemon-reload systemctl enable rustfs systemctl start rustfs systemctl status rustfs这里有个问题要特别提醒很多人把 systemd 服务配置好后又去宝塔的“进程守护管理器”里添加同一个进程结果导致服务被拉起两次端口被占。实际上 systemd 托管就是守护宝塔插件没有必要再加同一个进程。我后面详细说这个冲突。3.3 在宝塔面板放行端口并通过浏览器验证Rustfs 启动后关键一步是让外部能访问。宝塔面板自带防火墙管理默认只放行部分端口。我一开始没注意服务在服务器本机 curl 能通但浏览器根本访问不了白白排查了半小时。需要做两件事。第一在宝塔面板 - 安全 - 防火墙 中放行你选择的端口比如 9001。第二如果服务器在云厂商还要去云控制台的安全组里放行相同端口。这两个地方任何一个没放行外部都无法访问。验证方式直接用浏览器访问http://服务器IP:9001如果能出 JSON 响应或者控制台页面说明服务已经对外可用。如果只想验证端口通不通可以用curl -v http://127.0.0.1:9001如果本机能通、外部不通优先检查安全组和宝塔防火墙。4. 核心配置和 boto3 接入的细节4.1 服务端配置项逐条讲清楚Rustfs 的配置文件是 TOML 格式我把实际用的配置贴出来然后逐条解释[server] listen_addr 0.0.0.0:9001 [storage] root_dir /data/rustfs [s3] access_key myAccessKey secret_key mySecretKey region us-east-1第一段[server]是监听地址。这里要特别注意如果写成127.0.0.1:9001那就只有本机能访问外网永远连不上这是很多“本地无法访问”问题的根源。需要对外服务时监听地址必须是0.0.0.0。第二段[storage]是数据存储根目录。Rustfs 会把 bucket 和对象文件放在这个目录下面。我特意也在这个目录里放了日志方便排查问题。第三段[s3]是访问凭证和区域。access_key 和 secret_key 就是后续 boto3 或 s3cmd 连接时要用到的密钥。region 通常随便填但要注意和客户端保持一致我习惯填 us-east-1兼容性最好。还有一个参数容易被忽视signature_version或者兼容模式相关配置。如果 Rustfs 默认用 S3 协议里的某种签名版本而客户端比如 boto3默认用另一种就会出现签名不匹配的情况。这个我在 4.2 里专门讲。4.2 boto3 连接 Rustfs 的正确姿势搜索引擎热词里“boto3 如何连接 rustfs”出现频率很高说明这里确实是重灾区。我一开始直接拿 boto3 默认客户端去连以为只要改 endpoint_url 就行结果跑起来疯狂报错。正确的连接方式如下import boto3 from botocore.client import Config s3_client boto3.client( s3, endpoint_urlhttp://你的服务器IP:9001, aws_access_key_idmyAccessKey, aws_secret_access_keymySecretKey, region_nameus-east-1, configConfig( signature_versions3v4, s3{addressing_style: path} ) )这里最关键的是addressing_style设为path。云厂商的 S3 默认走 virtual-hosted style也就是bucket.endpoint/path这种访问方式。但自建 Rustfs 很多实现只支持 path style也就是endpoint/bucket/path。不配置这个创建 bucket 或者读写对象时会直接报地址不匹配的错误。另外signature_versions3v4也是常规操作。有些自建对象存储默认只支持 SigV4如果不指定boto3 可能用 SigV4 或者尝试 SigV2在兼容性上容易出问题。显式指定成 s3v4 后签名逻辑就统一了。连接验证脚本response s3_client.list_buckets() print(response[Buckets]) s3_client.create_bucket(Buckettest-bucket) s3_client.put_object(Buckettest-bucket, Keyhello.txt, Bodybhello rustfs) res s3_client.get_object(Buckettest-bucket, Keyhello.txt) print(res[Body].read())这一套跑通后说明 boto3 到 Rustfs 的链路是通的。后面做自动化备份、文件上传都基于这套代码。4.3 搭配宝塔计划任务实现自动备份宝塔面板的计划任务功能可以定时执行脚本这个和 Rustfs 搭配起来很实用。我配置了一个每天凌晨备份数据库和网站目录到 Rustfs 的脚本。宝塔计划任务里新增一条 shell 脚本任务内容大致如下#!/bin/bash BACKUP_DIR/data/backups DATE$(date %Y%m%d) # 使用宝塔自带备份命令或 pg_dump/mysqldump 生成备份 mysqldump -u你的用户 -p你的密码 你的数据库 ${BACKUP_DIR}/${DATE}_db.sql pg_dump -U postgres 你的数据库 ${BACKUP_DIR}/${DATE}_pg.sql # 压缩 tar -czf ${BACKUP_DIR}/${DATE}_site.tar.gz /www/wwwroot/你的站点目录 # 上传到 Rustfs python3 /opt/scripts/upload_to_rustfs.py ${BACKUP_DIR}/${DATE}_db.sql backups/${DATE}_db.sql python3 /opt/scripts/upload_to_rustfs.py ${BACKUP_DIR}/${DATE}_pg.sql backups/${DATE}_pg.sql python3 /opt/scripts/upload_to_rustfs.py ${BACKUP_DIR}/${DATE}_site.tar.gz backups/${DATE}_site.tar.gz # 清理本地 7 天前的备份 find ${BACKUP_DIR} -type f -mtime 7 -delete上传脚本里就用前面那段 boto3 代码封装成一个函数。这里有个心得备份文件名里带上日期上传到 Rustfs 时梳理目录结构比如按backups/mysql/、backups/pgsql/、backups/site/区分后面查找和清理就特别方便。5. 踩坑实录这些问题我一个个替你趟过5.1 “本地无法访问”的三大典型原因搜索引擎热词里“本地无法访问”出现频率很高我在实际调试中也遇到好几次。整理下来无非三种原因。第一种是监听地址绑定错误。配置文件里写的是127.0.0.1而不是0.0.0.0导致只有服务器本机可以通过回环地址访问。这种情况本机 curl 是通的外网或者本地电脑连不上。第二种是防火墙没放行。宝塔面板的安全页和云厂商安全组双重拦截。很多人在宝塔里放行了端口但漏了云控制台的安全组配置尤其阿里云、腾讯云这两家默认安全组只放行少数端口。第三种是浏览器和网络环境问题。比如你服务器在国内本地出口网络到该端口有干扰或者使用了某些代理工具请求走了代理路径导致超时。这种时通时不通的网络问题需要额外判断可以先用手机流量访问试试如果手机流量能通基本就能确定是本地网络路径的问题。排查“本地无法访问”时我一般按这个顺序来先curl 127.0.0.1:端口看服务是否正常再curl 公网IP:端口看是否被防火墙拦截最后在自己电脑上 telnet 远程端口确认链路。这样一步步缩小范围基本十分钟内能定位。5.2 权限不对导致网站读写总是失败这个问题是在把某个网站的附件存储切到 Rustfs 时踩的。现象是Rustfs 运行正常boto3 从命令行上传下载也正常但网站程序通过 PHP 或 Python 调用 S3 接口上传文件时要么超时要么报 Permission Denied。排查后发现Rustfs 是以 root 身份运行的它写出的文件权限是 root:root而宝塔的网站进程是以 www 用户跑的。网站进程没有权限读取 Rustfs 数据目录里的文件自然各种报错。解决方案有两种。第一种是改 systemd 服务让 Rustfs 以 www 用户运行[Service] Userwww Groupwww但要注意改成 www 用户后数据目录也得给 www 用户授权chown -R www:www /data/rustfs第二种方案是保持 root 运行但在 Web 服务层做权限隔离比如把 Rustfs 的数据目录挂载到某个 Nginx 可读的位置通过内部接口访问。这么做隔离性好一些但实现复杂。我的建议是小服务直接改成 www 用户运行省事。这个坑我不止一次踩过建议大家在配置 systemd 服务时就指定好运行用户不要在 root 下跑完再改否则一旦积累了大量文件再 chown 会消耗不少时间。5.3 进程守护管理器与 systemd 的冲突宝塔有一个“进程守护管理器”插件可以在面板里监控某个进程挂了自动重启。我一开始觉得这个很好就在 systemd 托管 Rustfs 后又把同一个启动命令加到了宝塔进程守护里。结果就是进程卡死崩溃后systemd 和宝塔守护同时尝试拉起导致两个进程实例同时运行端口互相争抢日志里全是地址冲突报错。后来才明白一个进程只需要一种守护方式重复守护反而会制造新的问题。正确做法是如果已经用 systemd 托管宝塔里的进程守护管理器就不要再管 Rustfs 了。如果你更习惯用宝塔界面管理那就不要用 systemd直接在进程守护管理器里配置好启动命令并让宝塔负责开机启动。两种方案选一种不要混着来。5.4 宝塔备份 PostgreSQL 失败的连带坑标题里提到“宝塔无法备份 pgsql”这个我遇到过。一开始还以为是 Rustfs 的问题因为备份功能需要写上传接口但后来单独测试发现宝塔备份 PostgreSQL 本身就有不少限制。宝塔备份 PostgreSQL 时默认会在本地生成备份文件然后根据你选的后端存储进行上传。如果选的是自定义对象存储或者本地存储而 Rustfs 又没有正确配置上传就会失败。但实际上哪怕不接 Rustfs宝塔备份 pgsql 也经常因为 pg_dump 路径不对、认证方式不匹配等原因失败。解决方法是先绕开宝塔的数据库备份按钮手动验证 PostgreSQL 备份命令确保pg_dump能正常导出。然后再把导出文件通过计划任务上传到 Rustfs。等我手动把 PostgreSQL 备份链路跑通后再回来看宝塔的备份配置思路就清晰很多了。所以这个坑最大的教训是不要把宝塔的报错直接归因于 Rustfs。先在最小链路里验证每一环再组合起来问题才不会交叉污染。6. 写在最后的个人体会这次在宝塔里折腾 Rustfs前后花了两三天时间。整体感受是Rustfs 本身作为一个轻量对象存储是合格的安装配置都不复杂最坑的往往不是 Rustfs 自身而是和宝塔环境、权限体系、进程守护方式之间的组合问题。我的建议是如果你想给宝塔管理的服务器加一个自建对象存储尽量先把架构画清楚Rustfs 负责存储、宝塔负责管理和定时任务、boto3 负责程序对接。三者职责分开不要搅在一起踩坑的概率会小很多。另外所有外部访问类的服务配置完先自己做一次从本机到外网的连通性测试能排除掉一半的网络问题。以后再扩展的话我打算在 Rustfs 前面再加一层 Nginx 反向代理配上 HTTPS 域名这样程序和外部访问就不用暴露裸端口安全性也更可控。这个打算等下次有空再折腾到时候如果再踩到什么坑我再分享出来。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻