セルフホストS3互換ストレージ:HomeLabのバックアップとメディア管理にDockerでMinIOを活用する

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

HomeLabを構築して3ヶ月後、AWS S3の請求額が月40ドルを超えるようになっていた。特別なことをしていたわけではない——VMスナップショット、Grafanaダッシュボードのエクスポート、時々のDockerボリュームバックアップを保存していただけだ。新しいサービスを追加するたびに、その数字は着実に増えていった。

心当たりがあるなら、MinIOが解決策だ。MinIOは自分のハードウェアで動かせるS3互換のオブジェクトストレージサーバーで、HomeLabで1年以上運用してきたが、以来クラウドに戻る気は一切ない。

本当の問題:クラウドストレージコストの忍び寄る増大

HomeLabの文脈でオブジェクトストレージのコストがいかに早く積み上がるか、多くの人は過小評価している。AWS S3は数ギガバイト程度なら安いが、バックアップを自動化し始めた瞬間——データベースの日次スナップショット、Dockerボリューム、設定ファイル——気づかないうちに数百ギガバイトを扱うことになる。

コスト以外にも、レイテンシの問題がある。バックアッププロセスがus-east-1のS3に書き込み、HomeLabが東京にある場合、すべてのバックアップジョブでリクエストごとに150ms以上のレイテンシが加算される。大きなファイルでは、10分のバックアップ処理が45分に膨れ上がる。

より根本的な問題は、ローカルネットワークの外に出ないデータに対して、サードパーティのサービスへの依存を作り上げてしまっているということだ。Restic、Duplicati、Nextcloud、その他多数のセルフホストツールがすべてS3をサポートしている——つまり、これらすべてをローカルのMinIOインスタンスに向けることができるのだ。

クラウドS3が常に正解ではない理由

AWS S3は大規模な本番ワークロードには本当に優秀だ。しかし、HomeLabの使い方はそのプロファイルとは合わない:

  • データがローカルネットワークの外に出ることはほとんどないため、エグレス費用は価値ではなくコスト増の原因に過ぎない
  • JellyfinのメディアキャッシュやGrafanaのバックアップに、イレブンナインの耐久性は必要ない
  • 無料プランのAPIレート制限が、自動バックアップスケジューラーを壊してしまう
  • プライバシー:サードパーティのクラウドプロバイダーに置きたくないデータも存在する

根本的な原因は、クラウドストレージの料金モデル(GB単位+リクエスト単位+転送単位の課金)とHomeLabの使用パターン(バースト書き込み、ローカル読み取り、柔軟な保持期間)との間のミスマッチにある。

セルフホストオブジェクトストレージ:どんな選択肢があるか?

MinIOに決める前に、3つの代替案を検討した:

Ceph

エンタープライズ向けの選択肢だ。Cephは分散構成でオブジェクト、ブロック、ファイルストレージを扱える。本番環境グレードだが、シングルノードのHomeLabには過剰設計もいいところだ。最小限のデプロイでも3ノードとかなりのRAMオーバーヘッドが必要になる。マルチサーバーラックを運用しているのでなければ、候補から外してよい。

Garage

セルフホストのユースケース向けに設計された軽量なRust製の代替ツールだ。メモリフットプリントが非常に小さく、Raspberry Pi上でも問題なく動作する。ただし、エコシステムのサポートはまだ追いついていない——GarageのAPI実装と正しく動作させるためにワークアラウンドが必要なS3クライアントも存在する。

MinIO

HomeLabにとってのスイートスポットだ。S3互換APIにより、S3をサポートするあらゆるツールがそのまま動作する——クライアント側の設定変更はゼロだ。シングルノードで効率よく動作し、クリーンなWeb UIも備えている。活発な開発が続けられ、ドキュメントも充実している。コミュニティエディションはAGPLのもとで完全なオープンソースだ。

クライアントプロジェクトと自分のHomeLabの両方でMinIOを本番環境に適用してきたが、結果は一貫して安定していた。Resticのバックアップターゲットから Nextcloudの外部ストレージまで、あらゆる用途を問題なく処理する。

DockerでMinIOをセットアップする

実際に私が使っているセットアップを紹介する。専用ディレクトリにdocker-compose.ymlを作成しよう:

version: '3.8'

services:
  minio:
    image: quay.io/minio/minio:latest
    container_name: minio
    restart: unless-stopped
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: admin
      MINIO_ROOT_PASSWORD: your_strong_password_here
      MINIO_VOLUMES: /data
    volumes:
      - /opt/minio/data:/data
    ports:
      - "9000:9000"   # S3 API
      - "9001:9001"   # Webコンソール
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 10s
      retries: 3

最初から正しく設定しておくべきことがいくつかある:

  • /opt/minio/dataには適切なパスを使用しよう——OSドライブではなく、専用ディスクかZFSデータセットが理想的だ
  • 強いrootパスワードをすぐに設定すること。MinIOのAPIはネットワーク越しにアクセス可能であり、デフォルト認証情報はHomeLabセットアップにおけるセキュリティミスの第1位だ
  • --console-address ":9001"により、APIポート(9000)とWeb UIポート(9001)が分離される——NginxやTraefikをフロントに置く場合に重要だ

起動して確認しよう:

docker compose up -d
docker compose logs -f minio

http://your-server-ip:9001でコンソールにアクセスし、最初のバケットを作成しよう。

rootクレデンシャルではなくサービスアカウントを使う

アプリケーションの設定にrootクレデンシャルを使ってはいけない。MinIOには適切なIAMサポートがある——アクセスが必要なアプリケーションごとにサービスアカウントを作成しよう。

MinIOコンソールから:Identity → Service Accounts → Create

またはMinIOクライアント(mc)を使って:

# mcをインストール
curl -O https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/

# エイリアスを設定
mc alias set local http://localhost:9000 admin your_strong_password_here

# Resticバックアップ専用ユーザーを作成
mc admin user add local restic-user restic_password_here

# 権限を制限したポリシーを作成
cat > restic-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::restic-backups/*", "arn:aws:s3:::restic-backups"]
    }
  ]
}
EOF

mc admin policy create local restic-policy restic-policy.json
mc admin policy attach local restic-policy --user restic-user

これで、Resticジョブは自身のバケットにしかアクセスできなくなり、クレデンシャルが漏洩しても他のものには手が届かない。

各ツールをMinIOに向ける

S3互換性こそがMinIOを本当に有用にしている。最も一般的なHomeLabツールの設定方法を紹介する:

Restic

export AWS_ACCESS_KEY_ID=restic-user
export AWS_SECRET_ACCESS_KEY=restic_password_here
export RESTIC_REPOSITORY=s3:http://your-server:9000/restic-backups

restic init
restic backup /path/to/data

rclone

rclone config create minio-local s3 \
  provider=Minio \
  access_key_id=your-access-key \
  secret_access_key=your-secret \
  endpoint=http://your-server:9000

# 動作確認
rclone ls minio-local:restic-backups

Nextcloud External Storage

External Storage Supportアプリをインストールし、MinIOのクレデンシャルでhttp://your-server:9000を指すS3互換ストレージエントリを追加する。Nextcloudの観点からは、本物のAWS S3バケットとまったく同じように動作する。

1年以上MinIOを運用して得たTips

これらはドキュメントには書かれていなかった教訓だ:

バケットライフサイクルポリシーを設定する

ライフサイクルルールがないと、古いバックアップが永遠に蓄積される。長期保持が不要なバケットには自動期限切れを設定しよう:

mc ilm add local/restic-backups --expiry-days 90

重要なバケットではバージョニングを有効にする

設定ファイルや重要なアプリケーションデータを保存するバケットにはバージョニングを有効にしよう。壊れたバックアップスクリプトが正常なデータを破損したアーカイブで上書きしてしまったとき、これに救われたことがある:

mc version enable local/config-backups

ディスク使用量を積極的に監視する

MinIOはディスクがほぼ満杯になってもWriteを絞らない——ただサイレントに失敗し始めるだけだ。シンプルなcronチェックを追加しよう:

# crontabに追加:1時間ごとにチェック
0 * * * * df -h /opt/minio/data | awk 'NR==2{if($5+0 > 85) print "警告: MinIOディスク使用量 "$5}' | mail -s "MinIOディスクアラート" [email protected]

TLSのためにリバースプロキシの背後に置く

LANの外からMinIOにアクセスする場合は、TLSを使ったNginxかTraefikをフロントに置こう。暗号化されていないHTTPでS3クレデンシャルを送信することは、共有ネットワークセグメント上では現実のリスクだ。基本的なNginx設定:

server {
    listen 443 ssl;
    server_name minio.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/minio.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/minio.yourdomain.com/privkey.pem;

    # S3 API
    location / {
        proxy_pass http://localhost:9000;
        proxy_set_header Host $host;
        client_max_body_size 0;  # 大容量ファイルのアップロードに必要
    }
}

既存の監視システムと統合する

MinIOは/minio/v2/metrics/clusterでPrometheusメトリクスを公開している。HomeLabですでにPrometheusとGrafanaを運用しているなら、MinIOをスクレイプターゲットに追加するだけで、ディスクI/O、リクエストレイテンシ、バケットごとのストレージグラフが追加作業なしで手に入る。

MinIOが置き換えられないもの

シングルノードのMinIOには冗長性がない——ZFSミラーやRAIDを下層で使っていない限り、ディスク障害はデータ損失を意味する。バックアップ戦略の1つの層として扱い、唯一のコピーにはしないこと。

私が守っているルール:重要なデータはMinIO(ローカル、高速、常時利用可能)に置き、rclone経由でBackblaze B2(月額6ドル/TBの安価なコールドストレージ)にオフサイト同期する。セルフホストしていても、3-2-1バックアップルールは適用される。

クラウドストレージの費用削減を先延ばしにしてきた人へ——上記のMinIOセットアップにかかる時間は約20分だ。ほとんどのS3互換ツールはコード変更なしに接続できる——エンドポイントURLとクレデンシャルを差し替えるだけで、既存のバックアップジョブが自分のハードウェアへの書き込みを開始する。

Share: