使用minIO自建S3存储,并迁移cloudFlare R2

cloudFlare提供了对象存储服务R2,包含10GB的免费存储额度且不收取流量费用。关于免费流量,我当时记R2的宣传口号类似是“不需要为获取自己的东西而付费”,这算是打了互联网几乎所有厂商的脸了吧。R2免费虽好,奈何受限于国内糟糕的访问体验,决定还是搬回来自建S3存储,因为正好有台国内限制的服务器。

一、配置minIO

兼容S3对象存储的开源解决方案,支持简单且灵活的存储扩容。

注意:minIO支持最好的文件格式是XFS,如果有可能,请尽量使用XFS。

1.1 下载

# RPM(RHEL)
wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20250312180418.0.0-1.x86_64.rpm -O minio.rpm
rpm install minio.rpm

# DEB(Debian/Ubuntn)
wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20250312180418.0.0_amd64.deb -O -O minio.deb
dpkg -i minio.deb

1.2 配置服务

编辑文件:/usr/lib/systemd/system/minio.service,替换为下面的内容。

[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
Type=notify

WorkingDirectory=/usr/local

User=root
Group=root

EnvironmentFile=-/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

# Let systemd restart this service always
Restart=always

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=1048576

# Specifies the maximum number of threads this process can create
TasksMax=infinity

# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

# Built for ${project.name}-${project.version} (${project.name})

1.3 配置变量

编辑文件:/etc/default/minio,替换为下面的内容。

# 用户名
MINIO_ROOT_USER=myminioadmin
# 密码
MINIO_ROOT_PASSWORD=minio-secret-key-change-me
# 文件存放目录
MINIO_VOLUMES="/mnt/data"
# 访问ui界面的端口
MINIO_OPTS="--console-address :9001"

1.4 配置用户

为minIO添加用户和用户组,并修改文件存储目录的归属。

groupadd -r minio-user
useradd -M -r -g minio-user minio-user
chown minio-user:minio-user /mnt/data

1.5 启动服务

systemctl start minio # 启动
systemc enable minio # 开启自启动
journal -f -u minio # 查看日志

1.6 高级配置

如果需要多硬盘、多节点部署,只需要修改变量MINIO_VOLUMES

  • 如果有2个硬盘挂载在/mnt/data1和/mnt/data2,那么MINIO_VOLUMES的值就是/mnt/data1 /mnt/data2
  • 如果有2台主机192.168.1.1和192.168.1.2,那么MINIO_VOLUMES的值就是http://192.168.1.1:9000/mnt/data http://192.168.1.2:9000/mnt/data

1.7 外部访问

默认情况下,minIO存储桶中的文件默认无法公开匿名访问,通过分享的方式支持的公开匿名访问也有期限限制。但是可以通过配置访问策略实现外链需求。进入存储桶设置页面,为匿名访问添加可读的访问策略。

然后使用9000端口的api地址拼接存储桶名称、路径和文件名即可访问。

二、配置nginx

nginx反向代理minIO,这里配置了两个域名,一个用户访问minIO的ui界面,一个用于提供外链。

server {
listen 8012 ssl;
server_name minio.domain.com;

client_max_body_size 10M;

ssl_certificate cert/*.domain.com.cert.pem;
#ssl证书的key文件路径
ssl_certificate_key cert/*.domain.com.key.pem;

location / {
proxy_pass http://127.0.0.1:9001;
charset utf-8;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
}
}

server {
listen 8012 ssl;
server_name storage.domain.com;

client_max_body_size 10M;

location / {
proxy_pass http://127.0.0.1:9000;
charset utf-8;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

反向代理minIO UI界面时要支持WS,否则界面上无法展示文件列表。minIO对文件没有大小要求,但是如果用nginx反向代理,则需要配置client_max_body_size,否则文件超过1M就会无法上传,看起来像是minIO对文件大小做了限制。

关于https证书,可以使用let’s encrypt提供的免费证书,支持泛域名,添加定时之后可以做到证书永不过期。

三、迁移CLoudFlare R2

这里借助Rclone来实现文件的迁移。Rclone的优点就是支持所有的对象存储,缺点就是弱可视化界面。

3.1 下载Rclone

访问Rclone官网的下载页面:https://rclone.org/downloads ,选择合适的版本下载。

3.2 配置Rclone

配置cloudflare r2

rclone config

# 输入 n 创建新配置,按提示填写以下信息
Name> r2
Storage> s3
Provider> 6 # 提供商选择 `Cloudflare R2 Storage`
env_auth> N # 不自动使用环境变量凭证
access_key_id> YOUR_R2_ACCESS_KEY # 输入 R2 的 Access Key
secret_access_key> YOUR_R2_SECRET_KEY # 输入 R2 的 Secret Key
region> auto # 区域填写 `auto`
endpoint> YOUR_ACCOUNT_ID.r2.cloudflarestorage.com # 替换为你的 Cloudflare 账户 ID
location_constraint> 留空直接回车
acl> 留空直接回车
storage_class> 留空直接回车

配置minIO

rclone config

# 输入 n 创建新配置,按提示填写以下信息
Name> minIO
Storage> s3
Provider> Other # 提供商选择 `Other`
env_auth> N # 不自动使用环境变量凭证
access_key_id> YOUR_ACCESS_KEY # 输入 R2 的 Access Key
secret_access_key> YOUR_SECRET_KEY # 输入 R2 的 Secret Key
region> auto # 区域填写 `auto`
endpoint> storage.domain.com # 替换为minIO的api域名
location_constraint> 留空直接回车
acl> 留空直接回车
storage_class> 留空直接回车

关于minIO的密钥id和key如何获取:

  • 找到存储桶的设置页面,点击“Access——Users”
  • 创建用户,分配“readwrite”读写权限
  • 切换到Service Accounts,创建密钥“Create Access Key”

3.3 迁移

rclone sync r2:bucket1 minIO:bucket2 --progress --log-file=日志文件  # 全量同步
rclone copy r2:bucket1 minIO:bucket2 --progress --log-file=日志文件 # 差异同步