S3互換のオブジェクトストレージ minio を動かしてNextcloudのプライマリストレージにする

経緯

現在我が家では自宅サーバが一機稼働している1のだが、諸々の理由2により、将来的にraspberry pi のような省電力で安価なSBCとコンテナを利用したクラスタ構成にしたいと思っている。

その際、バックアップやセキュリティの都合上、オブジェクトストレージやデータベースといった、永続化したいサービスのみファイルサーバで動かし、それ以外のウェブアプリケーションは別のホストに分離したい。

ということで、今回はその第一歩として、MinIOというS3互換のオブジェクトストレージを起動し、Nextcloudのストレージとして使えるようにしてみる。

初めに

本記事で扱うこと

本記事で扱わないこと

バージョン情報

$ uname -a                                                                                                                       
Linux fox 5.4.169-1-MANJARO #1 SMP PREEMPT Wed Dec 29 18:08:59 UTC 2021 x86_64 GNU/Linux
$ podman --version                                                                                                               
podman version 3.4.4
$ mcli --version
mcli version RELEASE.2021-12-10T00-14-28Z

Minioの起動

公式の例ではコンテナを扱うコマンドとして、docker ではなく podman というのを使っていた。 podman は初見ではあったが docker もたいして使ったことがあるわけでもないので公式のマニュアル通り無難に podman を使う。

$ sudo pacman -S podman

podmanでminioを起動する。 各引数は-dでバックグラウンド化、-pでポートを、-vでホストのボリュームをマウント、-eで環境変数を指定している(基本的にはDockerと同じはず)。

$ sudo podman run -d \
  -p 9000:9000 \
  -p 9001:9001 \
  -v /bottle/minio:/data \
  -e "MINIO_ROOT_USER=minioadmin" \
  -e "MINIO_ROOT_PASSWORD=<miniopassword>" \
  quay.io/minio/minio server /data --console-address ":9001"

ちなみに、上記の管理ユーザや後で作成するnextcloudユーザもそうだが、MinIOでのユーザ名とパスワードは、S3でいうところのAccess key Id, Secret Access Keyと共用となっている模様。

9000ポートでオブジェクトストレージに、9001ポートでコンソールにアクセスできる。

Minioの設定

MinIO Client (mc) — MinIO Baremetal Documentation

Webコンソールも使えるのだが、基本的な設定はCLIでできるようにしたいので、今回はmcmcli)というMinIO用のクライアントコマンドを使って設定していく。

$ sudo pacman -S minio-client

サーバの登録

mcli alias set で、9000ポートを local という名前に紐づける。git でいうところのgit remote add のような感じ。

$ mcli alias set local http://localhost:9000
Enter Access Key: minioadmin
Enter Secret Key: 
Added `local` successfully.

パスワードやIDは podman run 時に指定した管理用の物を入力する。

バケットの作成

mcli mb でバケットの作成

$ mcli mb local/nextcloud
Bucket created successfully `local/nextcloud`.

mcli ls で確認できる

$ mcli ls local
[2022-01-23 11:34:02 JST]     0B nextcloud/

ポリシーの作成

Amazon S3公式の例(S3 バケットのオブジェクトへの読み取りおよび書き込みアクセスを許可する)を参考に nextcloud バケット用のポリシーを作成する

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListObjectsInBucket",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::nextcloud"
      ]
    },
    {
      "Sid": "AllObjectActions",
      "Effect": "Allow",
      "Action": [
        "s3:*Object*"
      ],
      "Resource": [
        "arn:aws:s3:::nextcloud/*"
      ]
    }
  ]
}

このjsonを nextcloud ポリシーとして読み込む

$ mcli admin policy add local nextcloud nextcloud.json

ユーザの作成、ポリシーの割り当て

nextcloud ユーザを作成する

$ mcli admin user add local nextcloud nextcloudpasswd
Added user `nextcloud` successfully.

nextcloud ユーザに nextcloud ポリシーを紐づける。

$ mcli admin policy set local nextcloud user=nextcloud
Policy `nextcloud` is set on user `nextcloud`

これでnextcloudユーザがnextcloudバケットの読み書きができるようになったはず。

Nextcloud の設定

今回はNextcloud内部に全くデータを置かないというのが理想なので、dataディレクトリ(マニュアル曰くPrimary Storage)を丸々オブジェクトストレージに差し替える設定をする。3

設定ファイルに objectstore の追記

以下のようにNextcloudの設定ファイルの最後に objectstore を追加する

<?php
$CONFIG = array (
  /* 中略 */
  'objectstore' => array (
    'class' => 'OC\\Files\\ObjectStore\\S3',
    'arguments' => 
    array (
      'bucket' => 'nextcloud', //MinIOのバケット名
      'autocreate' => true, // 未検証、おそらくバケットがない場合作るものと思われるが、今回は作成済みのため関係ないはず。
      'key' => 'nextcloud', // MinIO上の`nextcloud`用ユーザ
      'secret' => '****************************************', // MinIO上の`nextcloud`ユーザのパスワード
      'hostname' => 'localhost', //MinIOのホスト名
      'port' => 9000, //MinIOのポート
      'use_ssl' => false, //ssl を使うかどうか、今回はローカルなので不要。
      'use_path_style' => true, // バケットをパスで指定するかドメインで指定するか。今回は手っ取り早くlocalhostでアクセスするためパスで指定する。なお、本家AWS S3ではパス指定は非推奨
    ),
  ),
);

設定自体はこれだけで完了、MinIOにアクセスできるようになっている。

結果

設定直後のNextcloud Filesの様子がこちら、Nextcloud Notes アプリが作成した Documents/Note フォルダ以外は空っぽになっていることがわかる。

空っぽになったNextcloud filesの画像 Minioのコンソールで確認すると、すでに多数のファイルが追加されていることがわかる。

バケットの画像

ちゃんと読み書きできている模様。

ファイル名はすべてIDらしきものになっており、これだけだとどれがどのファイルなのかはわからない。

参考までに、以下がデフォルト(objectstore未設定時)のdataディレクトリの中身、上記のMinioとは全く異なっていることがわかる。

sudo tree -L 3 /usr/share/webapps/nextcloud/data                                                                                               
/usr/share/webapps/nextcloud/data
├── appdata_************
│   #中略
├── files_external
│   └── rootcerts.crt
├── fluo10
│   ├── cache
│   ├── files
│   │   ├── Documents
│   │   ├── InstantUpload
│   │   ├── Nextcloud intro.mp4
│   │   ├── Nextcloud Manual.pdf
│   │   ├── Nextcloud.png
│   │   ├── Notes
│   │   ├── Pictures
│   │   ├── Reasons to use Nextcloud.pdf
│   │   └── Talk
│   ├── files_trashbin
│   │   ├── files
│   │   ├── keys
│   │   └── versions
│   ├── files_versions
│   │   ├── Documents
│   │   ├── InstantUpload
│   │   └── Pictures
│   └── uploads
├── index.html
├── nextcloud.log
└── nextcloud.log.1

パスの構造が全く違うため、通常のバックアップやリストアのように、単にディレクトリをコピペして移行するのは無理そう。今回はユーザーが筆者一人であり、クライアント側にあるデータを同期し直せば済む(タイムスタンプは残らなそうだが)ので、サーバ側での作業はこれでヨシとする。

その他参考ページ


  1. NextcloudやGitea, mpdなど、自分用のサービスをまとめて動かしてVPN経由で屋外からアクセスできるようにしている。自作PCのあまりパーツを流用したもので、無駄にRyzenを積んでおり、力を持て余している感が否めない。 ↩︎

  2. 理由としては省電力化やハードウェアのスケーリングや冗長化、セキュリティ向上のためのホストの分離、とくにファイルサーバとそれ以外の機能はなるべく分離したい。 ↩︎

  3. ちなみにGUIから設定できる外部ストレージ機能もあるのだが、それとは別の機能。単に外部のストレージを使うだけならsmb/cifsが使えるそっちの方が手軽かも知れない。 ↩︎