Synology Docker での Nextcloud の構築方法

Synology DSM 7.1 上で Docker パッケージを使って Nextcloud をホストする方法について、日本語で書かれたドキュメントがあまりないな～と思ったので、書き起こしてみます。
また、セキュリティ＆セットアップ警告で「すべてのチェックに合格しました」が表示されるところまでを目標としてみます。このために若干ムチャもしています。

# 前提
以下の環境が用意されていることを前提としています。
- Synology 社製 DiskStation NAS があること。DSMのバージョンは7.x
- Let's Encrypt で Synology DSM (大雑把に言えば Synology NASの管理画面のことです) に対してSSLサーバー証明書が設定されていること
- ヘアピンNATに対応したルーターであること（宅内からDSMのSSLサーバー証明書が設定されたドメインへアクセスできるのであれば、必ずしもその必要はありません）
- 可能であれば、ほかの環境で Nextcloud をセットアップした経験があること

# わかる人向けのミソ
このポイントに気を付けてセットアップしてね、で通じるのであれば、以下の文章を読む必要はありません。

- 外部への露出のために Synology DSM のリバースプロキシ機能を使っています。これによって、Let's Encrypt サーバー証明書の更新を Synology DSM が勝手にやってくれるようになります。
- 共有フォルダーにDockerコンテナ外に置かれる(永続化される)ファイルを置くフォルダーをいくつか作成しています。MariaDB コンテナに見せるフォルダーと、Nextcloudコンテナに見せる data と config と custom_apps のフォルダーについて、Synology DSM の Everyone ユーザーに読み書きの許可を与えています。
- Nextcloud の config.php に以下を書いています。
```
'overwriteprotocol' => 'https',
'default_phone_region' => 'JP',
```

- Nextcloud に設置される .htaccess を永続化してカスタマイズしています。
以下の記述について、
```
RewriteRule ^.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^.well-known/caldav /remote.php/dav/ [R=301,L]
```
以下のようになおしています。
```
RewriteRule ^.well-known/carddav https://%{SERVER_NAME}:%{SERVER_PORT}/remote.php/dav/ [R=301,L]
RewriteRule ^.well-known/caldav https://%{SERVER_NAME}:%{SERVER_PORT}/remote.php/dav/ [R=301,L]
```
- Nextcloud コンテナ内に ImageMagick をインストールします。
```
apt update
apt install -y imagemagick
```

# 構築前の下準備
ということで、いってみましょう。まずは下準備から。

## Let's Encrypt 証明書の取得
この手順では、Synology DSMで取得したLet's Encrypt証明書をDocker上にこれから構築しようとしているNextcloudでも使用する。
Synology DSMへのログインにHTTPSが利用できているのであれば、特に問題ない。もし設定されていない場合は、このへんを読んで設定してほしい。
[Synology NASでLet's Encryptから証明書を取得する方法は？](https://kb.synology.com/ja-jp/DSM/tutorial/How_to_enable_HTTPS_and_create_a_certificate_signing_request_on_your_Synology_NAS)

## Synology DSM で取得した証明書を Nextcloud で使う設定
Synology DSMのコントロールパネル > ログイン ポータル > 詳細設定 > リバース プロキシ > 作成で以下のようにする。

| 設定名 | 設定値 | 
| ----- | ----- |
| プロキシ名を反転 | Nextcloud（ここはただの設定名を書くところ　多分）|
| Target | |
| プロトコル | HTTPS |
| ホスト名 | 何も書かない |
| ポート | ｘｘｘｘｘ（Nextcloudクライアントで指定するポート。ルーターで開いてあればなんでもよい）|
| HSTSを有効にする | チェックオン（たしかこれをオンにしないとNextcloudのセキュリティチェックで怒られた気がする）|
| 送り先 | |
| プロトコル | HTTP |
| ホスト名 | localhost |
| ポート | 8088（なんでもよい）|

カスタムヘッダーや詳細設定のタブは何も変更しなくてもよい。

念のため
コントロールパネル > セキュリティ > 証明書 > 設定 で
*:先ほど追加したTargetのポート番号　の設定で使う予定のドメインの証明書が選ばれていることを確認しておく。

なお、https:// 証明書のドメイン名/ でSynology DSMが開かない場合は、ルーターがヘアピンNATに対応していないと思われます。
この場合は、Hostsでなんとかする必要がでてきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673401/0998d412-a4c2-8ed7-3617-295c1c521e10.png)

### 利用している回線が v6プラス の場合は...
本筋から脱線しますが、回線がv6プラスの場合では、IPv4で利用可能なポート番号が制限されています。
IPv4環境しかない外部から Nextcloud へアクセスする必要がでてきたとき、この利用可能なポート番号の範囲内でTargetのポート番号を設定しておかないと
アクセスできないことになってしまいます。

あとからURLを変えるのは面倒なので、ちゃんと調査しておきましょう。
http://ipv4.web.fc2.com/map-e.html

# 共有フォルダを作成する
この共有フォルダにNextcloudのデータや、MariaDBコンテナのデータベースなどDockerで永続化するデータを保存する。

コントロールパネル > 共有フォルダ > 作成 ボタンで共有フォルダをひとつ作成する。
名前は Nextcloud などとする。

ごみ箱機能は有効化していない。Nextcloud 上に機能として存在するし、そちらを使うのがスマートであるため Synology 上では有効化しない。
そのほか、この共有フォルダへのアクセス権は Synology NAS へパソコンからアクセスする際に使用しているユーザーのみに与えている。

| 設定名 | 設定値 | 
| ----- | ----- |
| 名前 | Nextcloud |
| ごみ箱を有効にする | オフ |
| ユーザー許可を作成 | 自分の作ったユーザーのみ「読み取り/書き込み」にチェック |

## Docker で永続化するファイルを保存するフォルダの作成
File Station を使って、今作成した Nextcloud 用のフォルダーに以下のフォルダを作成する。
- data
- mysql
- htaccess
- config
- custom_apps

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673401/0272b390-cefb-c3cf-fecb-7ed403edcdc0.png)

## フォルダーへのアクセス権の設定
なぜかこの設定をしないと、これから作成する MariaDB の Docker コンテナが起動せずコンテナ再起動ループにはまってしまいますし
Nextcloud は内部サーバーエラーとなってセットアップを開始できません。

File Station で Nextcloud 用フォルダーの中に作成した「mysql」フォルダを右クリックして「プロパティ」を選択。
所有者のタブで Synology DSM にログインするのに使っているユーザーを選んでから「許可」タブをクリックし「作成」ボタンをクリック。

ユーザーのところをクリックすると、ユーザーの一覧がポップアップしますので「Everyone」にチェックを入れます。
それから「許可」の一覧にある「読み取り」と「書き込み」にチェックを入れます。
子項目はすべてチェックを入れたままでOKですので「完了」をクリックします。

このあと、**data、config、custom_apps のフォルダーにも同じ設定を行います(重要)**。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673401/3db2d998-8a5b-cd96-663d-627ae918a9c4.png)

# パッケージセンターで Docker パッケージをインストールする
Synology 純正の Docker パッケージをインストールするだけで Docker の実行環境が手に入るようになっているので、長い物には巻かれるようにインストールを行う。

Synology DSMのデスクトップから「パッケージセンター」を起動し、「Docker」を検索して「インストール」ボタンをクリックしてインストールする。
今回はこの手順は筆者はずいぶん前に実施済みのため、何か設定項目があったかどうかもわすれてしまったが、たぶん大したことは聞かれていないはず。

インストールすると「開く」ボタンが押せるようになる。

# 「レジストリ」から必要なイメージをダウンロードする
この画面の翻訳が微妙で Docker イメージのことがすべて「画像」と表現されているんだけど、気にしない。

Docker を開いて「レジストリ」から以下の項目を探して「ダウンロード」する。今回はすべて「latest」のタグでダウンロードしている。
- Nextcloud
青いチェックマークのついた「nextcloud」を選択して「ダウンロード」ボタンを押して「latest」タグのイメージをダウンロードする。

- MariaDB
青いチェックマークのついた「mariadb」を選択して「ダウンロード」ボタンを押して「latest」タグのイメージをダウンロードする。

- Redis
青いチェックマークのついた「redis」を選択して「ダウンロード」ボタンを押して「latest」タグのイメージをダウンロードする。

# 「コンテナ」タブでコンテナを作成する
先ほどダウンロードした Nextcloud、MariaDB、Redis のコンテナを作成します。
コンテナ名をこうします、と指示していますが、実際はなんでもよいです。

## MariaDBのコンテナを作成する
コンテナ > 作成 から画像名「mariadb:latest」を選んで次へ。
続いて「選択されたネットワークを使用」で「bridge」を選んで次へ進みます。

ここではコンテナ名を「Nextcloud_mariadb」に設定し、自動再起動を有効にします。
今回はここで「詳細設定」をクリックして「環境」タブで以下のパラメータを追加します。

| 設定名 | 設定値 | 
| ----- | ----- |
| MYSQL_DATABASE | nextcloud |
| MYSQL_USER | nextcloud |
| MYSQL_PASSWORD | 何らかのパスワードを設定（乱数とか） |
| MYSQL_ROOT_PASSWORD | 何らかのパスワードを設定（乱数とか） |

ローカルポートは自動のまま、コンテナのポートやタイプは変更せず、次へ進みます。
ボリュームの設定では、以下のフォルダーを追加します。

| ファイル／フォルダ | マウントパス | 読み取り専用 |
| ----- | ----- | ----- |
| /Nextcloud/mysql | /var/lib/mysql | オフ |

要約の画面で「ウィザード終了後、このコンテナを実行」のチェックはいれたまま「完了」をクリックします。
うまくいけば、ここで作成したコンテナが実行中になりますが、コンテナが予期せぬ終了からの再起動ループにはまった場合は
File Station で mysql フォルダーに Everyone の許可を与えたか確認してください。

## Redis のコンテナを作成する
コンテナ > 作成 から画像名「redis:latest」を選んで次へ。
続いて「選択されたネットワークを使用」で「bridge」を選んで次へ進みます。

ここではコンテナ名を「Nextcloud_redis」に設定し、やはり自動再起動を有効にします。
ポートの設定や、ボリュームの設定は何も触らなくても大丈夫です。
要約の画面で「ウィザード終了後、このコンテナを実行」のチェックはいれたまま「完了」をクリックします。

永続化の設定も含めて何もいじっていないので、問題なく起動するはずです。
起動しなかったらお陀仏です。何が悪いのかわかりません。

## Nextcloud のコンテナを作成する
コンテナ > 作成 から画像名「nextcloud:latest」を選んで次へ。
続いて「選択されたネットワークを使用」で「bridge」を選んで次へ進みます。

コンテナ名に「Nextcloud_app」と入力、自動再起動を有効にして
ここでも MariaDBのコンテナと同様に「詳細設定」をクリックし、続いて「リンク」のタブで「追加」を２回クリックし、出現した２行の設定を以下のように設定して「保存」をクリックして、続いて「次へ」をクリックしてください。

| コンテナ名 | エイリアス |
| ----- | ----- |
| Nextcloud_mariadb | db |
| Nextcloud_redis | redis |

ポート設定をする
ローカルポートに、最初のほうの手順でSynology DSMのリバースプロキシの設定をしたときの「送り先」に設定したポート番号を入力する。

ボリューム設定をする
永続化するフォルダーの指定を行って「次へ」をクリック。
「フォルダの追加」をクリックして、Nextcloud用に作成した共有フォルダの中から、以下のフォルダーを選んで、以下のように設定して次に進みます。

| ファイル／フォルダ | マウントパス | 読み取り専用 |
| ----- | ----- | ----- |
| /Nextcloud/config | /var/www/html/config | オフ |
| /Nextcloud/data | /var/www/data | オフ |
| /Nextcloud/custom_apps | /var/www/html/custom_apps | オフ |

**dataフォルダだけhtmlフォルダではなくてwwwフォルダの直下**なので、気を付けてください。

要約の画面で「ウィザード終了後、このコンテナを実行」のチェックはいれたまま「完了」をクリックします。

# Nextcloud の初期設定をする
ブラウザ(Google Chromeなど)で
https:// 証明書に記載のドメイン名:リバースプロキシのTargetポート/ でアクセスします。
ここでNASのIPアドレスでアクセスしてセットアップすると、セットアップ中に 400 Bad Request が発生します。

うまくいっていれば「管理者アカウントを作成してください」という画面が表示されますが
ここで「内部サーバーエラー」が出る場合は、File Station で Nextcloud 用に作成した共有フォルダ内の dataフォルダとconfigフォルダおよびcustom_appsフォルダにEveryoneのアクセス許可を与えたか確認してください。

うまくいった場合は、以下のように設定します。
**気を付けないとデータフォルダーが永続化されないとか、データベースがSQLiteで設定されてしまうので気を付けてください**。

「ストレージとデータベース▼」をクリックして設定項目を展開して以下のように設定します。

データフォルダーに /var/www/html/data と最初に入力されていますが、必ず **/var/www/data に変更**してください。

「データベースを設定してください」で「MySQL/MariaDB」を選択し

| 設定名 | 設定値 | 
| ----- | ----- |
| データベースのユーザー名 | nextcloud |
| データベースのパスワード | MariaDBのコンテナを作成する際に MYSQL_PASSWORD に入力したパスワード |
| データベース名 | nextcloud |
| データベースのホスト名 | localhostと最初書かれていますが、dbに変更 |

データベースのホスト名で設定している `db` とは、Nextcloud_app コンテナのリンクで設定した「エイリアス」の名前です。

これで「インストール」ボタンをクリックし、続いて「推奨アプリをインストール」にするか、表示されているアプリがいらなければ「キャンセル」をクリックします。

# Nextcloud コンテナの中への入り方
以下、セットアップ警告が出ないようにする手順のなかで、コンテナの中に入ってコマンドを入力する場面が何回か出てきますが
Synology の Docker では以下の２通りの方法があります。

## 方法1... Synology DSMの「Docker」で実行する方法
Dockerを起動して「コンテナ」のNextcloudが入ったコンテナ（この手順通りにやっていれば[Nextcloud_app]）をダブルクリック。
「端末」タブをクリック。

ここでなぜかコンテナが予期せず終了することがあります。
なぜかわかりません。

ここで少し待ってコンテナが再度立ち上がってきたぐらいのタイミングで
「作成」をクリックすると「bash」が出現するので、bashをクリック。
すると、コマンドが入力できる状態になります。

すべて終わったらbashを削除してかまいません。

## 方法2... Synology NASにSSH接続して実行する方法
Synology DSMのコントロールパネル > 端末とSNMP > SSHサービスを有効化するにチェックを入れて
TeraTermなどでここに表示されたポート番号にSSH接続し、DSMにログインするときのIDとパスワードでログインしてから

`sudo docker exec -it Nextcloud_app bash`
を入力すると、コンテナ内に入ることができます（-it オプションはコンテナ名を与えてください。大文字と小文字は区別します）
ここでの入力はコンテナ内での実行になります。
終わったらexitを入力して抜けます。

なお、occコマンドを実行する都合上、Apacheのユーザーで入りたい場合は
`sudo docker exec -u www-data -it Nextcloud_app bash`
とします。

# Nextcloud のセットアップ警告が出ないようにする
Nextcloud のダッシュボードで、右上のユーザー名の頭文字のアイコンをクリックしてから「設定」をクリックするとNextcloud の設定画面が開きます。
「管理」の「概要」をクリックすると、セキュリティ＆セットアップ警告が表示されます。
現行の最新バージョン 24.0.1 で上記のセットアップ方法でセットアップしたときに表示される警告については、以下の方法で解消できます。

## 「安全な接続でインスタンスにアクセスしていますが、インスタンスは安全でないURLを生成しています」
Synology NAS上に作成したNextcloud用共有フォルダーの中にある「config」フォルダの「config.php」を変更します。

設定ファイルのどこかに、以下を書きます。
`'overwriteprotocol' => 'https',`

どこかに、と書きましたが、同じような設定が並んでいるところのどこかにしてくださいね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673401/31f4e1ca-ddcc-de1f-b69b-2c2246f68f85.png)
たとえば先頭行とかではだめです。

これは、書いて保存してもすぐ反映されません。
何度かリロードしていると、そのうちでなくなります。

以下の電話地域の設定もあわせて設定しましょう。

## 「ご使用のシステムには、デフォルトの電話地域が設定されていません・・・」

Synology NAS上に作成したNextcloud用共有フォルダーの中にある「config」フォルダの「config.php」を変更します。

設定ファイルのどこかに、以下を書きます。
`'default_phone_region' => 'JP',`

例によって、この設定も書いて保存してもすぐ反映されません。
正しく上の設定が書いてあれば、そのうちでなくなります。

## 「Webサーバーで "./well-known/〇〇〇dav" が解決されるように正しく設定されていません」の解決方法
.htaccess を永続化して、それを使うようにします。
あんまりスマートではありませんが、現状この方法でしか解決できていません。

Synology NASにSSHログインして、以下のようにして.htaccessファイルをコピーします。
`sudo docker cp Nextcloud_app:/var/www/html/.htaccess /volume1/Nextcloud/htaccess/`
上は、Nextcloudのコンテナ名が Nectcloud_app で Synology NAS に作成した共有フォルダー名が Nextcloud の場合の例です。

このファイルのなかで、
```
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
```
と書かれている箇所を以下のように変更します。
```
RewriteRule ^\.well-known/carddav https://%{SERVER_NAME}:%{SERVER_PORT}/remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav https://%{SERVER_NAME}:%{SERVER_PORT}/remote.php/dav/ [R=301,L]
```

このあと、Nextcloud_app のDockerコンテナのボリュームの設定で、ファイルを追加し

| ファイル／フォルダ | マウントパス | 読み取り専用 |
| ----- | ----- | ----- |
| /Nextcloud/htaccess/.htaccess | /var/www/html/.htaccess | オフ |

この設定を追加します。読み取り専用はオンでもいいかもしれません。

とりあえずこれで解決しますが、Nextcloudをバージョンアップしようとするとき、一度この設定を削除しないとコンテナが予期せぬ終了ループにはまってしまいます。

また、今後のバージョンアップでオリジナルの .htaccess ファイルの内容が変更になるかもしれず
その場合は、そのオリジナルのファイルをコピーして、上記の箇所を再度変更するようにしないと、よからぬことが起こると思われます。
なので、このようなやりかたはやめたいのですが、今のところ良い方法が見つかっていません。

## 「メールサーバーの設定が未設定または未確認です・・・」
Nextcloudの個人 > 個人情報で自分のメールアドレスを設定したあとで、
Nextcloudの管理 > 基本設定でメールサーバーの設定を行い、**テストメールの送信まで実行**できれば、この警告は消えます。

Gmail あたりの設定をしておくとよいでしょう。
参考： https://support.google.com/mail/answer/7126229?hl=ja のステップ2
このとき、Google アカウントで二段階認証設定をしている場合は、アプリパスワードの生成が必要です。

## 「このインスタンスのphp-imagickモジュールはSVGをサポートしていません・・・」
コンテナに ImageMagick が入っていないために発生しています。
Nextcloud の公式イメージを使っているんだから、ソフトウェア関係は完ぺきな状態にしておいてくれよ、と愚痴りたくなるんですけど
コンテナの中で ImageMagick をインストールするコマンドを実行すれば解決します。

コンテナ内に入って、以下のコマンドを入力します。
```
apt update
apt install -y imagemagick
```

コンテナを削除して Nextcloud をバージョンアップすると、再びこのコマンドを実行する必要がでてきます。

# あれ？Redisはどうした？
そうですね。せっかくMariaDBのコンテナとRedisのコンテナを作ったのに、Redisを使っていませんね。
Nextcloudの昔のバージョン(15ぐらい?)では、Redisを構成するようにしないとセットアップ警告を完全にクリーンにすることはできませんでしたが、今はしなくてもオールグリーンになりますね。

まあでも、せっかくなので使うようにしてみます。
Synology NAS上に作成したNextcloud用共有フォルダーの中にある「config」フォルダの「config.php」を変更します。

この設定を追加します。

```
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' => 
array (
  'host' => 'redis',
  'port' => 6379,
),
```

host で設定している `redis` とは、Nextcloud_app コンテナのリンクで設定した「エイリアス」の名前です。

# この方法で作成した Nextcloud コンテナをバージョンアップするには
しばらくすると、Nextcloud へログインしたときに「Nextcloud バージョンxx.xx への更新があります」などの通知がでてくるようになります。
せっかく Docker を使っているので、Dockerイメージの更新で対応したいですね。

1. Nextcloud_app コンテナを停止
1. Nextcloud_mariadb コンテナ、Nextcloud_redis コンテナを停止
1. Synology NAS の「Nextcloud」共有フォルダーの中身全体をどこかにバックアップ（面倒ならせめてdataフォルダ以外だけでも）
1. そもそも data フォルダの中が空でないことを確認する（空である場合は、最初のセットアップ時にデータフォルダの永続化に失敗している）
1. Nextcloud_app コンテナを右クリック→設定→設定をコピーでコピーのインスタンスを作っておく（環境変数などの設定がなんだったかわからなくなったときのためのバックアップコピー）
1. Synology DSMの画面→Docker→レジストリの画面で「Nextcloud」を検索、ダブルクリックしてタグ「latest」をダウンロード
1. 通知画面に Docker イメージ %NAME% が正常にダウンロードされました。が表示されるまで待つ
1. 「コンテナ」画面で Nextcloud_app コンテナを削除
1. 「Nextcloud のコンテナを作成する」の手順で再びコンテナを作成する。ボリュームの永続化設定や、コンテナのリンク設定も忘れずに行う。このとき、.htaccessの永続化は行わないこと。
1. Nextcloud へウェブブラウザでアクセスしてアップグレードを実行
1. 正常終了したら、Nextcloud_app コンテナを一度停止して .htaccess の永続化を行う。
1. 再び開始する

## アップグレードが失敗する場合
データベースの容量がそれなりの大きさ以上である場合など、アップグレードをコマンドラインから実施する必要があるかもしれない。

「Nextcloud コンテナの中への入り方」の方法でコンテナの bash を起動してから `./occ upgrade` コマンドを手動実行する。
アップグレード後に、メンテナンスモードが勝手に解除されない場合は `./occ maintenance:mode --off` を実行してメンテナンスモードを解除する。

```
www-data@nextcloud_app:~/html$ ./occ upgrade
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
Setting log level to debug
Updating database schema
Updated database
Checking for update of app accessibility in appstore
Checked for update of app "accessibility" in App Store
Checking for update of app activity in appstore
：
：
：
Checking for update of app workflowengine in appstore
Checked for update of app "workflowengine" in App Store
Starting code integrity check...
Finished code integrity check
Update successful
Maintenance mode is kept active
Resetting log level
www-data@nextcloud_app:~/html$ ./occ maintenance:mode --off
Maintenance mode disabled
```

こういったことが過去一度でもあった場合、あるいは心配な場合は、アップグレード後のバージョンのコンテナを立ち上げて
ウェブブラウザーでアップグレード開始ボタンが表示されることを確認してから、上のようにコマンドラインで実行するとよいと思う。

## アップグレード後にセットアップ警告で「データベースにいくつかのインデックスがありません」と表示される場合
なんやかんやメジャーバージョンアップの後は毎回出ているような気がする。
これらはコマンドラインで実行する必要があるので「Nextcloud コンテナの中への入り方」の方法で　Nextcloud コンテナの bash を起動してから「〇〇を実行することによって」に書かれているコマンドを実行する。

例）occ db:add-missing-indices を実行することによって　と書かれている
`./occ db:add-missing-indices`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673401/0d8ebc2d-3047-498a-ed97-4e421f5ec470.png)

終わったら exit で抜ける。