NextcloudでiOSだけファイルアップロードのエラー 413 ファイルが大きすぎます

プライベートのストレージとして便利すぎるNextcloud(Dropbox, Onedriveのようなことができます)ですが、iOSアプリ特有?の問題に直面しました。

PCブラウザでは問題ない構成でも、iOSのNextcloudアプリではファイルサイズの大きい動画ファイルがアップロードできないエラーが発生しました。

公式ドキュメントを参考に対応できたのでメモを残します。ただし、根本原因までは特定できていません。

目次

1. Nextcloudの構成

  • サーバー1 フロント
    • NGINXのロードバランサ―(プロキシー)
    • Let’s EncryptのTLS証明書
  • サーバー2 バックエンド
    • docker composeでNextcloudとMySQLを起動しています
      • nextcloud:26.0.1 (apache, php-fpmを含むイメージ)
      • mysql:8.0.32

2. エラーの切り分け

リクエストはフロントのNGINX経由なので、直接Apacheがリクエストを処理しているわけではありません。そのため、まずNGINXとApacheのどちらがエラーを返しているか調べる必要があります。これは簡単でNextcloudにリクエストが届いていなければNGINX側の問題ということになります。

Nextcloudの管理画面では、次のようなログが出ているのでNextcloudまでは到達しているようです。これはiPhone上でリトライされる度に「413: ファイルサイズがおおきすぎます」が表示され、ログも記録されるので、まずはNextcloud側の問題として切り分けてもよさそうです。

# iPhone8 2GBを超える動画ファイル
Expected filesize of 2043863883 bytes but read (from Nextcloud client) and wrote (to Nextcloud storage) 0 bytes. Could either be a network problem on the sending side or a problem writing to the storage on the server side.

# iPhone12 9GBを超える動作ファイル
Expected filesize of 9216860555 bytes but read (from Nextcloud client) and wrote (to Nextcloud storage) 2091417600 bytes. Could either be a network problem on the sending side or a problem writing to the storage on the server side.

3. 公式ドキュメントの対策を確認

こちらのドキュメントを見るとデフォルトの最大サイズは512MBで、設定変更で制限解除できることが記載されています。PCで動作していることから、基本的には対策できているはずなのですが見直してみました。

No種類設定コメント
1PHPupload_max_filesizePHP_UPLOAD_LIMITで対応済み。phpinfo()でも確認済み。
2PHPpost_max_sizePHP_UPLOAD_LIMITで対応済み。phpinfo()でも確認済み。
3PHPmax_input_timeアップロード開始直後にエラーなので関係なさそう
4PHPmax_execution_timeアップロード開始直後にエラーなので関係なさそう
5ApacheLimitRequestBody公式ドキュメントによるデフォルトでは無制限のはず
https://httpd.apache.org/docs/2.4/ja/mod/core.html#limitrequestbody

Nextcloudイメージの設定はApacheのserver-infoで確認したところ設定値は無し。つまりデフォルト値ではないのかな?
6ApacheSSLRenegBufferSizeバックエンドはhttpなので関係なさそう
7ApacheTimeoutタイムアウトする前に413レスポンスがあるので関係なさそう。Apacheのserver-infoの値は300でした。
ファイルサイズが大きいファイルをアップロードするためのNextcloudの設定値見直し

4. 念のためフロントのNGINXも対策を確認

No種類設定コメント
1NGINXclient_max_body_size設定済み
2NGINXfastcgi_read_timeout[未設定] proxyなので関係なさそう
3NGINXclient_body_temp_path[未設定] PCアップロードで問題ないので関係なさそう
4NGINXproxy_bufferingoffに設定しても効果無し
5NGINXproxy_max_temp_file_size64000Mに設定しても効果無し
6NGINXX-Accel-Buffering[未設定] フロント側で対策可能なのでスルー
ファイルサイズが大きいファイルをアップロードするためのNGINXの設定値見直し

5. 結果

まずはフロントのNGINXで対策してみましが効果ありませんでした。次にApacheのLimitRequestBodyの設定を追加して対策をしてみたのですが、設定反映直後のiPhoneアプリのリトライからアップロードが成功しました。次の設定値を追加してDocker再起動でOKです。

# nextcloud.confを作成
LimitRequestBody 0

# docker-compose.ymlで設定ファイルをバインド
app:
  volumes:
    - type: bind
      source: ./services/app/etc/apache2/conf-enabled/nextcloud.conf
      target: /etc/apache2/conf-enabled/nextcloud.conf

公式イメージにはLimitRequestBodyの設定値はなかったのですが、デフォルト値0ではないのでしょうか?しかし、設定してすぐにエラーが解消したので挙動から見ると何かが違うようです。

その他、Nextcloudでチャンクサイズの調整などもあるようですが、LimitRequestBodyで問題解消したので試していません。

参考

githubのIssueなど見ると同様のエラーが発生して同じような対策をしているようですが、コメントにもあるように、サーバーサイドの問題として切り分けられているのでNextcloudの問題ではないということでクローズになっています。Dockerfile自前で作るほどでもなく、設定ファイル1つで対策できるので公式イメージに設定追加はなさそうです。