Docker内のNextcloudへNginxからリバースプロキシする

## やりたいこと
nginxをサーバ上に直接立てている。いつも使うのはこっち。
もしサブディレクトリに/nextcloud/が指定されたら、サーバにdockerで立てているnextcloudに振り分け（リバースプロキシし）たい。
類似の環境構築をしている人を探したけど、一方のみがdockerのパターンが少なかったり、途中で困った点が合ったので自分の設定も晒す。

```mermaid
stateDiagram-v2
  client --> nginx
  nginx --> nextcloud: locationが/nextcloud/で始まる
  nginx --> nginx内のサイト: locationが/nextcloud/で始まらない
```

~~多分、行儀は良くない。~~

## 設定ファイル一覧
いじったファイル一覧を示す。大部分は省略してる。
ドメイン名（example.com）やポート番号（65536）は適宜すること。

### compose.yaml

```yaml:compose.yaml
volumes:
  nextcloud:
  db:

services:
  db:
    image: mariadb
    restart: always
    volumes:
      - ./db-data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${ENV_MYSQL_ROOT_PASSWORD}  # .envファイルに環境変数を設定
      - MYSQL_PASSWORD=${ENV_MYSQL_PASSWORD}  # .envファイルに環境変数を設定
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - PHP_MEMORY_LIMIT=2048M
      - PHP_UPLOAD_LIMIT=10240M

  app:
    image: nextcloud
    restart: always
    volumes:
      - ./nextcloud-data:/var/www/html
    ports:
      - 65536:80
    links:
      - db
```

基本的にはs_Pure様の「[NextcloudをDockerで構築する手順](https://qiita.com/s_Pure/items/48d3823837e647b57091)」と同じ。
`PHP_MEMORY_LIMIT`と`PHP_UPLOAD_LIMIT`を追加させていただいた。

### nextcloud-data/config/config.php

```php:config.php
$CONFIG = array (
  ...
  'overwriteprotocol' => 'https',
  'overwritehost' => 'example.com',
  'overwritewebroot' => '/nextcloud',
  'overwrite.cli.url' => 'https://example.com/nextcloud',
  'trusted_domains' => 
  array (
    0 => 'localhost:65536',
  ),
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'mysql',
  ...
```

overwriteから始まる4行が重要。nextcloudがリンクとして返すURLのプロトコル、ホスト名、ルートディレクトリを強制的に書き換えるというもの。これによりURLの先頭に/nextcloudが付き続けるため、リバースプロキシがうまく動く。

### nginx.conf

```conf:nginx.conf
...
http {
    ...
    # HTTPS server
    #
    server {
        server_name example.com;
        root   /var/www/html/;

        listen 443 ssl;

        location ~ /nextcloud/ {
            rewrite /nextcloud(.*) $1 break;
            proxy_pass http://localhost:65536;
            client_max_body_size 10G;
            proxy_connect_timeout 1800;
            proxy_send_timeout 1800;
            proxy_read_timeout 1800;
            send_timeout 1800;
        }

        location / {
            index  index.html index.htm index.php;
        }
        ...
```

`rewrite`と`proxy_pass`の2行で、サブディレクトリ`/nextcloud/`以降のURLをnextcloudに転送している。
アップロード/ダウンロード中にセッションが切れないよう、timeout系も変更している。

## 途中で困ったこと

### Docker composeをdown→up すると502エラーが発生する

composeファイルにて、`/var/lib/mysql`をvolumes永続化しないとMySQLに登録されたデータが毎度毎度消えるため。

### 「不明なエラー」によってファイルがアップデートできない

`client_max_body_size`を変更しないとアップロードできるサイズが上限1MB(?)のため。
一度にアップロードできるファイルサイズをこれで設定する。

### ログインできずループする

ブラウザのコンソールを見ると「because it violates the following Content Security Policy directive: "form-action 'self'"」って表示される。
CSPと呼ばれるセキュリティ機能によって、ログイン時の転送が禁止されている。クロスサイトスクリプティング辺りの対策らしい。
エラーにかかれてある通り、nginxのconfigに`form-action 'self'`を登録したが効果なく。
設定ファイルを書き直すといつの間にか治ったので、詳細な原因と解決策は不明。

### 

## 参考にしたサイト
* @s_Pure 様　[Qiita | NextcloudをDockerで構築する手順](https://qiita.com/s_Pure/items/48d3823837e647b57091)
* virtuliment 様 [Nextcloudのsnap版をNginxのリバースプロキシとサブディレクトリ構成で使う](https://virment.com/setup-nextcloud-behind-nginx-reverse-proxy/)
* @noblin_1031 様 [Qiita | Nginx リバースプロキシ基本設定](https://qiita.com/noblin_1031/items/ba7ef5dd06b1519deb5e)
* @hidao 様 [Qiita | nextCloudとcloud9をdockerで導入し、NginXでリバースプロキシをかけてサブディレクトリで切り替える](https://qiita.com/hidao/items/51b42054430dc7550649)
* 楽介 様 [Fun For Productivity | Nextcloud でバックアップなど大量のデータを扱う注意点](https://ict-worker.com/web_cloud/nextcloud-backup-large-data.html)
* sys323様 [Zenn | nginxでリバースプロキシ](https://zenn.dev/sey323/scraps/eee29d8b822d34)
* [Nextcloud公式ディスカッション掲示板 | Content-Security-Policy issue](https://help.nextcloud.com/t/content-security-policy-issue/192491)