Коллега на работе пожаловался, что не может загрузить большой 100-гиговый файл на корпоративный Nextcloud. А я напомню, что рабочий сервер я обновлял и настраивал по этой статье:
https://typical-admin.ru/item/99-nextcloud-update-18-to-30
Чтобы можно было загружать такие большие файлы на Nextcloud, требуется изменить несколько конфигов. Начну с необязательного. В /var/www/html/nextcloud/config/config.php рекомендуется добавить вот такую строчку:
'max_chunk_size' => 104857600,
По умолчанию клиенты Nextcloud (и сам сервер) обычно и так используют чанки ~100 MiB, поэтому ручная установка в 100 MiB часто просто дублирует поведение по умолчанию. Но плюс явной установки в том, что гарантируется одинаковое поведение для всех клиентов (браузер, desktop, WebDAV) и предотвращаются ситуации, когда клиент решит отправлять слишком большие чанки (и тогда может сработать upload_max_filesize или post_max_size).
Далее будут уже обязательные изменения конфигов. В /etc/php/8.3/fpm/php.ini нужно поправить вот эти параметры:
max_execution_time = 43200
max_input_time = 43200
upload_max_filesize = 1024M
post_max_size = 1024M
Nextcloud НЕ грузит 100 ГБ одним файлом, он режет его на чанки (chunked upload). Поэтому нужно увеличить время на обработку загрузки. max_execution_time — параметр в PHP, который задаёт максимальное время в секундах, в течение которого скрипт должен полностью загрузиться. Если этого не происходит, работа скрипта завершается. max_input_time — директива в PHP, которая задаёт максимальное время в секундах, в течение которого скрипт должен разобрать все входные данные, переданные запросами вроде POST или GET. upload_max_filesize — директива в PHP, которая определяет максимальный размер загружаемых файлов на сервер. post_max_size — директива в PHP, которая устанавливает максимальный размер данных, отправленных методом POST, включая размер загружаемых файлов.
Далее пойдут настройки Apache под большие загрузки. Создаю для этого отдельный конфиг:
nano /etc/apache2/conf-available/nextcloud-large-upload.conf
Его содержимое будет таким:
Timeout 43200
ProxyTimeout 43200
LimitRequestBody 214748364800
RequestReadTimeout header=20-40,MinRate=500 body=3600,MinRate=500
Timeout — общий сетевой таймаут, который определяет, как долго Apache готов ждать завершения блокирующих операций сети там, где нет отдельных переопределений. ProxyTimeout — директива, которая настраивает время ожидания для прокси-запросов. Позволяет установить время, в течение которого сервер будет ждать ответа от бэкенд-сервера, к которому он проксирует запросы. LimitRequestBody позволяет задавать максимально допустимый размер тела клиентского запроса. В Apache 2.4.54+ по умолчанию стоит 1 GiB, что прерывает запросы файлов >1 GB. Нужно увеличить этот лимит, 214748364800 = 200 GiB. RequestReadTimeout — директива в Apache HTTP Server, которая устанавливает лимиты времени на чтение заголовков (headers) и тела (body) запроса. header=20-40,MinRate=500 — даёт 20 сек на начальное чтение заголовков, расширяет до 40 сек с учётом минимальной скорости передачи 500 B/s; это защищает от очень медленных/подозрительных клиентов. body=3600,MinRate=500 — на чтение тела даётся до 3600 с с минимальной скоростью передачи (MinRate) 500 bytes/sec; медленные соединения будут прерваны, но нормальные — пройдут.
Теперь нужно включить этот конфиг:
a2enconf nextcloud-large-upload
и перезапустить apache и php-fpm:
service php8.3-fpm restart
service apache2 restart
В целом, тут можно было бы и закончить. Но, в моём случае, загрузка таких больших файлов требуется очень редко, поэтому руководитель сказал, что будем включать эту возможность вручную по мере необходимости, а в остальное время настройки пускай остаются прежними. И, чтобы упростить процесс включения/отключения, я попросил у chatgpt скрипт для этого. Прикладываю этот скрипт сюда же:
https://disk.yandex.ru/d/duGEwspnTtRc4A
#!/usr/bin/env bash
# /usr/local/bin/gigafiles
#
# Скрипт переключает настройки PHP/Apache для поддержки редких загрузок очень больших файлов (≈100 ГБ).
# Usage:
# sudo gigafiles on - включить режим "под большие файлы"
# sudo gigafiles off - вернуть прежние значения
#
# Что делает:
# 1) Создаёт бэкап /etc/php/8.3/fpm/php.ini с меткой времени.
# 2) Заменяет или добавляет в php.ini четыре директивы:
# max_execution_time
# max_input_time
# upload_max_filesize
# post_max_size
# Значения зависят от аргумента on/off.
# 3) Перезагружает php-fpm (reload, при проблеме — restart).
# 4) Включает/выключает конфигурацию Apache /etc/apache2/conf-available/nextcloud-large-upload.conf
# через a2enconf / a2disconf.
# 5) Проверяет конфигурацию Apache (apachectl configtest) и, если проверка прошла,
# выполняет systemctl reload apache2. Если проверка упала — возвращает php.ini из бэкапа.
#
# Права: требуется root (run via sudo).
#
set -euo pipefail
# Путь к php.ini
PHPINI="/etc/php/8.3/fpm/php.ini"
# Имя конфигурации Apache (без .conf). Используется a2enconf/a2disconf.
APACHE_CONF_NAME="nextcloud-large-upload"
APACHE_CONF="/etc/apache2/conf-available/${APACHE_CONF_NAME}.conf"
# Имена systemd-сервисов, которые будем перезагружать
PHP_FPM_SERVICE="php8.3-fpm"
APACHE_SERVICE="apache2"
# Утилиты
APACHECTL="$(command -v apachectl || true)"
# Вспомогательные функции
# timestamp - генерация метки времени для бэкапов
timestamp() { date +"%Y%m%d-%H%M%S"; }
# die - печатает сообщение об ошибке и завершает работу
die() { echo "ERROR: $*" >&2; exit 1; }
# Проверка прав root
if [ "$(id -u)" -ne 0 ]; then
die "Этот скрипт должен запускаться от root (используйте sudo)."
fi
# Проверяем входной параметр
if [ $# -ne 1 ]; then
echo "Использование: $0 on|off"
exit 2
fi
ACTION="$1"
if [[ "$ACTION" != "on" && "$ACTION" != "off" ]]; then
die "Неверный аргумент: $ACTION. Используйте 'on' или 'off'."
fi
# Проверка наличия php.ini
if [ ! -f "$PHPINI" ]; then
die "php.ini не найден по пути $PHPINI"
fi
# Создаём бэкап php.ini с меткой времени.
BACKUP="${PHPINI}.bak.gigafiles.$(timestamp)"
cp -a "$PHPINI" "$BACKUP"
echo "Создан бэкап php.ini -> $BACKUP"
# Функция: заменить директиву в php.ini, либо добавить её в конец файла, если не найдена.
# Аргументы: ключ, значение
replace_or_append() {
local key="$1"
local value="$2"
# Если директива найдена (игнорируем регистр), заменяем всю строку.
# Поддерживаем формат: key = value
if grep -Ei "^\s*${key}\s*=" "$PHPINI" >/dev/null 2>&1; then
# sed: заменить первую найденную строку формата "key = anything" на "key = value".
sed -ri "s#^\s*(${key})\s*=.*#\1 = ${value}#I" "$PHPINI"
echo "Заменено: ${key} -> ${value}"
else
# Если директивы нет, просто добавляем в конец файла.
echo -e "\n; added by gigafiles\n${key} = ${value}" >> "$PHPINI"
echo "Добавлено: ${key} -> ${value}"
fi
}
# Устанавливаем новые значения в зависимости от режима on/off
if [ "$ACTION" = "on" ]; then
# Режим "включить большие файлы"
NEW_max_execution_time="43200" # 12 часов
NEW_max_input_time="43200" # 12 часов
NEW_upload_max_filesize="1024M" # 1 GiB (предел чанка)
NEW_post_max_size="1024M" # 1 GiB
else
# Режим "выключить — вернуть стандартные значения"
NEW_max_execution_time="60"
NEW_max_input_time="60"
NEW_upload_max_filesize="512M"
NEW_post_max_size="512M"
fi
# Вносим изменения в php.ini (с заменой или добавлением)
# Комментарии рядом с записями помогут понять, что добавил скрипт.
replace_or_append "max_execution_time" "$NEW_max_execution_time"
replace_or_append "max_input_time" "$NEW_max_input_time"
replace_or_append "upload_max_filesize" "$NEW_upload_max_filesize"
replace_or_append "post_max_size" "$NEW_post_max_size"
# Функция для отката php.ini в случае ошибки (восстановление из бэкапа)
rollback_phpini() {
if [ -f "$BACKUP" ]; then
cp -a "$BACKUP" "$PHPINI"
echo "php.ini восстановлен из бэкапа $BACKUP"
else
echo "Бэкап $BACKUP не найден — невозможно восстановить php.ini" >&2
fi
}
# Перезагрузка php-fpm:
# Попытка reload (без прерывания соединений), при неудаче — restart.
echo "Перезагрузка $PHP_FPM_SERVICE..."
if systemctl is-active --quiet "$PHP_FPM_SERVICE"; then
if systemctl reload "$PHP_FPM_SERVICE"; then
echo "$PHP_FPM_SERVICE успешно перезагружен (reload)."
else
echo "Reload не удался — пробую restart $PHP_FPM_SERVICE..."
systemctl restart "$PHP_FPM_SERVICE"
echo "$PHP_FPM_SERVICE успешно перезапущен (restart)."
fi
else
# Если сервис не активен, запустим его.
systemctl start "$PHP_FPM_SERVICE"
echo "$PHP_FPM_SERVICE запущен."
fi
# Включение/отключение Apache конфигурации
if [ "$ACTION" = "on" ]; then
if [ ! -f "$APACHE_CONF" ]; then
echo "Внимание: $APACHE_CONF не найден; пропускаю a2enconf (файл должен быть создан вручную)." >&2
else
echo "Включаем Apache конфигурацию: $APACHE_CONF_NAME"
a2enconf "$APACHE_CONF_NAME" >/dev/null || true
fi
else
if [ -f "$APACHE_CONF" ]; then
echo "Отключаем Apache конфигурацию: $APACHE_CONF_NAME"
a2disconf "$APACHE_CONF_NAME" >/dev/null || true
else
echo "Apache конфигурация $APACHE_CONF не найдена; ничего не делаю."
fi
fi
# Проверка конфигурации Apache и reload:
# Если apachectl отсутствует, предупредим, но попробуем reload (systemctl).
if [ -n "$APACHECTL" ]; then
echo "Тест конфигурации Apache..."
if apachectl configtest >/dev/null 2>&1; then
echo "apachectl configtest: OK"
echo "Reloading $APACHE_SERVICE..."
systemctl reload "$APACHE_SERVICE"
echo "$APACHE_SERVICE reloaded."
else
# Если проверка упала — откатываем php.ini и сообщаем пользователю.
echo "Ошибка: apachectl configtest не прошёл. Восстанавливаю php.ini из бэкапа и прекращаю."
rollback_phpini
# Старайтесь восстановить php-fpm состояние: reload чтобы вернуть прежние значения из бэкапа
systemctl reload "$PHP_FPM_SERVICE" || true
# Показываем тест для диагностики
echo "Вывод apachectl configtest для диагностики:"
apachectl configtest || true
die "apachectl configtest завершился с ошибкой — проверьте конфиги Apache."
fi
else
# Если apachectl не найден (маловероятно на Debian), используем systemctl reload и предупреждаем.
echo "Предупреждение: apachectl не найден. Попытка systemctl reload apache2..."
systemctl reload "$APACHE_SERVICE" || {
echo "systemctl reload apache2 не удался. Восстанавливаю php.ini из бэкапа."
rollback_phpini
systemctl reload "$PHP_FPM_SERVICE" || true
die "Не удалось перезагрузить Apache; проверьте конфигурацию вручную."
}
echo "Apache перезагружён через systemctl."
fi
echo "Готово. Текущий режим: $ACTION"
echo "php.ini бэкап: $BACKUP"
Инструкции:
Сохранить содержимое в /usr/local/bin/gigafiles.
Сделать исполняемым:
chmod +x /usr/local/bin/gigafiles.
Запускать из-под root:
Включить режим для больших файлов:
gigafiles on
Выключить:
gigafiles off
Что делает скрипт:
создаёт бэкап php.ini с временной меткой;
заменяет или добавляет четыре директивы в /etc/php/8.3/fpm/php.ini;
перезагружает php8.3-fpm;
включает/отключает конфигурацию Apache через a2enconf / a2disconf;
проверяет apachectl configtest и — если OK — перезагружает Apache. Если configtest падает, скрипт откатывает php.ini из бэкапа и прекращает (с сообщением об ошибке).
Безопасность/ограничения:
Скрипт предполагает, что файл /etc/apache2/conf-available/nextcloud-large-upload.conf корректен и готов к включению.
Скрипт сохраняет один бэкап при каждом запуске (с временной меткой).
Скрипт не правит другие файлы (pool.d/www.conf и т.п.).
В консоли отработка скрипта выглядит так:

Донаты принимаются на кошельки:
Yoomoney:
4100118091867315
Карта Т-Банк (бывший Тиньков):
2200 7017 2612 2077
Карта Альфа-Банк:
2200 1539 1357 2013