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とクレデンシャルを差し替えるだけで、既存のバックアップジョブが自分のハードウェアへの書き込みを開始する。

