Arch Linux MinIO 部署与使用指南
Arch Linux MinIO 部署与使用指南
本文记录在 Arch Linux 云服务器上恢复 MinIO、配置开机运行,以及通过 Python 生成固件下载和日志上传预签名 URL 的完整过程。
示例公网 IP:203.0.113.10(文档示例专用地址,无法用于实际部署)。执行命令前,请统一替换为你自己的服务器公网 IP。本文中的用户名和密码均为示例或占位符。
1. 服务结构与注意事项
| 项目 | 配置 |
|---|---|
| S3 上传、下载接口 | http://203.0.113.10:9000 |
| 管理页面 | http://203.0.113.10:9001 |
| 固件 bucket | firmware |
| 日志 bucket | diagnostic |
| 数据目录 | /var/lib/minio/data |
| 管理员配置 | /etc/minio/minio.env |
| 服务配置 | /etc/systemd/system/minio.service |
9000 是 S3 API,9001 是管理页面。浏览器访问 9000 根路径时出现 XML 或 AccessDenied,不表示服务故障。
MinIO 社区仓库于 2026 年 4 月 25 日归档,本文采用社区源码构建恢复既有服务。该方式不代表上游仍提供持续安全维护;长期运行应规划维护版本或迁移。参见 MinIO 社区仓库。
HTTP 不加密登录信息、文件和预签名链接。公网长期使用应配置 HTTPS;9001 建议仅允许管理员公网 IP 访问。预签名 URL 在有效期内可被持有者使用,不要公开传播。
本指南适用于新目录部署。如果旧数据盘仍存在,先备份、确认挂载与数据版本,勿覆盖原目录。重新安装服务不会恢复已经丢失的对象。
2. 安装工具
以下命令在服务器 SSH 终端执行,源码构建使用普通用户,仅安装和系统配置使用 sudo。1
sudo pacman -Syu --needed base-devel git go python python-boto3 curl openssl nano
python-boto3 是 boto3 的 Arch 软件包,用于 Python 调用 S3 接口。MinIO 服务本身不依赖它,使用预签名 URL 的设备也无需安装。
3. 下载并构建 MinIO
1 | mkdir -p ~/minio-build |
如果 Git 自动将 GitHub 地址转换为失效代理,检查:1
git config --show-origin --get-regexp 'url\..*\.insteadof'
若存在下述旧配置,可移除后重新克隆:1
2git config --global --unset-all \
'url.https://mirror.ghproxy.com/https://github.com/.insteadOf'
如果 Go 依赖下载缓慢,设置模块代理:1
2go env -w GOPROXY=https://goproxy.cn,direct
go env GOPROXY
如果提示环境变量覆盖配置,在当前终端执行:1
export GOPROXY=https://goproxy.cn,direct
继续下载和编译:1
2
3
4
5cd ~/minio-build/minio
go mod download -x
go build -trimpath -o minio .
./minio --version
sudo install -m 0755 minio /usr/local/bin/minio
中断后可以重新执行,已下载的模块会复用,不要清理缓存。保留依赖校验,不要设置 GOSUMDB=off。若提示 Go 版本不足,升级至源码 go.mod 要求的版本。
4. 创建运行用户和目录
1 | id minio >/dev/null 2>&1 || sudo useradd \ |
如果使用独立数据盘,应先完成持久挂载,再调整数据路径及对应服务配置。
5. 设置管理员用户名和密码
1 | sudo nano /etc/minio/minio.env |
写入以下内容,把占位符替换为实际值,建议密码使用至少 24 位随机字母和数字:1
2
3MINIO_ROOT_USER=minio_admin
MINIO_ROOT_PASSWORD=REPLACE_WITH_A_NEW_RANDOM_PASSWORD
MINIO_REGION_NAME=us-east-1
可用下面的命令生成随机密码:1
openssl rand -hex 24
在 nano 中按 Ctrl+O、回车保存,Ctrl+X 退出,然后设置权限:1
sudo chmod 600 /etc/minio/minio.env
不要复用曾在聊天、截图或公开脚本中出现的旧密钥。
6. 配置 systemd 持久运行
以下配置按本次需求开放管理页面监听;安全组中应限制 9001 的访问来源。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30sudo tee /etc/systemd/system/minio.service >/dev/null <<'EOF'
[Unit]
Description=MinIO Object Storage
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/minio/data
[Service]
Type=simple
User=minio
Group=minio
EnvironmentFile=/etc/minio/minio.env
ExecStart=/usr/local/bin/minio server /var/lib/minio/data --address :9000 --console-address :9001
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/minio
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now minio
sudo systemctl status minio --no-pager
应显示 active (running)。验证健康状态和监听端口:1
2curl -i http://127.0.0.1:9000/minio/health/live
sudo ss -lntp | grep -E ':9000|:9001'
健康检查应返回 HTTP 200,正文可以为空。
修改管理员账号密码后,只需重启服务;修改 unit 文件后需要先执行 daemon-reload。更改管理员凭据后,使用旧凭据的脚本需要更新,旧凭据签发的链接也会失效。
7. 配置安全组和防火墙
在云平台安全组添加入站规则,保留现有 SSH 规则:
| 协议 | 端口 | 建议来源 |
|---|---|---|
| TCP | 9000 | 上传、下载设备所在网络;确需任意网络访问时再放宽 |
| TCP | 9001 | 管理员电脑公网 IP/32 |
检查本机使用的防火墙:1
sudo systemctl is-active ufw firewalld nftables
只修改已经在使用的防火墙,不要同时启用多套。
如果使用 UFW,替换示例 IP 后执行:1
2
3sudo ufw allow 9000/tcp
sudo ufw allow from YOUR_ADMIN_PUBLIC_IP to any port 9001 proto tcp
sudo ufw status
如果使用自定义 nftables 或 firewalld,在现有配置中添加对应端口和来源规则并持久保存;不要清空现有规则。
从电脑浏览器访问:
- 健康检查:
http://203.0.113.10:9000/minio/health/live - 管理页面:
http://203.0.113.10:9001/
管理页面使用第 5 步设置的账号密码。不同社区版本的管理界面功能可能不同,下面使用 boto3 创建 bucket,不依赖页面功能。
如果不需要公网管理页面,将服务中的 --console-address :9001 改为 --console-address 127.0.0.1:9001,关闭公网 9001,改用 SSH 转发:1
2# 在自己的电脑执行,替换 SSH 用户名
ssh -N -L 19001:127.0.0.1:9001 YOUR_SSH_USER@203.0.113.10
保持连接,浏览器打开 http://localhost:19001。
8. 配置 Python 凭据
以下命令在运行 Python 脚本的 Linux 机器执行;该机器需要安装 python-boto3。1
2
3
4
5
6
7/usr/bin/python -c "import boto3; print(boto3.__version__)"
export S3_ENDPOINT=http://203.0.113.10:9000
export AWS_ACCESS_KEY_ID=minio_admin
read -rsp "请输入 MinIO 管理员密码: " AWS_SECRET_ACCESS_KEY
echo
export AWS_SECRET_ACCESS_KEY
若使用其他用户名,替换 minio_admin。这些变量仅在当前终端有效,重新连接后需再次设置。不要把密钥硬编码进脚本或提交到代码仓库。
使用系统 Python 可以直接读取 pacman 安装的 boto3;默认虚拟环境无法读取系统包。若选择虚拟环境,需要单独在其中安装 boto3。
9. 创建私有 bucket
1 | mkdir -p ~/minio-tools |
保持 bucket 私有,不需要开启匿名读写。
10. 上传固件到服务器
将以下内容保存为 ~/minio-tools/publish_firmware.py:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#!/usr/bin/env python3
import argparse
import os
import boto3
from botocore.config import Config
p = argparse.ArgumentParser()
p.add_argument('file', help='本地固件文件路径')
p.add_argument('key', help='bucket 内的对象路径')
a = p.parse_args()
s3 = boto3.client(
's3', endpoint_url=os.environ['S3_ENDPOINT'],
region_name='us-east-1',
config=Config(signature_version='s3v4',
s3={'addressing_style': 'path'}),
)
s3.upload_file(a.file, 'firmware', a.key)
print('上传完成:firmware/' + a.key)
示例:1
2cd ~/minio-tools
/usr/bin/python publish_firmware.py ./controller-v1.bin releases/controller-v1.bin
./controller-v1.bin 是本地文件;releases/controller-v1.bin 是远端对象名,无需预先创建目录。
11. 生成下载和上传预签名 URL
保存为 ~/minio-tools/presign.py:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#!/usr/bin/env python3
import argparse
import os
import boto3
from botocore.config import Config
p = argparse.ArgumentParser()
p.add_argument('action', choices=['download', 'upload'])
p.add_argument('key', help='对象路径')
p.add_argument('--expires', type=int, default=3600)
a = p.parse_args()
if not 1 <= a.expires <= 604800:
p.error('--expires 必须在 1 到 604800 秒之间')
s3 = boto3.client(
's3', endpoint_url=os.environ['S3_ENDPOINT'],
aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'],
aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
region_name='us-east-1',
config=Config(signature_version='s3v4',
s3={'addressing_style': 'path'}),
)
download = a.action == 'download'
print(s3.generate_presigned_url(
ClientMethod='get_object' if download else 'put_object',
Params={
'Bucket': 'firmware' if download else 'diagnostic',
'Key': a.key,
},
ExpiresIn=a.expires,
HttpMethod='GET' if download else 'PUT',
))
生成固件下载链接,默认有效期 1 小时:1
/usr/bin/python presign.py download releases/controller-v1.bin
生成日志上传链接:1
/usr/bin/python presign.py upload logs/device001/20261028-001.log
生成链接本身不上传文件,也不检查 bucket 和对象是否存在。必须使用客户端可达的地址签名,不能签名后再替换 URL 中的 IP、端口或路径。
旧脚本的 put_object 对应日志上传;固件下载使用 get_object。9001 不能作为脚本的 S3 endpoint。
12. 验证上传和下载
下载固件:1
2
3DOWNLOAD_URL=$(/usr/bin/python presign.py download releases/controller-v1.bin)
curl --fail --show-error -o downloaded.bin "$DOWNLOAD_URL"
sha256sum controller-v1.bin downloaded.bin
两个文件的 SHA-256 应一致。设备正式升级还应验证可信固件签名。
上传日志:1
2UPLOAD_URL=$(/usr/bin/python presign.py upload logs/device001/20261028-001.log)
curl --fail --show-error --upload-file ./device.log "$UPLOAD_URL"
上传使用 HTTP PUT,正文为原始文件内容,不是 multipart/form-data。URL 必须加引号,避免其中的 & 被终端解释。同名对象上传会覆盖原对象,建议对象名包含设备编号、时间和唯一编号。
可用管理员凭据查看上传结果:1
2
3
4
5
6
7
8
9
10
11/usr/bin/python - <<'PY'
import os
import boto3
from botocore.config import Config
s3 = boto3.client(
's3', endpoint_url=os.environ['S3_ENDPOINT'], region_name='us-east-1',
config=Config(signature_version='s3v4', s3={'addressing_style': 'path'}),
)
print(s3.head_object(Bucket='diagnostic',
Key='logs/device001/20261028-001.log')['ContentLength'])
PY
13. 日常使用的最小权限账号(建议)
前述步骤使用管理员凭据完成初始化。日常签发 URL 应使用专用账号,管理员凭据仅用于管理和发布固件。
如果需要通过命令行配置账号,构建社区客户端 mc:1
2
3
4
5
6cd ~/minio-build
git clone https://github.com/minio/mc.git
cd mc
git rev-parse HEAD | tee ../mc-source-commit.txt
go build -trimpath -o mc .
sudo install -m 0755 mc /usr/local/bin/mc
在服务器终端中,用第 8 步的管理员环境变量配置连接:1
2mc alias set local http://127.0.0.1:9000 \
"$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY"
mc 会保存管理凭据,请保护当前用户账号和 mc 配置文件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25cd ~/minio-tools
cat > device-policy.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::firmware/*"]
},
{
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": ["arn:aws:s3:::diagnostic/*"]
}
]
}
EOF
mc admin policy create local device-policy device-policy.json
DEVICE_SECRET=$(openssl rand -hex 32)
mc admin user add local device_signer "$DEVICE_SECRET"
mc admin policy attach local device-policy --user device_signer
printf '账号:device_signer\n密钥:%s\n' "$DEVICE_SECRET"
unset DEVICE_SECRET
将输出的新密钥存入密码管理器,然后将第 8 步的账号改为 device_signer,输入它的密钥,再运行 presign.py。该账号可下载固件、上传日志,但不能发布固件、删除对象或列出 bucket。
这个权限覆盖整个日志 bucket。若需要按设备隔离,应为每个设备或签发服务设置更窄的对象前缀和授权逻辑。密钥保存在签发端,设备只接收对应的预签名 URL。
14. 运行维护与故障排查
1 | sudo systemctl status minio --no-pager |
| 问题 | 检查方法 |
|---|---|
| ModuleNotFoundError: boto3 | 安装 python-boto3,使用 /usr/bin/python;检查是否误用了虚拟环境 |
| Go 依赖下载卡住 | 配置 GOPROXY,运行 go mod download -x 查看具体请求 |
| 本机健康检查成功,公网超时 | 云安全组、本机防火墙、实际公网 IP |
| 管理页面打不开 | 确认监听 :9001、安全组来源是否与当前电脑公网 IP 一致 |
| 9000 显示 XML 或 AccessDenied | 这是 S3 接口;管理页面在 9001 |
| SignatureDoesNotMatch | 凭据、HTTP 方法、URL 是否被修改、额外签名请求头是否一致 |
| AccessDenied | 签名账号权限、bucket、对象路径、链接是否过期 |
| NoSuchKey | 固件未上传,或对象路径、大小写不一致 |
| 链接立即失效 | 检查签发机器与服务器时间及凭据是否发生更改 |
| 服务无法启动 | 查看 journalctl;检查配置、目录权限、磁盘挂载和端口占用 |
首次部署后可在维护窗口重启服务器,验证服务自动启动、健康检查正常且已有对象可读。
单机存储不等于备份。为数据、账号策略和服务配置安排异机备份;使用 S3 工具复制对象,或停服后做一致性磁盘备份,并验证恢复流程。不要手工修改运行中的 MinIO 数据目录。
15. 参考资料
本文根据本次恢复过程整理;具体服务器的命令执行结果以现场验证为准。