SSD Nodes Learn Hosting plans →
Посібники Matt ConnorВід Matt Connor

Nextcloud на VPS: Docker, TLS і резервні копії

Запустіть Nextcloud на VPS через Docker Compose: Postgres, Redis і nginx з TLS від Let's Encrypt, а також узгоджені резервні копії для відновлення даних.

Що саме ви створюєте

Цей посібник описує запуск Nextcloud на VPS за допомогою Docker Compose, налаштування TLS від Let's Encrypt перед ним і створення резервної копії, яку можна відновити. Схема складається з чотирьох контейнерів і reverse proxy: офіційний образ nextcloud слухає loopback, Postgres зберігає всі дані про метадані файлів, Redis зберігає блокування файлів, другий контейнер з образом Nextcloud виконує лише цикл cron, а nginx на хості завершує TLS перед усіма цими компонентами. Саме встановлення займає двадцять хвилин і не є найважливішою частиною. Два рішення, прийняті протягом першої години, визначають, чи матимете ви доступ до своїх файлів через рік: використання повноцінної бази даних замість SQLite та резервної копії, яка зберігає каталог даних, базу даних і config.php як один узгоджений набір.

Передбачається, що ви використовуєте Ubuntu 24.04 LTS або Debian 13, Docker Engine із плагіном Compose v2, встановленим із власного репозиторію Docker, а також DNS-запис типу A (і AAAA, якщо у вас є IPv6), який уже вказує cloud.example.com на VPS. Для цього потрібен сервер, яким ви керуєте. Неможливо виконати TLS termination і дамп бази даних у чужому SaaS.

Sizing: що насправді споживає пам’ять

Використання пам’яті Nextcloud визначають три основні компоненти. Жоден із них не є власне «Nextcloud».

PHP workers. Образ -apache обробляє кожен паралельний запит окремим worker process, який містить PHP interpreter. Кожен worker може використати до PHP_MEMORY_LIMIT, після чого PHP завершить запит. Орієнтовний worst-case обсяг resident memory дорівнює добутку кількості паралельних запитів на ліміт пам’яті. Desktop sync client відкриває кілька паралельних з’єднань для кожного користувача. Верхню межу визначає concurrency, а не кількість користувачів.

Database. Postgres створює окремий backend для кожного з’єднання та зберігає shared buffers у пам’яті. Його working set залежить від кількості файлів, а не від кількості байтів: oc_filecache містить один рядок для кожного файлу кожного користувача. Сто тисяч малих файлів створюють більше навантаження на database, ніж сто великих файлів.

Preview generation. Під час створення thumbnail вихідне зображення декодується в пам’ять у повній роздільній здатності. Для відеопрев’ю використовуються зовнішні виклики до ffmpeg. Запуск occ preview:generate-all повторює цей пік навантаження один за одним і є найпоширенішим способом довести невеликий VPS до спрацювання OOM killer.

Redis порівняно мало споживає пам’яті. Усе, що ви додасте пізніше, зокрема Collabora, full-text search або antivirus scanner, є окремим resident service із власним обсягом пам’яті. Його потрібно врахувати в плані sizing до ввімкнення.

Якщо RAM мало, змініть такі параметри: зменште PHP_MEMORY_LIMIT, обмежте preview_max_x / preview_max_y / preview_max_filesize_image, скоротіть enabledPreviewProviders до форматів, які ви фактично переглядаєте, і налаштуйте trashbin_retention_obligation та versions_retention_obligation, щоб data directory непомітно не зростав у кілька разів порівняно з розміром файлів. Додайте swap file. Swap працює повільно, але завершення процесу через OOM killer під час оновлення має гірші наслідки.

Чому SQLite створює проблеми

Nextcloud підтримує SQLite, і офіційний image без проблем використовуватиме його. Не використовуйте SQLite. SQLite серіалізує операції запису за допомогою блокування всієї бази даних: одночасно може виконуватися лише один запис для всього файлу. Nextcloud постійно виконує записи: блокування файлів, записи про активність, елементи кешу та стан завдань. Один desktop client, який синхронізує дерево каталогів, надсилає багато паралельних запитів. За такого навантаження ви отримуєте SQLSTATE[HY000]: General error: 5 database is locked і HTTP 500, а збій виникає саме тоді, коли instance починає приносити користь.

Пізніше можна виконати конвертацію за допомогою occ db:convert-type, але це тривала міграція «все або нічого» для активного набору даних. Одразу використовуйте Postgres або MariaDB.

Файл Compose

Розмістіть це у /srv/nextcloud/compose.yaml, а секрети зберігайте в сусідньому файлі .env з режимом доступу 600.

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:

Зафіксуйте major tag і перевірте актуальний tag на Docker Hub, перш ніж дослівно копіювати 35. Станом на 21 October 2026 Nextcloud підтримує версії 33, 34 і 35. Для версії 31 підтримку припинено в February 2026, а для 32 — у September 2026, тому tag зі старого посібника встановить release, який більше не отримує виправлень. latest автоматично переведе вас через межу major version під час одного з майбутніх docker compose pull, а Nextcloud цього не підтримує.

Каталог даних навмисно підключено як bind mount, а не як named volume: можливість безпосередньо вказати цей шлях інструменту резервного копіювання важливіша за акуратність. Створіть його з UID образу www-data і правами доступу, яких вимагає 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, які обробляються ще до того, як пакет потрапляє в ланцюжок INPUT ufw. Простий 8080:80 відкриває незашифрований Nextcloud у публічному інтернеті незалежно від налаштувань ufw. Прив’язка до loopback не дає доступу через публічний інтерфейс. Тоді firewall має дозволити доступ лише proxy. Якщо ви не хочете залишати SSH відкритим для всього інтернету, доступ до VPS через self-hosted WireGuard VPN дає змогу повністю вилучити порт 22 із публічних правил:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Запустіть його за допомогою docker compose up -d, а потім відстежуйте docker compose logs -f app. Під час першого запуску весь application tree копіюється у volume і запускається installer. Поки цей процес не завершиться, контейнер не відповідає на запити.

TLS і reverse proxy

Встановіть nginx і certbot із репозиторію дистрибутива, створіть звичайний server block для порту 80 із правильним server_name, а потім дозвольте certbot переписати його. Механізм HTTP-01 challenge, timer поновлення та сценарії помилок докладно описано в отриманні сертифікатів Let's Encrypt за допомогою certbot і nginx в Ubuntu 24.04:

sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d cloud.example.com

Certbot додає рядки ssl_certificate і редирект :80 → :443, а також встановлює systemd timer для поновлення 90-денного сертифіката. Перевірте його наявність за допомогою systemctl list-timers | grep certbot. Timer поновлення, який ніколи не вмикали, — це 90-денний зворотний відлік до відмови.

Сам proxy 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;. У 1.25.0 цієї директиви немає, і nginx не запуститься, якщо її побачить. В Ubuntu 24.04 постачається старіша збірка, де еквівалентом є listen 443 ssl http2;. nginx -t покаже, який варіант підтримує ваша збірка.

Якщо client_max_body_size має замале значення, nginx одразу відхилить великий upload із помилкою 413. Якщо тайм-аути читання надто короткі, upload перерветься посередині. Наведені вище значення запобігають обом проблемам. proxy_request_buffering off передає upload потоком, не зберігаючи спочатку весь файл на диску proxy.

nginx на хості — найпростіший варіант для одного застосунку. Якщо Nextcloud працюватиме на одному VPS з іншими контейнерами, запуск Traefik як reverse proxy в Docker Compose для кількох застосунків перенесе маршрутизацію та видачу сертифікатів у labels контейнерів. Ті самі питання щодо client_max_body_size і тайм-аутів виникнуть знову, але вже у вигляді middleware та параметрів transport.

trusted_proxies і overwriteprotocol

Саме тут найчастіше виникають помилки в self-hosted інсталяціях Nextcloud. Їхні симптоми часто не пов’язані на перший погляд із причиною.

X-Forwarded-Proto: https враховується лише тоді, коли запит надходить з адреси, зазначеної в trusted_proxies. Якщо ця умова не виконується, Nextcloud вважає запит звичайним HTTP і формує URL-адреси http://. Проксі перенаправляє їх на HTTPS, браузер переходить за перенаправленням, а Nextcloud знову формує http://. Так виникає цикл перенаправлень. OVERWRITEPROTOCOL: https примусово задає схему незалежно від цього.

Проблема з TRUSTED_PROXIES полягає в тому, що адреса, яку бачить Nextcloud, — це не 127.0.0.1. nginx працює на хості та підключається до опублікованого порту, тому контейнер бачить шлюз Docker bridge, тобто адресу з 172.x. Визначте фактичну підмережу:

docker network inspect nextcloud_default \
  -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}'

Додайте цей CIDR або мережу, що охоплює 172.16.0.0/12, до TRUSTED_PROXIES. Якщо вказати надто широку мережу, будь-який клієнт зможе підробити X-Forwarded-For. Якщо вказати неправильну мережу, усі входи виглядатимуть так, наче вони надходять із адреси шлюзу. Захист від brute-force одночасно заблокує весь інстанс, а в огляді адміністратора з’явиться повідомлення "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy."

OVERWRITECLIURL потрібен для cron-контейнера, який не отримує вхідного запиту, щоб визначити ім’я хоста. Без цього фонові завдання формують посилання на localhost, а email-сповіщення містять непридатні URL-адреси.

Фонові завдання: cron, а не AJAX

Стандартний засіб запуску завдань 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>. Варто створити для неї alias.

Резервні копії: три компоненти або жодного

Резервна копія лише файлової системи відновлює зламаний інстанс. Каталог даних містить байти; Postgres зберігає файловий кеш, спільні ресурси, користувачів і стан застосунку; config.php містить облікові дані бази даних, ID інстансу та сіль пароля. Якщо відновити файли без бази даних, Nextcloud не зможе їх побачити. Якщо відновити базу даних без config.php, вона не зможе відкрити базу даних. Якщо відновити стару базу даних у новіший каталог даних, ви отримаєте спільні ресурси, що вказують на файли, які вже переміщено.

Створюйте резервні копії всіх трьох компонентів, попередньо перевівши інстанс у стан спокою:

#!/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 ще не встиг звернутися. Зверніть увагу: скрипт зберігає дампи бази даних із часовими мітками, але створює лише одне дзеркало каталогу даних, rsync --delete перезаписує його під час кожного запуску, тому з копією файлів узгоджується лише найновіший дамп.

Потім перенесіть резервну копію за межі сервера. Резервна копія, що зберігається на тому самому VPS, що й дані, які вона захищає, є копією, а не резервною копією. restic для object storage або другого хоста є стандартним рішенням, а дедуплікація значно краще обробляє каталог даних, ніж щоденний tarball. Повний опис налаштування, від ініціалізації репозиторію до нічного таймера та перевірки відновлення, наведено в матеріалі резервні копії VPS за межами сервера за допомогою restic.

Відновлення не є простим виконанням цих кроків у зворотному порядку. Щойно запущений стек виконує інсталятор і записує абсолютно новий config.php, новий 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 --all

files:scan узгоджує файловий кеш із фактичним станом диска. Відпрацюйте цю процедуру один раз на резервному VPS, перш ніж вона стане потрібною. Такий самий поділ між байтами на диску та метаданими в Postgres визначає роботу всіх інших застосунків цієї структури. Саме тому резервна копія Immich, що містить бібліотеку, але не базу даних, відновлює порожню часову шкалу.

Оновлення: лише одна основна версія за раз

Nextcloud підтримує оновлення рівно на одну основну версію за раз. В офіційному Docker image перехід з 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 він продовжує перезапускатися та виводити ті самі рядки), режим обслуговування не вмикається, а дані й база даних залишаються без змін. Установіть tag на наступну основну версію та запустіть контейнер знову.

Оновлення Docker виконується так: створіть резервну копію, змініть tag на одну основну версію вище в обох сервісах app і cron (з 35 на 36, коли вийде 36, що Nextcloud планує на February 2027), потім виконайте docker compose pull && docker compose up -d, а після цього docker compose logs -f app. Entrypoint image виявляє новіший код у поєднанні з наявними даними та сам запускає occ upgrade. Не переривайте цей процес. Коли журнали перестануть змінюватися, виконайте docker compose exec -u www-data app php occ status і перевірте versionstring, а також переконайтеся, що застосунки знову ввімкнені.

Запам’ятайте два правила: оновлюйте одну основну версію, перевіряйте результат, потім переходьте до наступної. Ніколи не змінюйте tag у сервісі app без відповідної зміни cron. Дві різні версії Nextcloud, підключені до однієї бази даних, можуть спричинити пошкодження даних.

Помилки, які ви побачите на практиці

"Your data directory is readable by other people. Please change the permissions to 0770 so that the directory cannot be listed by other people." Остання цифра режиму доступу до каталогу, яка відповідає іншим користувачам, не дорівнює нулю. Будь-який дозвіл на читання, запис або виконання для інших користувачів спричиняє цю помилку. Права групи не перевіряються, оскільки сам режим 0770 надає групі повний доступ. Спочатку Nextcloud самостійно виконує chmod 0770 і лише потім показує попередження, якщо команда завершується невдало. Для bind mount це зазвичай означає, що каталог не належить UID 33. sudo chown -R 33:33 /srv/nextcloud/data і sudo chmod 0770 /srv/nextcloud/data.

"Your data directory is invalid. Ensure there is a file called ".ncdata" in the root of the data directory." Bind mount вказує на каталог, який Nextcloud ніколи не ініціалізував, у шляху є помилка або замість робочого каталогу підключено новий порожній каталог. Перевірте, що шлях на хості відповідає рядку volume.

"Access through untrusted domain." Ім’я хоста в запиті відсутнє у trusted_domains. NEXTCLOUD_TRUSTED_DOMAINS застосовується лише під час першого встановлення. Після цього змініть значення безпосередньо в запущеній системі: occ config:system:set trusted_domains 1 --value=cloud.example.com.

502 Bad Gateway, із connect() failed (111: Connection refused) while connecting to upstream у /var/log/nginx/error.log. nginx не отримав відповіді на 127.0.0.1:8080. Контейнер ще ініціалізується (перевірте docker compose logs app), завершив роботу (docker compose ps) або рядок publish не відповідає порту proxy_pass. Підтвердьте це за допомогою ss -ltnp | grep 8080.

Цикл перенаправлень або попередження "insecure" в огляді адміністратора. Відсутній OVERWRITEPROTOCOL: https або TRUSTED_PROXIES не містить підмережу Docker gateway. Див. наведений вище розділ про проксі.

LockedException: "files/..." is locked. Якщо задано REDIS_HOST, образ налаштовує Redis як бекенд блокувань, тому застарілі блокування виникають рідко. Без цього блокування зберігаються в таблиці бази даних oc_file_locks, а примусове завершення запиту під час запису залишає в ній рядки. Перед ручним видаленням рядків блокувань переконайтеся, що Redis справді використовується: occ config:system:get memcache.locking має повернути клас Redis.

"The PHP memory limit is below the recommended value of 512 MB." Збільште PHP_MEMORY_LIMIT і повторно створіть контейнер. Пам’ятайте, як це впливає на граничне значення у найгіршому випадку.

Що ламається під навантаженням

Перша проблема виникає, коли каталог даних стає більшим за том. Збільшення тому на VPS — це зміна його розміру та розширення файлової системи. Виконати це планово значно простіше, ніж після заповнення тому на 100%. Налаштуйте сповіщення про використання диска вже зараз, а не пізніше.

Друга проблема — oc_filecache. Переліки файлів і сканування під час синхронізації сповільнюються зі зростанням кількості записів. Виправлення потребує роботи з базою даних: розмістіть Postgres на швидкому сховищі, виділіть йому достатній обсяг shared memory і видаляйте кошик та старі версії за допомогою параметрів зберігання, а не дозволяйте їм накопичуватися без обмежень.

Третя проблема — конкуренція генерації попередніх переглядів за ресурси з іншими процесами. На невеликому сервері обмежте кількість preview providers і ніколи не запускайте occ preview:generate-all у робочі години. Якщо більшість даних становлять фотографії з камери телефона, генерацію мініатюр краще виконувати на спеціалізованому photo server. У матеріалі Порівняння PhotoPrism та Immich за використанням RAM, телефонними застосунками й командами резервного копіювання описано, скільки ресурсів кожен із них потребує поруч із Nextcloud.

Після цього чесна відповідь така: додатковим компонентам потрібна окрема машина. Collabora і повнотекстовий пошук — це окремі резидентні сервіси з власними профілями використання пам’яті. Якщо розмістити їх на сервері, де також зберігається єдина копія файлів, без жодної користі збільшується домен відмови. Якщо потрібне редагування документів у браузері, саме мінімальні вимоги постачальників до RAM і обмеження кількості підключень, які відрізняють OnlyOffice від Collabora визначають, чи зможе VPS із 2 до 4 GB запустити відповідний сервіс. Переносьте файлове сховище до основного S3-compatible сховища, коли том перестає відповідати вашим потребам. Врахуйте, що це ускладнює резервне копіювання, а не спрощує його: база даних і далі містить метадані, тому її потрібно дампити синхронно з bucket.

Коли instance почне обслуговувати реальних користувачів, встановіть Uptime Kuma перед ним, щоб дізнаватися про простої раніше, ніж про них повідомлять клієнти синхронізації. Приватна cloud-система добре поєднується з власним mail server, а якщо ви не хочете з’єднувати сервіси вручну, у матеріалі Cloudron, CasaOS та Coolify порівнюються платформи, які роблять це за вас. Якщо наступним у списку буде self-hosted search engine, очікуйте проблем іншого класу: помилки 429 у SearXNG виникають або через його власний обмежувач швидкості, або через блокування вашої IP-адреси VPS upstream engines. Визначити причину можна лише за журналом.

FAQ

Чи можна запускати Nextcloud на SQLite замість Postgres?

Так, це можливо, і офіційний образ це дозволяє. Але один клієнт синхронізації на робочому столі, який надсилає паралельні запити, спричинятиме SQLSTATE[HY000]: General error: 5 database is locked і помилки HTTP 500. SQLite блокує запис на рівні всієї бази даних, а Nextcloud постійно виконує записи: блокування файлів, рядки активності та стан завдань. Почніть із Postgres або MariaDB; occ db:convert-type існує, але це тривала міграція в режимі «все або нічого» для робочих даних.

Скільки RAM насправді потрібно Nextcloud VPS?

Розраховуйте обсяг за кількістю паралельних запитів, а не користувачів. Піковий обсяг resident memory приблизно дорівнює кількості паралельних запитів, помноженій на PHP_MEMORY_LIMIT, плюс shared buffers Postgres і по одному backend-процесу на кожне з’єднання, а також пам’ять, до якої може зрости споживання під час генерації preview. Сервер із 2 GB RAM підходить для невеликого домашнього екземпляра, якщо обмежити генерацію preview і додати swap. Якщо додати Collabora або повнотекстовий пошук, потрібно додатково виділити ресурси для окремого набору resident-сервісів.

Чому великі завантаження не проходять через reverse proxy nginx?

Зазвичай це пояснюють два налаштування на proxy. Якщо client_max_body_size залишити зі значенням за замовчуванням 1 MB, nginx одразу відхиляє більший запит із помилкою 413 (Request Entity Too Large). Така помилка з’являється в error log nginx, а не у вигляді частково завантаженого файла. Малі значення proxy_read_timeout / proxy_send_timeout переривають тривалі передавання даних посередині. Задайте обидва параметри з достатнім запасом, увімкніть proxy_request_buffering off для потокового передавання замість збереження у spool і збільште PHP_UPLOAD_LIMIT у контейнері застосунку до відповідного значення.

Чому Nextcloud зациклює редирект або попереджає про reverse proxy?

Контейнер бачить не nginx за адресою 127.0.0.1, а gateway Docker bridge, десь у діапазоні 172.x. Якщо цю адресу не додати до TRUSTED_PROXIES, заголовок X-Forwarded-Proto: https ігнорується, Nextcloud формує URL із http://, а proxy перенаправляє їх назад. Задайте TRUSTED_PROXIES для фактичної підмережі bridge і зафіксуйте OVERWRITEPROTOCOL: https.

Чи можна оновити Nextcloud безпосередньо з 29 до 31?

Ні. Nextcloud підтримує оновлення лише на одну major version за раз. В офіційному Docker image entrypoint перевіряє major versions перед запуском occ upgrade, виводить It is only possible to upgrade one major version at a time. і завершує роботу. Тому контейнер не запускається, а дані та база даних залишаються без змін. Спочатку змініть tag на 30: створіть резервну копію, збільште tag на одну major version в обох сервісах app і cron, виконайте docker compose pull && docker compose up -d, перевірте результат за допомогою occ status, а потім повторіть процедуру.