NextcloudをVPSで運用する方法 DockerとTLS
Docker Compose、Postgres、Redis、Let's Encrypt対応nginxでNextcloudをVPSに構築します。データディレクトリ、DB、設定を復元できるバックアップと、安全なアップグレード手順も解説します。
構築するシステムの内容
本ガイドでは、VPS 上で Docker Compose を使用して Nextcloud を実行し、Let's Encrypt による TLS 終端を前段に配置した上で、確実に復元可能なバックアップ環境を構築します。構成は、4 つのコンテナと 1 つのプロキシです。具体的には、ループバックで待機する公式の nextcloud イメージ、ファイルメタデータを保持する Postgres、ファイルロックを管理する Redis、cron ループのみを実行する Nextcloud イメージのコピー、そしてこれらすべての前段で TLS 終端を担うホスト上の nginx です。インストール自体は 20 分で完了しますが、重要なのはそこではありません。最初の 1 時間で行う 2 つの決定が、1 年後もファイルが手元に残っているかを左右します。それは、SQLite ではなく本格的なデータベースを採用すること、そしてデータディレクトリ、データベース、config.php を一貫したセットとして取得するバックアップを構築することです。
本ガイドは、Ubuntu 24.04 LTS または Debian 13 を使用し、Docker 公式リポジトリからインストールした Docker Engine (Compose v2 プラグインを含む) が導入されていることを前提とします。また、DNS の A レコード (IPv6 を利用する場合は AAAA も) が、すでに cloud.example.com を指して VPS に向いている必要があります。これらすべてには管理権限のあるサーバーが必要です。他社の SaaS 環境では、TLS 終端やデータベースのダンプを自前で制御することはできません。
メモリを実際に消費するもの
Nextcloud のメモリ使用量を大きく左右するのは 3 つです。いずれも、厳密な意味での「Nextcloud」そのものではありません。
PHP ワーカー。 -apache イメージは、PHP インタープリターを保持するワーカープロセスで、同時実行される各リクエストを処理します。各ワーカーは、PHP がリクエストを強制終了するまで PHP_MEMORY_LIMIT まで増加する可能性があります。最悪時の常駐メモリは、おおむね 同時実行リクエスト数 × メモリ制限 です。デスクトップの同期クライアントは、ユーザーごとに複数の接続を並列で開きます。上限を決めるのはユーザー数ではなく、同時実行数です。
データベース。 Postgres は接続ごとにバックエンドを fork し、共有バッファーを常駐させます。ワーキングセットはバイト数ではなく、ファイル数 に応じて増加します。oc_filecache には、ユーザーごとにファイル 1 つあたり 1 行が格納されます。小さなファイルが 100,000 個あるデータベースは、大きなファイルが 100 個あるデータベースより負荷が高くなります。
プレビュー生成。 サムネイルの生成では、元画像をフル解像度でメモリに展開します。動画のプレビューでは ffmpeg を外部コマンドとして実行します。occ preview:generate-all を実行すると、このメモリ使用量の急増が連続して繰り返されるため、小規模な VPS を OOM killer の対象にする最も一般的な原因になります。
Redis のメモリ使用量は比較的少なくて済みます。後から追加する Collabora、全文検索、ウイルス対策スキャナーなどは、それぞれ固有のメモリ使用量を持つ別の常駐サービスです。有効化する前に、サイジング計画へ含めてください。
RAM に余裕がない場合の調整項目は次のとおりです。PHP_MEMORY_LIMIT を下げ、preview_max_x / preview_max_y / preview_max_filesize_image に上限を設定し、実際に閲覧する形式だけに enabledPreviewProviders を絞り込みます。また、データディレクトリがファイル容量の数倍まで気付かないうちに増加しないよう、trashbin_retention_obligation と versions_retention_obligation を設定します。swap ファイルも追加してください。swap は低速であり、アップグレード中に OOM kill が発生するよりはましです。
SQLite が破綻する理由
Nextcloud は SQLite をサポートしており、公式イメージも問題なく SQLite を使用します。しかし、SQLite は使用しないでください。SQLite はデータベース全体のロックによって書き込みを直列化します。1 回に書き込めるのは 1 つの処理だけで、対象はファイル全体です。Nextcloud では、ファイルロック、アクティビティの行、キャッシュエントリ、ジョブの状態などが常に書き込まれます。さらに、1 台のデスクトップクライアントがディレクトリツリーを同期すると、多数のリクエストが並列に発生します。この条件では SQLSTATE[HY000]: General error: 5 database is locked と HTTP 500 が発生し、インスタンスが実用になり始めたまさにその時点で障害が表面化します。
後から occ db:convert-type で変換することは可能ですが、稼働中のデータセットに対する長時間の一括移行になります。移行を途中で分割することもできません。最初から Postgres または MariaDB を使用してください。
Compose ファイル
これを /srv/nextcloud/compose.yaml に配置し、Secret はモード 600 の別ファイル .env に保存します。
services:
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db:/var/lib/postgresql/data
environment:
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
app:
image: nextcloud:35-apache
restart: unless-stopped
depends_on: [db, redis]
ports:
- "127.0.0.1:8080:80"
volumes:
- html:/var/www/html
- /srv/nextcloud/data:/var/www/html/data
environment:
POSTGRES_HOST: db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: ${ADMIN_PASSWORD}
NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com
TRUSTED_PROXIES: 172.16.0.0/12
OVERWRITEPROTOCOL: https
OVERWRITECLIURL: https://cloud.example.com
APACHE_DISABLE_REWRITE_IP: "1"
PHP_MEMORY_LIMIT: 512M
PHP_UPLOAD_LIMIT: 10G
cron:
image: nextcloud:35-apache
restart: unless-stopped
entrypoint: /cron.sh
depends_on: [db, redis]
volumes:
- html:/var/www/html
- /srv/nextcloud/data:/var/www/html/data
volumes:
db:
html:メジャータグを固定し、35 をそのままコピーする前に Docker Hub で現在のタグを確認してください。2026 年 10 月 21 日時点で、Nextcloud は 33、34、35 を保守しています。バージョン 31 は 2026 年 2 月に、32 は 2026 年 9 月にサポート終了となりました。そのため、古いガイドからコピーしたタグでは、修正が提供されないリリースがインストールされます。latest を指定すると、将来のある docker compose pull でメジャーバージョンの境界をまたいで更新されます。Nextcloud はこの更新方法をサポートしていません。
データディレクトリには、意図的に名前付きボリュームではなく bind mount を使用します。バックアップツールから直接指定できるパスのほうが、構成の整然さより重要だからです。イメージの www-data UID と、Nextcloud が要求する権限で作成します。
sudo mkdir -p /srv/nextcloud/data
sudo chown -R 33:33 /srv/nextcloud/data
sudo chmod 0770 /srv/nextcloud/dataポート公開の設定 127.0.0.1:8080:80 に注意してください。Docker は DNAT ルールを書き込みます。このルールは、パケットが ufw の INPUT チェーンに到達する前に評価されます。そのため、単純な 8080:80 では、ufw の設定に関係なく暗号化されていない Nextcloud がパブリックインターネットに公開されます。loopback にバインドすれば、パブリックインターフェースから切り離せます。これにより、ファイアウォールで許可するのはプロキシだけで済みます。SSH をインターネット全体に公開したくない場合は、自己ホスト型 WireGuard VPN 経由で VPS に接続することで、パブリックルールからポート 22 を完全に削除できます。
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enabledocker compose up -d で起動し、続いて docker compose logs -f app を監視します。初回起動時は、アプリケーションツリー全体をボリュームにコピーしてインストーラーを実行します。この処理が完了するまで、コンテナは応答しません。
TLS とリバースプロキシ
ディストリビューションのパッケージから nginx と certbot をインストールし、適切な server_name を指定した単純な port-80 の server block を作成してから、certbot に書き換えさせます。HTTP-01 チャレンジの仕組み、更新タイマー、失敗するケースについては、Ubuntu 24.04 で certbot と nginx を使って Let's Encrypt 証明書を発行するで詳しく説明しています。
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d cloud.example.comCertbot は ssl_certificate の行と :80 → :443 のリダイレクトを追加し、90-day 証明書を更新する systemd timer をインストールします。systemctl list-timers | grep certbot で timer が存在することを確認してください。有効化されていない更新 timer は、90-day の時限爆弾です。
プロキシ block 自体は次のとおりです。
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name cloud.example.com;
# certbot manages ssl_certificate / ssl_certificate_key here
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
client_max_body_size 10G;
client_body_timeout 300s;
location = /.well-known/carddav { return 301 /remote.php/dav; }
location = /.well-known/caldav { return 301 /remote.php/dav; }
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}nginx 1.25.1 以降では http2 on; を追加します。この directive は 1.25.0 には存在しないため、nginx はこれを検出すると起動しません。Ubuntu 24.04 には古い build が含まれており、同等の設定は listen 443 ssl http2; です。nginx -t を実行すると、使用中の build がどちらを受け付けるか確認できます。
client_max_body_size が小さすぎると、nginx は大きな upload を 413 で即座に拒否します。read timeout が短すぎると、upload は途中で失敗します。上記の値により、これらの問題を防げます。proxy_request_buffering off はファイル全体を先にプロキシのディスクへ保存せず、upload をそのまま転送します。
ホスト上で nginx を動かす方法は、1 つのアプリに対して最も簡単に動作する構成です。Nextcloud を他のコンテナと同じ VPS で運用する場合は、複数のアプリ向けに Traefik を Docker Compose のリバースプロキシとして実行することで、ルーティングと証明書発行をコンテナ label に移せます。その場合も、同じ client_max_body_size と timeout に関する注意点が middleware と transport の設定として再び現れます。
trusted_proxies と overwriteprotocol
ここで、多くの self-hosted Nextcloud インスタンスが誤設定されます。症状は原因と無関係に見えます。
X-Forwarded-Proto: https は、リクエストが trusted_proxies に記載されたアドレスから到着した場合にだけ適用されます。適用されない場合、Nextcloud はリクエストを通常の HTTP と判断し、http:// URL を生成します。プロキシはそれらを HTTPS にリダイレクトします。ブラウザーがそのリダイレクトに従うと、Nextcloud は再び http:// を生成します。これがリダイレクトループです。OVERWRITEPROTOCOL: https を指定すると、リクエスト元に関係なくスキームを固定できます。
TRUSTED_PROXIES で注意が必要なのは、Nextcloud が認識するアドレスが 127.0.0.1 ではない ことです。nginx はホスト上で動作し、公開ポートに接続します。そのため、コンテナーからは Docker ブリッジのゲートウェイ、つまり 172.x 内のアドレスが送信元として見えます。実際のサブネットを確認します。
docker network inspect nextcloud_default \
-f '{{range .IPAM.Config}}{{.Subnet}}{{end}}'その CIDR、またはそれを包含する 172.16.0.0/12 を TRUSTED_PROXIES に設定します。範囲を広くしすぎると、任意のクライアントが X-Forwarded-For を偽装できます。誤った値を設定すると、すべてのログインがゲートウェイアドレスからのアクセスとして記録されます。その結果、ブルートフォース対策がインスタンス全体を一度にブロックし、管理画面には 「リバースプロキシのヘッダー設定が正しくないか、信頼されたプロキシから Nextcloud にアクセスしています。」 と表示されます。
OVERWRITECLIURL は cron コンテナーで重要です。このコンテナーには、ホスト名を推測できる受信リクエストがないためです。設定しないと、バックグラウンドジョブが localhost へのリンクを生成し、メール通知に使用できない URL が含まれます。
バックグラウンドジョブ: AJAX ではなく cron
Nextcloud のデフォルトのジョブ実行方式は AJAX です。誰かがページを読み込んだときの副作用としてジョブが実行されます。04:00 に誰もブラウズしないと、ゴミ箱の期限切れ処理、バージョンのクリーンアップ、プレビュー生成、フェデレーションの再試行が滞ります。最初に現れる症状は、データディレクトリが増え続けることです。上記の cron サービスは、同じボリュームに対して公式の /cron.sh ループを実行します。Nextcloud にこの方式を使用するよう指示します。
docker compose exec -u www-data app php occ background:cronすべての occ コマンドは、docker compose exec -u www-data app php occ <command> という形式に従います。エイリアスを設定しておくと便利です。
バックアップ: 3 つすべて、または何もなし
ファイルシステムだけのバックアップでは、壊れたインスタンスしか復元できません。データディレクトリにはバイト列が保存されます。Postgres にはファイルキャッシュ、共有、ユーザー、アプリケーションの状態が保存されます。config.php にはデータベースの認証情報、インスタンス ID、パスワードソルトが保存されます。データベースなしでファイルを復元すると、Nextcloud はそれらを認識できません。config.php なしでデータベースを復元すると、データベースを開けません。古いデータベースを新しいデータディレクトリに対して復元すると、移動済みのファイルを指す共有が作成されます。
停止状態にしたインスタンスから、3 つすべてをバックアップします。
#!/usr/bin/env bash
set -euo pipefail
cd /srv/nextcloud
DEST="/var/backups/nextcloud/$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$DEST"
occ() { docker compose exec -T -u www-data app php occ "$@"; }
occ maintenance:mode --on
trap 'occ maintenance:mode --off' EXIT
docker compose exec -T db \
pg_dump -U nextcloud --clean --if-exists nextcloud | gzip > "$DEST/db.sql.gz"
docker compose exec -T app \
tar -C /var/www/html -cf - config custom_apps themes > "$DEST/app.tar"
rsync -a --delete /srv/nextcloud/data/ /var/backups/nextcloud/data/メンテナンスモードにすることで、ダンプとファイルコピーの内容が一致します。これを省略すると、rsync がまだコピーしていないファイルを参照するデータベースを、いずれ取得することになります。スクリプトはタイムスタンプ付きのデータベースダンプを保持しますが、データディレクトリのローリングミラーは 1 つだけです。rsync --delete は実行のたびにこのミラーを上書きするため、ファイルコピーと組み合わせられるのは最新のダンプだけです。
次に、バックアップをサーバーの外部へ移します。バックアップ対象と同じ VPS に保存されたバックアップは、バックアップではなくコピーです。通常は、オブジェクトストレージまたは 2 台目のホストに対して restic を使用します。重複排除により、毎晩作成する tarball よりもデータディレクトリを効率よく扱えます。リポジトリの初期化から、夜間タイマー、復元訓練までの完全な構成は、restic を使った VPS の外部バックアップにまとめています。
復元は、単純に逆の手順を行えばよいわけではありません。起動直後のスタックはインストーラーを実行し、新しい config.php、新しいインスタンス ID、パスワードソルトを書き込みます。その新しい ID の上にダンプをインポートすると、セッションと共有トークンが壊れた状態になります。最初に古い ID を、次の順序で戻します。
docker compose up -d && docker compose stop app cron # create the volumes, then halt the app
sudo rsync -a --delete /var/backups/nextcloud/data/ /srv/nextcloud/data/
docker compose run --rm -T --entrypoint "" app \
tar -C /var/www/html -xf - < app.tar # the original config.php returns
gunzip -c db.sql.gz | docker compose exec -T db psql -U nextcloud -d nextcloud
docker compose start app cron
docker compose exec -T -u www-data app php occ maintenance:mode --off
docker compose exec -T -u www-data app php occ files:scan --allfiles:scan は、ファイルキャッシュと実際にディスク上に存在する内容を整合させます。必要になる前に、予備の VPS で一度この手順をリハーサルしてください。ディスク上のバイト列と Postgres 内のメタデータを分けて扱う点は、この構成の他のすべてのアプリにも共通します。そのため、ライブラリは取得してもデータベースを取得しない Immich のバックアップでは、空のタイムラインに復元されます。
アップグレードは一度に 1 つのメジャーバージョンだけ進める
Nextcloud は、一度に 1 つのメジャーバージョンだけアップグレードできます。公式の Docker イメージでは、29 から 31 へ直接移行してもアップグレード処理は実行されません。entrypoint は occ upgrade を実行する前にメジャーバージョンを比較し、Can't start Nextcloud because upgrading from <installed version> to <image version> is not supported. に続けて It is only possible to upgrade one major version at a time. を出力して終了します。コンテナは起動を拒否します(restart: unless-stopped の場合は再起動を繰り返し、同じ行を出力し続けます)。メンテナンスモードは有効にならず、データとデータベースも変更されません。タグを次のメジャーバージョンに変更して、もう一度起動してください。
Docker でのアップグレード手順は、バックアップを取得し、app サービスと cron サービスの両方でタグを 1 つ先のメジャーバージョンに変更し(36 がリリースされる予定の 2027 年 2 月以降は 35 から 36 へ変更)、次に docker compose pull && docker compose up -d を実行し、その後 docker compose logs -f app を実行することです。イメージの entrypoint は、既存のデータに対してコードが新しいことを検出し、occ upgrade を自動的に実行します。処理を中断しないでください。ログの出力が止まったら、docker compose exec -u www-data app php occ status を実行し、versionstring とアプリが有効な状態に戻っていることを確認します。
トラブルを防ぐルールは 2 つあります。1 つのメジャーバージョンだけ上げて確認し、その後に次のバージョンへ進めてください。また、app サービスのタグだけを変更せず、必ず cron も同じバージョンに変更してください。1 つのデータベースに対して異なる Nextcloud バージョンを使用すると、データ破損につながります。
実際に表示されるエラー
「データディレクトリを他のユーザーが読み取れます。ディレクトリを他のユーザーが一覧表示できないように、権限を 0770 に変更してください。」 ディレクトリの mode の最後の桁、つまり他のユーザーに対する桁が 0 ではありません。他のユーザーに read、write、execute のいずれかのビットが設定されていると、このエラーが発生します。0770 自体でグループに完全なアクセス権が与えられるため、グループのビットは確認されません。Nextcloud は最初に chmod 0770 を自動的に試行し、それが失敗した場合にのみ警告します。bind mount でこの操作が失敗する場合、通常はディレクトリの所有者が UID 33 ではないことを意味します。sudo chown -R 33:33 /srv/nextcloud/data と sudo chmod 0770 /srv/nextcloud/data を確認してください。
「データディレクトリが無効です。データディレクトリのルートに ".ncdata" というファイルがあることを確認してください。」 bind mount の接続先が、Nextcloud によって初期化されたことのない場所です。パスの誤記や、稼働中のインスタンスで使用しているディレクトリが空の新しいディレクトリに置き換わった可能性もあります。ホスト側のパスが volume の行と一致していることを確認してください。
「信頼されていないドメイン経由のアクセスです。」 リクエストの hostname が trusted_domains に含まれていません。NEXTCLOUD_TRUSTED_DOMAINS が適用されるのは初回インストール時だけです。その後は次のコマンドで実行中の設定を変更します: occ config:system:set trusted_domains 1 --value=cloud.example.com
502 Bad Gateway が表示され、/var/log/nginx/error.log に connect() failed (111: Connection refused) while connecting to upstream が記録されている場合、nginx は 127.0.0.1:8080 で待ち受けているプロセスに接続できていません。コンテナの初期化中である可能性があります(docker compose logs app を確認してください)。コンテナが終了した可能性もあります(docker compose ps)。または、publish の行が proxy_pass ポートと一致していません。ss -ltnp | grep 8080 で確認してください。
リダイレクトループが発生する場合、または管理画面の概要に「安全ではない」という警告が表示される場合。 OVERWRITEPROTOCOL: https が設定されていないか、TRUSTED_PROXIES に Docker gateway のサブネットが含まれていません。前述のプロキシのセクションを参照してください。
LockedException: "files/..." is locked。 REDIS_HOST を設定すると、イメージは Redis をロックのバックエンドとして構成するため、古いロックが残ることはほとんどありません。設定しない場合、ロックはデータベーステーブル oc_file_locks に保存され、書き込み途中でリクエストが強制終了すると行が残ります。手作業でロックの行を削除する前に、Redis が実際に使用されていることを確認してください。occ config:system:get memcache.locking が Redis のクラスを返すことを確認します。
「PHP memory limit が推奨値の 512 MB を下回っています。」 PHP_MEMORY_LIMIT を引き上げて、コンテナを再作成してください。この設定が最悪時の上限に与える影響を忘れないでください。
規模拡大時に問題になる点
最初の壁は、データディレクトリがボリュームの容量を超えることです。VPS でボリュームを拡張するには、ボリュームの resize とファイルシステムの grow が必要です。容量が 100% に達してからではなく、余裕があるうちに計画的に実施すると、作業の負担を大幅に減らせます。ディスク使用量のアラートは、今すぐ設定してください。
2 つ目の壁は oc_filecache です。ファイル一覧の取得や同期スキャンは、行数が増えるほど遅くなります。対策にはデータベースの調整が必要です。Postgres は高速なストレージに置き、十分な shared memory を使用できるようにします。ゴミ箱とバージョンは retention 設定で削除し、永続的に蓄積させないでください。
3 つ目は、プレビュー生成が他の処理とリソースを奪い合うことです。小規模なサーバーでは、プレビュー provider の対象を絞り、作業時間中に occ preview:generate-all を実行しないでください。保存データの大半がスマートフォンのカメラロールなら、サムネイル生成は専用の photo server に任せるべきです。RAM、スマートフォンアプリ、バックアップコマンドの観点から PhotoPrism と Immich を比較では、Nextcloud 用のサーバーと併用した場合に必要なリソースを説明しています。
これ以上の追加機能については、別のマシンを用意するのが現実的です。Collabora と full-text search は、それぞれ独自のメモリ使用特性を持つ常駐サービスです。唯一のファイルコピーも保存しているサーバーに配置すると、メリットがないまま障害範囲が広がります。ブラウザー上のドキュメント編集が必要なら、OnlyOffice と Collabora を分ける vendor の RAM 最低要件と接続数制限によって、2 から 4 GB の VPS でどちらを実行できるかが決まります。ボリュームが用途に合わなくなったら、ファイルストレージを S3-compatible の primary storage に移します。ただし、これでバックアップが簡単になるわけではありません。データベースにはメタデータが残るため、bucket と同じタイミングで dump する必要があります。
インスタンスが実際のユーザーにサービスを提供するようになったら、Uptime Kuma を前段に配置し、sync client より先にダウンタイムを検知できるようにします。private cloud は 自分で運用する mail server と相性がよく、サービスの連携を手作業で設定したくない場合は、Cloudron、CasaOS、Coolify が自動化を担う各プラットフォームを比較しています。次に self-hosted search engine を導入する場合は、これまでとは異なる種類の問題に備えてください。SearXNG の 429 エラー は、SearXNG 自身の rate limiter、または upstream engine による VPS の IP アドレスのブロックが原因です。どちらなのかはログでしか判断できません。
FAQ
SQLite を Postgres の代わりに Nextcloud で使用できますか?
使用できます。公式イメージも SQLite を許可します。ただし、単一のデスクトップ同期クライアントが並列リクエストを送るだけで、SQLSTATE[HY000]: General error: 5 database is locked と HTTP 500 エラーが発生します。SQLite はデータベース全体の書き込みロックを取得します。Nextcloud はファイルロック、アクティビティ行、ジョブ状態などを継続的に書き込むためです。Postgres または MariaDB で開始してください。occ db:convert-type は存在しますが、稼働中のデータに対する長時間の一括移行になります。
Nextcloud VPS には実際にどれだけの RAM が必要ですか?
ユーザー数ではなく、同時実行数を基準にサイジングします。最悪時の常駐メモリは、おおむね同時リクエスト数に PHP_MEMORY_LIMIT を掛けた量に加え、Postgres の共有バッファー、接続ごとのバックエンド 1 つ、さらにプレビュー生成で一時的に増加する分です。2 GB のサーバーでも、プレビュー生成を制限して swap を追加すれば、小規模な家庭内インスタンスを実行できます。Collabora や全文検索を追加する場合は、常駐サービス一式をもう 1 組分、見積もる必要があります。
nginx リバースプロキシの背後で大きなアップロードが失敗するのはなぜですか?
通常は、プロキシの 2 つの設定が原因です。client_max_body_size をデフォルトの 1 MB のままにすると、nginx はそれを超えるリクエストを 413(Request Entity Too Large)で即座に拒否します。このエラーは部分ファイルではなく、nginx のエラーログに記録されます。短い proxy_read_timeout / proxy_send_timeout の値では、長時間の転送が途中で終了します。両方に余裕のある値を設定し、proxy_request_buffering off を有効にして一時保存ではなくストリーミング転送にし、アプリコンテナの PHP_UPLOAD_LIMIT も同じ値に引き上げてください。
Nextcloud がリダイレクトループになる、またはリバースプロキシについて警告するのはなぜですか?
コンテナからは nginx が 127.0.0.1 にあるようには見えません。Docker ブリッジのゲートウェイが 172.x のどこかにあるように見えます。そのアドレスが TRUSTED_PROXIES に含まれていない場合、X-Forwarded-Proto: https ヘッダーは無視されます。Nextcloud は http:// URL を生成し、プロキシがそれらを再び転送するため、ループが発生します。実際のブリッジサブネットを TRUSTED_PROXIES に設定し、OVERWRITEPROTOCOL: https を固定してください。
Nextcloud を 29 から 31 に直接アップグレードできますか?
できません。Nextcloud は、1 回のアップグレードで 1 つのメジャーバージョンだけをサポートします。公式 Docker イメージでは、entrypoint が occ upgrade の実行前にメジャーバージョンを確認します。It is only possible to upgrade one major version at a time. を出力して終了するため、コンテナは起動せず、データとデータベースはそのまま残ります。まずタグを 30 に設定してください。バックアップを取得し、app と cron の両サービスでタグを 1 メジャーバージョン分だけ更新し、docker compose pull && docker compose up -d を実行して、occ status で確認します。その後、同じ手順を繰り返してください。