Skip to content
twinkling.top服务MinIOEN
板型Pi 4B 4GB and up, with the data on the SSD rather than the SD card without exception
内核6.6.51+rpt-rpi-v8
空闲温度48 °C
内核架构arm64
参考机:Pi 4B 8GB / Bookworm 64-bit

服务卡片 · 文件与存储

把 MinIO 当作备份目标:机架上的 S3,给那些只认它的工具用

这台机架上的备份去三个地方:NAS、一个加密的 restic 仓库、以及异地。MinIO 存在的理由是,越来越多的备份工具只讲 S3、别的都不讲——restic、Duplicati、Immich 和 Nextcloud 的备份脚本,以及那个只接受 S3 端点的容器备份工具。在这里跑一个,就意味着这些工具能拿到它们想要的接口,而不需要在别处开账号。

minio/minio:RELEASE.2026-01-15T00-00-00Z · 2026-10-23 ·

MinIO rack plate: board stack and host ports
服务参数
容器镜像minio/minio:RELEASE.2026-01-15T00-00-00Z
宿主端口:9000/tcp, :9001/tcp
数据目录/srv/homelab/minio/data
内存预留340 MB
CPU 上限0.50 vCPU (cpus: "0.50")
更新节奏quarterly, and the version string is date-based. The project publishes a community release and the AGPL terms changed once already, so the pinned tag matters more here than anywhere else on the rack
ARM 兼容arm64 native; erasure coding across multiple drives is not used here because a single-drive setup has nothing to code against
端口映射与暴露面
宿主容器proto暴露用途
:90009000tcp仅局域网the S3 API that backup tools and applications write to
:90019001tcp仅局域网the web console, used for browsing buckets and issuing access keys

部署步骤

  1. 在首次启动前替换默认 root 凭据

    镜像拒绝用文档里那套默认值启动,这是刻意的安全设计。把两个值都生成出来,之后再也不要把它们手打进工具配置里。

    run
    echo "MINIO_ROOT_USER=rackroot" >> /srv/homelab/.env
    echo "MINIO_ROOT_PASSWORD=$(openssl rand -base64 32 | tr -d '/+=')" >> /srv/homelab/.env
    chmod 600 /srv/homelab/.env
  2. 建桶时就启用对象锁定,事后补不了

    这是唯一一个必须在写入第一个字节之前定下来的决定。已有的桶之后无法启用对象锁定,只能重建桶、重新初始化仓库。

    run
    cd /srv/homelab/minio && docker compose up -d
    docker exec -it minio mc alias set rack http://127.0.0.1:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD"
    docker exec -it minio mc mb --with-lock rack/restic-rack
  3. 给每个写入应用单独签发一个限定范围的密钥

    共用一个凭据,意味着四个工具里任何一个都能删掉一切。限定范围的密钥能把「全盘沦陷」变成「局部失控」,而且配置成本为零。

    run
    docker exec -it minio mc admin user add rack immich-backup "$(openssl rand -base64 24)"
    docker exec -it minio mc admin policy create rack only-immich-dumps /config/policies/immich.json
    docker exec -it minio mc admin policy attach rack only-immich-dumps --user immich-backup

桶里到底放什么

四个性格不同的桶。restic-rack 只允许追加,装着每晚备份写入的加密仓库。immich-dumps 装着那些否则就会变成「一个等着被遗忘的本地文件」的数据库导出。nextcloud-cold 装着每季度才写一次的归档导出。tmp-share 就是它听起来的样子——工具们用作暂存区的临时桶,配了一条把超过七天的对象删掉的生命周期规则。

桶写入方版本控制生命周期
restic-rack派上的 restic启用,对象锁定无,只追加
immich-dumpsImmich 备份任务启用30 天后过期
nextcloud-cold季度导出任务启用无
tmp-share各类工具关闭7 天后过期

对象锁定才是让它成为备份的东西

一个以备份用户身份运行的勒索进程可以删掉备份仓库。带保留期的对象锁定让这些对象在一段确定的时间内不可变,于是删除会失败,仓库得以存活。

前提是对象锁定必须在建桶时启用,之后补不了。这是在写入第一个字节之前就值得定下来的唯一一个设置,因为事后没有任何办法补上它。

shell
mc mb --with-lock rack/restic-rack
mc retention set --default GOVERNANCE 30d rack/restic-rack
mc version enable rack/restic-rack
mc ilm rule add --expire-days 7 rack/tmp-share

每个写入方一个密钥,以及为什么

四个工具共用一个 S3 凭据,意味着其中任何一个都能读取和删除全部内容。限定作用域的密钥不花任何代价,却能把「全盘沦陷」变成「局部失控」。

每个密钥拿到的策略只允许访问自己的那个桶,别的都不行——没有账号级的桶列举权限,访问不了控制台。策略文件和其它配置一起放在仓库里。

shell
mc admin user add rack immich-backup "$IMMICH_S3_SECRET"
mc admin policy create rack immich-dumps-only /config/policies/immich.json
mc admin policy attach rack immich-dumps-only --user immich-backup

关于性能,说点实话

树莓派上的 MinIO 走千兆链路加 USB 固态盘,写入大约每秒 60 到 90MB——对每晚备份来说完全够用,而对任何对延迟敏感的主存储层来说完全不适合。它是一个讲 S3 的备份目标,不是 NAS 的替代品。

它真正挣到位置的地方是异地复制:MinIO 能把一个桶镜像到另一个兼容 S3 的端点,于是本地一个桶变成两地备份,一条命令的事,不用再添一个备份工具。

shell
mc mirror --watch rack/restic-rack remote/restic-rack
# 或者用定时的单向同步,而不是 watch 循环

compose 文件

整份文件放在 /srv/homelab/minio/compose.yaml。标签固定版本号,不用 latest——树莓派上回滚比升级麻烦得多。

compose.yaml
services:
  minio:
    image: minio/minio:RELEASE.2026-01-15T00-00-00Z
    container_name: minio
    restart: unless-stopped
    command: server /data --console-address ":9001"
    ports:
      - "9000:9000/tcp"
      - "9001:9001/tcp"
    environment:
      TZ: Asia/Shanghai
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
      MINIO_BROWSER_REDIRECT_URL: https://objects.lan
      MINIO_SERVER_URL: https://objects.lan:9000
    volumes:
      - /srv/homelab/minio/data:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks: [rack]

networks:
  rack:
    external: true

加固清单

  • 默认 root 凭据在首次启动前就被替换;镜像拒绝用文档里那套默认值启动,这是刻意的安全设计
  • 每个写入方一个访问密钥,作用域限定在单个桶,被攻陷的备份客户端读不到别的应用的桶
  • 控制台在局域网内并置于认证门户之后;S3 API 端口只有写入它的容器能访问
  • 存放 restic 仓库的那个桶启用了版本控制和对象锁定,这是让「被勒索删除」可恢复的关键

备份方案

这些桶里装的就是备份数据,再备份一次会变成循环。真正保护的是配置:访问密钥、桶策略和生命周期规则都记录在仓库里,底层卷按和别的东西一样的计划同步到 NAS。

上线后验证

  • restic 备份能写入 restic-rack 桶,且 restic check 校验仓库通过
  • 在保留期内删除对象会以 governance 错误失败,说明对象锁定生效了
  • immich-backup 这个密钥能写自己的桶,尝试列举别的桶时被拒绝
  • 网页控制台里四个桶的版本控制和生命周期设置都符合预期

踩过的坑

  • 对象锁定不能在已有的桶上启用。如果 restic 仓库是在没有它的情况下建的,就得重建桶、重新初始化仓库,代价是一整个备份周期。
  • root 凭据不是任何工具该用的凭据。用 root 配置的工具能删掉每一个桶,这把作用域密钥的意义全抵消了。
  • 在 SD 卡上跑 MinIO 会把卡写坏。它是机架上写入最重的服务,和其余数据一样,该待在固态盘上。
  • 基于日期的发布标签不遵循语义化版本,而且社区版已经改过一次许可条款。读发布说明,锁定一个具体标签,别追 latest。

硬件与选型问答

NAS 已经能提供 SMB 了,还需要 MinIO 吗?
只有在某个工具要求 S3 时才需要。SMB 是文件系统协议,对任何能挂载共享的东西都适用;S3 是对象 API,带版本控制、对象锁定和生命周期规则,这是文件系统共享给不了的。这里的典型案例就是 restic 仓库:只追加、不可变、有版本,而且必须能被一个只讲 S3 的工具访问。
相比一个普通的目录,它增加了多少开销?
340MB 内存,多一个要打补丁的服务,以及相比直接写文件系统大约百分之十的吞吐损失。换来的是接口契约:备份工具完全不需要知道机架的文件系统布局,而桶可以被镜像到别处而不改工具配置。
能让 NAS 和 MinIO 用同一块卷吗?
物理上可以,但这是个坏主意:备份目标的意义就在于它能挺过被备份对象的故障。如果 NAS 的卷和 MinIO 的数据在同一块盘上,一次盘故障会同时带走数据和备份。本机架把它们放在不同设备上,MinIO 的数据在派的固态盘里。