Установка Nextcloud на собственном сервере

Опубликовано 13 мин. чтения

От пустого сервера до страницы обзора без предупреждений: веб-сервер, модули PHP, база данных, права на каталог данных, trusted_domains, лимиты загрузки и фоновые задания через cron.

Распаковать Nextcloud недолго. Время съедает то, что начинается потом: на свежей установке страница обзора в разделе Параметры администрирования практически всегда показывает целый список жёлтых и красных предупреждений, загрузка файлов обрывается на 2 МБ, а обращение по IP-адресу заканчивается сообщением «You are accessing the site from an untrusted domain.». В этой статье путь пройден целиком, с остановками ровно в тех местах, на которых большинство руководств заканчивается.

Что решить заранее: версия PHP, база данных, каталог для файлов

Nextcloud привязан к версии PHP жёстче, чем большинство другого серверного софта. Актуальные ветки 33 и 34 требуют минимум PHP 8.2, ветка 32 работает начиная с PHP 8.1. Поэтому именно дистрибутив решает, хватит ли вам штатных пакетов:

СистемаPHP из дистрибутиваБаза данных из дистрибутиваОценка
Debian 13 (trixie)8.4MariaDB 11.8подходит без сторонних репозиториев
Debian 12 (bookworm)8.2MariaDB 10.11подходит, но по нижней границе
Ubuntu 24.04 LTS8.3MariaDB 10.11, MySQL 8.0подходит без сторонних репозиториев
Ubuntu 22.04 LTS8.1MariaDB 10.6, MySQL 8.0слишком стар для Nextcloud 33 и 34
Debian 11 (bullseye)7.4MariaDB 10.5не подходит вовсе

Debian 11 — самый тяжёлый случай, и замечают его обычно поздно, потому что установка пакетов проходит без единой ошибки. Метапакет php тянет там PHP 7.4, и актуальная версия Nextcloud при первом же открытии в браузере отдаёт HTTP 500 с сообщением «This version of Nextcloud requires at least PHP 8.2». Обычная поддержка Debian 11 к тому же уже закончилась, для новой установки это неподходящая основа. Если другого выхода нет, подключите заранее репозиторий Sury и ставьте пакеты с явным указанием версии, то есть php8.2-fpm, php8.2-cli, php8.2-mysql и так далее, вместо неверсионированных метапакетов.

На Ubuntu 22.04 вы точно так же упрётесь в стену, как только поставите актуальную версию Nextcloud. Либо вы сознательно остаётесь на ветке 32, либо берёте PHP из известного PPA:

sudo apt-get install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt-get update
sudo apt-get install -y php8.3-fpm php8.3-cli php8.3-mysql

Ещё два момента, которые определяются в самом начале, а позже меняются с большим трудом. Debian принципиально не поставляет пакет mysql-server, там по умолчанию MariaDB. И каталог данных должен лежать не в /var/www/nextcloud/data, а за пределами корневого каталога веб-сервера, например в /var/nextcloud-data. Стандартный путь опасен ровно тем, что при сломанной конфигурации веб-сервера наружу отдаются все пользовательские файлы. Nextcloud в этом случае предупреждает строкой «Your data directory and files are probably accessible from the internet», но только после того, как ошибка уже допущена.

Настройка веб-сервера, PHP и базы данных

Мы берём nginx с PHP-FPM. Если вам ближе Apache с mod_php, путь описан в статье Apache, PHP и MySQL на Debian, всё сказанное про PHP ниже остаётся в силе. Базовая установка nginx разобрана в статье установка nginx.

sudo apt-get update
sudo apt-get install -y nginx mariadb-server
sudo apt-get install -y php-fpm php-cli php-mysql php-gd php-curl php-mbstring php-intl php-gmp php-bcmath php-xml php-zip php-imagick php-apcu

Список намеренно длиннее необходимого минимума. bcmath и gmp нужны Nextcloud для входа без пароля, intl для правильной сортировки букв с диакритикой и спецсимволов, imagick для эскизов, apcu для локального кэша. Если не хватает одного из обязательных модулей, мастер установки просто не пустит вас дальше, а страница перечислит недостающие модули поимённо.

После этого проверьте, что действительно загружено:

php -v
php -m

Вторая частая ловушка: конфигураций PHP две, отдельная для командной строки и отдельная для FPM. php --ini показывает вам файл командной строки, а конфигурация веб-сервера лежит в /etc/php/<version>/fpm/php.ini. Правки в неправильном файле не дают никакого эффекта, и по опыту именно на это уходит больше всего времени.

Теперь база данных. Сначала защитите MariaDB, об этом статья защита MariaDB и MySQL, затем:

sudo mariadb -e "CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
sudo mariadb -e "CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'ЗдесьДлинныйПароль';"
sudo mariadb -e "GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost';"
sudo mariadb -e "FLUSH PRIVILEGES;"

utf8mb4 в первой команде — не мелочь. Если создать базу с utf8, Nextcloud позже сообщит «MySQL is used as database but does not support 4-byte characters», а переделывать кодировку на работающей системе заметно неприятнее, чем один раз написать правильный CREATE DATABASE. Если вход пользователя базы данных не проходит, поможет статья как устранить Access denied for user.

Распаковка и права доступа

sudo apt-get install -y wget unzip
wget https://download.nextcloud.com/server/releases/latest.zip
sudo unzip -q latest.zip -d /var/www
sudo mkdir -p /var/nextcloud-data
sudo chown -R www-data:www-data /var/www/nextcloud
sudo chown -R www-data:www-data /var/nextcloud-data
sudo chmod 750 /var/nextcloud-data

Права доступа — то место, где халтурят чаще всего. Три типичные ошибки и их причины:

  • «Cannot write into config directory»: каталог /var/www/nextcloud/config принадлежит не пользователю веб-сервера. На Debian и Ubuntu это www-data, а на AlmaLinux и Rocky apache или nginx. Вслепую скопированная команда chown www-data в семействе Red Hat не даёт ничего.
  • «Can't create or write into the data directory»: путь не существует, указан не абсолютным, либо в один из вышестоящих каталогов пользователю www-data нельзя зайти.
  • «Your data directory is readable by other users»: права слишком широкие. Достаточно выполнить chmod 750 для каталога данных.

Не поддавайтесь искушению решить вопрос командой chmod -R 777. Nextcloud ответит на это ровно тем предупреждением, от которого вы хотели избавиться, а заодно каждый файл станет читаемым для любого локального пользователя.

Конфигурация nginx

Nextcloud нужен не просто стандартный блок для PHP, а ещё и правила перезаписи для обнаружения служб в /.well-known/ и запреты на внутренние каталоги. Ниже сокращённый вариант официального шаблона, он работает как есть:

upstream php-handler {
    server unix:/run/php/php8.3-fpm.sock;
}

server {
    listen 80;
    server_name cloud.example.com;
    root /var/www/nextcloud;

    client_max_body_size 10G;
    client_body_timeout 300s;
    fastcgi_buffers 64 4K;

    add_header Referrer-Policy "no-referrer" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Permitted-Cross-Domain-Policies "none" always;
    add_header X-Robots-Tag "noindex, nofollow" always;

    index index.php index.html /index.php$request_uri;

    location ^~ /.well-known {
        location = /.well-known/carddav { return 301 /remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /remote.php/dav/; }
        location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
        return 301 /index.php$request_uri;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }

    location ~ \.php(?:$|/) {
        rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+) /index.php$request_uri;
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;
        try_files $fastcgi_script_name =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_request_buffering off;
        fastcgi_max_temp_file_size 0;
    }

    location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|map|woff2)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;
        access_log off;
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}

Путь к сокету FPM нужно привести в соответствие с вашей версией PHP. На Debian 13 он называется php8.4-fpm.sock, на Debian 12 php8.2-fpm.sock, на Ubuntu 24.04 php8.3-fpm.sock, на Ubuntu 22.04 php8.1-fpm.sock. Если имя не совпадает, вы получите 502 Bad Gateway. Настоящее имя покажет:

systemctl enable --now php8.4-fpm
ls /run/php/

Первая строка здесь не лишняя: файл сокета появляется только при запуске службы. До этого каталог /run/php/ либо пуст, либо не существует вовсе, и ls отвечает No such file or directory. На обычном сервере пакет запускает службу сам при установке, но после переустановки системы или внутри контейнера это не гарантировано. Номер версии в имени службы приведите к своей установке. После этого nginx -t и перезагрузка конфигурации.

Установка, HTTPS и trusted_domains

Установку можно пройти кликами в браузере или сразу выполнить в командной строке. Второй вариант воспроизводим и легко укладывается в скрипт:

cd /var/www/nextcloud
sudo -u www-data php occ maintenance:install --database "mysql" --database-name "nextcloud" --database-user "nextcloud" --database-pass "ЗдесьДлинныйПароль" --admin-user "admin" --admin-pass "ДругойДлинныйПароль" --data-dir "/var/nextcloud-data"

Здесь две ловушки. Во-первых, команду нужно запускать из каталога Nextcloud, иначе PHP завершится с Fatal Error. Во-вторых, occ нельзя запускать от root, иначе появится «Console has to be executed with the user that owns the file config/config.php», а в худшем случае свежесозданные файлы окажутся во владении не того пользователя.

Теперь HTTPS. Без сертификата мобильные приложения работать откажутся, а Nextcloud выведет предупреждение на странице обзора:

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

Если поддоменов несколько, имеет смысл wildcard-сертификат. После этого добавьте в блок сервера с TLS заголовок Strict-Transport-Security "max-age=15552000; includeSubDomains" always;, иначе предупреждение «The Strict-Transport-Security HTTP header is not configured to at least 15552000 seconds» так и останется.

И классика напоследок: вы открываете сайт под другим именем, чем при установке, и видите только «You are accessing the site from an untrusted domain.» Nextcloud принимает исключительно те имена узлов, которые перечислены в trusted_domains. Добавить имя, не правя файл вручную:

sudo -u www-data php occ config:system:set trusted_domains 1 --value=cloud.example.com
sudo -u www-data php occ config:system:get trusted_domains

Индекс начинается с 0, и нулевой обычно уже занят. Если выдать один и тот же индекс дважды, существующая запись будет перезаписана, и при неудачном стечении обстоятельств вы закроете доступ самому себе. Если это случилось: config/config.php — обычный PHP-файл, запись правится там в любом редакторе. Дополнительно задайте overwrite.cli.url с окончательным HTTPS-адресом, иначе фоновые задания будут формировать ссылки с неверным именем узла.

Размер загружаемых файлов и лимит памяти

Настройки PHP по умолчанию для Nextcloud слишком тесные. upload_max_filesize обычно стоит на 2M, memory_limit на 128M. Nextcloud рекомендует минимум 512M памяти и иначе предупреждает строкой «The PHP memory limit is below the recommended value of 512MB».

Мест здесь три, и поправить одно из них недостаточно:

  1. Конфигурация FPM в /etc/php/<version>/fpm/php.ini: memory_limit = 512M, upload_max_filesize = 10G, post_max_size = 10G, max_execution_time = 3600. После этого перезапустите FPM, перезагрузки конфигурации nginx недостаточно.
  2. Файл .user.ini в каталоге Nextcloud: Nextcloud приносит собственные значения, и, поскольку .user.ini действует на уровне каталога, он перебивает глобальный php.ini. Именно на этом регулярно спотыкается поиск причины. Значения нужно поправить и там. PHP кэширует этот файл, по умолчанию пять минут, так что изменение срабатывает с задержкой.
  3. Директива nginx client_max_body_size: если её нет или значение слишком мало, загрузка обрывается с «413 Request Entity Too Large» ещё до того, как дело дойдёт до PHP.

Чтобы проверить, что получилось в итоге, откройте страницу Параметры администрирования: там указан фактически действующий верхний предел. В командной строке:

grep -E '^(memory_limit|upload_max_filesize|post_max_size)' /etc/php/8.4/fpm/php.ini

Спрашивайте именно файл FPM, а не командную строку. Команда php -r "echo ini_get('memory_limit');" читает SAPI командной строки, и на всех проверенных дистрибутивах она возвращает -1, то есть без ограничения. Кто на это положится, сочтёт значение достаточным и всё равно упрётся позже в ошибки памяти, потому что в файле FPM по-прежнему стоит memory_limit = 128M. Что реально доходит до браузера, показывает php-fpm8.4 -i или временно созданный info.php с phpinfo(), который сразу после проверки нужно удалить.

Если при загрузке больших файлов процесс убивает ядро, значит попросту не хватает оперативной памяти. В качестве временной меры помогает настройка swap, но лучше добавить RAM.

Перевод фоновых заданий на cron

Сразу после установки Nextcloud работает в режиме AJAX: фоновые задания выполняются только тогда, когда кто-то держит интерфейс открытым. Именно поэтому на малопосещаемых установках полнотекстовый поиск, уборка мусора и уведомления как будто не происходят вовсе. Переключитесь на настоящий cron, Nextcloud рассчитывает на запуск каждые пять минут. Основы разобраны в статье настройка cron-задания в Linux.

sudo crontab -u www-data -e

Туда вписать:

*/5 * * * * php -f /var/www/nextcloud/cron.php

После этого сообщите Nextcloud о смене режима:

cd /var/www/nextcloud
sudo -u www-data php occ background:cron

Кто предпочитает обходиться без демона cron, берёт службу systemd с таймером. Юнит nextcloudcron.service вызывает /usr/bin/php -f /var/www/nextcloud/cron.php от пользователя www-data, а соответствующий таймер задаёт OnBootSec=5min и OnUnitActiveSec=5min.

Если предупреждение «Last background job execution ran X hours ago. Something seems wrong» всё равно остаётся, проверяйте по порядку: задание запускается от нужного пользователя? Путь действительно существует? И самое важное: способен ли cron.php вообще отработать с конфигурацией PHP для командной строки, или там не хватает модуля, который поставили только для FPM? Честнее всего проверять вручную, тогда каждое сообщение об ошибке видно открытым текстом:

sudo -u www-data php -f /var/www/nextcloud/cron.php

Разбор предупреждений на странице обзора

Список в разделе Параметры администрирования и Обзор не украшение, у каждой строки есть конкретная причина. Самые частые из них и способы их устранить:

  • «No memory cache has been configured»: APCu установлен, но не прописан. occ config:system:set memcache.local --value='\OC\Memcache\APCu'. Чтобы кэшем пользовались также occ и запуски cron, дополнительно задайте apc.enable_cli=1 в /etc/php/<version>/mods-available/apcu.ini.
  • «Transactional file locking is disabled»: установите Redis (apt-get install -y redis-server php-redis) и задайте memcache.locking значение \OC\Memcache\Redis. На установке для одного человека без этого можно обойтись, но как только начинают синхронизироваться несколько пользователей одновременно, уже нет.
  • «Your web server is not properly set up to resolve /.well-known/caldav»: не хватает правил перезаписи в блоке location ^~ /.well-known. Проверить это можно напрямую командой curl -I https://cloud.example.com/.well-known/caldav, ожидается 301 на /remote.php/dav/.
  • «Your installation has no default phone region set»: occ config:system:set default_phone_region --value="AT", для Германии DE. В качестве значения указывается код страны по ISO 3166-1.
  • «Server has no maintenance window start time configured»: occ config:system:set maintenance_window_start --type=integer --value=1. Значением задаётся час начала по UTC, тогда тяжёлые ежедневные задания идут ночью, а не посреди рабочего дня.
  • «The database is missing some indexes»: occ db:add-missing-indices, а к ней в пару occ db:add-missing-columns и occ db:add-missing-primary-keys. На больших установках эти команды работают медленно, но они безопасны.
  • «PHP does not seem to be setup properly to query system environment variables»: в файле пула FPM /etc/php/<version>/fpm/pool.d/www.conf раскомментируйте строку env[PATH] = /usr/local/bin:/usr/bin:/bin и перезапустите FPM.
  • «Module php-imagick in this instance has no SVG support»: это не ошибка Nextcloud, а отсутствующая библиотека-делегат в ImageMagick. Если предпросмотр SVG вам не нужен, предупреждение можно оставить как есть.

Как понять, что всё действительно работает

Четыре проверки, которые вместе дают ясную картину:

cd /var/www/nextcloud
sudo -u www-data php occ status
sudo -u www-data php occ check
sudo -u www-data php occ config:app:get core lastcron

occ status должен сообщить installed: true и ожидаемую версию, occ check не должен выводить ничего. Третья команда возвращает метку времени Unix. Пересчитайте её: она не должна быть старше пяти минут, тогда ваш cron действительно работает.

Снаружи:

curl -s https://cloud.example.com/status.php

В ответ приходит объект JSON с "installed":true, "maintenance":false и номером версии. Если возвращается HTML, значит одно из ваших правил location захватывает слишком много. Если приходит перенаправление на страницу входа, всё в порядке, просто вы взяли не тот URL.

И напоследок практическая проверка, которую не заменит ни одна страница статуса: загрузите через веб-интерфейс файл на несколько гигабайт и затем синхронизируйте его десктопным клиентом. Только так становится видно, согласованы ли между собой client_max_body_size, post_max_size, тайм-ауты и свободное место на накопителе. Если на этом месте всё внезапно встаёт, стоит посмотреть в сторону заполненного накопителя, ведь Nextcloud создаёт эскизы и версии файлов, а они растут заметно.

Если что-то пошло не так

Nextcloud пишет журнал в /var/nextcloud-data/nextcloud.log, то есть в ваш каталог данных, а не в /var/log. Именно в этот файл нужно смотреть первым, а не в журнал nginx. Для читаемого вывода:

sudo -u www-data php occ log:watch

Если после прерванного обновления установка застряла в режиме обслуживания, вернуть её обратно поможет occ maintenance:mode --off. Если интерфейс вообще недоступен, задайте 'maintenance' => false прямо в config/config.php.

Прежде чем крутить базу данных или конфигурацию, сделайте резервную копию и того, и другого. Копии одного лишь каталога недостаточно: без подходящей базы данных Nextcloud бесполезен:

sudo -u www-data php occ maintenance:mode --on
sudo mariadb-dump --single-transaction nextcloud > /root/nextcloud-db.sql
sudo -u www-data php occ maintenance:mode --off

И общий совет: доведите сервер до готовности прежде, чем открывать к нему доступ снаружи. Файрвол, защищённый SSH-доступ и пункты из чек-листа для нового root-сервера идут до первого входа в систему, а не после. Установку Nextcloud со стандартным паролем находят за считаные часы.

Частые вопросы

Какая версия PHP нужна для Nextcloud?
Nextcloud 33 и 34 требуют минимум PHP 8.2 и поддерживают версии вплоть до 8.5, Nextcloud 32 работает начиная с PHP 8.1. Debian 13 (PHP 8.4), Debian 12 (PHP 8.2) и Ubuntu 24.04 (PHP 8.3) подходят без сторонних репозиториев. Ubuntu 22.04 поставляет только PHP 8.1 и для актуальных веток уже слишком стар, там понадобится PPA ondrej/php. Debian 11 даёт PHP 7.4: установка проходит там без единой ошибки, но при первом же открытии Nextcloud отдаёт HTTP 500 и сообщение «This version of Nextcloud requires at least PHP 8.2».
Почему появляется «You are accessing the site from an untrusted domain»?
Nextcloud принимает только те имена узлов, которые перечислены в массиве trusted_domains в файле config/config.php. Добавьте нужное имя командой sudo -u www-data php occ config:system:set trusted_domains 1 --value=cloud.example.com. Индекс считается с 0, а уже занятый индекс будет перезаписан.
Почему загрузка файлов обрывается, хотя php.ini уже увеличен?
Ограничений три. Кроме upload_max_filesize и post_max_size в php.ini для FPM, Nextcloud приносит собственный .user.ini в каталоге установки, который действует на уровне каталога и потому перебивает глобальные значения, а nginx дополнительно ограничивает размер запроса через client_max_body_size. Если последнее значение слишком мало, появляется 413 Request Entity Too Large ещё до того, как дело дойдёт до PHP.
Почему не выполняются фоновые задания?
Свежие установки стоят в режиме AJAX, а в нём задания выполняются только при открытом интерфейсе. Впишите */5 * * * * php -f /var/www/nextcloud/cron.php в crontab пользователя www-data и переключите режим командой occ background:cron. Проверить результат можно через occ config:app:get core lastcron: метка времени не должна быть старше пяти минут.
Какие права нужны каталогу данных?
Он принадлежит пользователю веб-сервера (www-data на Debian и Ubuntu, apache или nginx в семействе Red Hat) и должен иметь права chmod 750. Слишком широкие права дают сообщение «Your data directory is readable by other users». Создавайте этот каталог за пределами корневого каталога веб-сервера, например в /var/nextcloud-data.
Как убрать предупреждение об отсутствующем кэше в памяти?
Установите php-apcu и задайте occ config:system:set memcache.local --value='\OC\Memcache\APCu'. Чтобы кэшем пользовались также occ и запуски cron, дополнительно пропишите apc.enable_cli=1 в файле apcu.ini для командной строки PHP.
Можно ли использовать Nextcloud с PostgreSQL?
Да, PostgreSQL поддерживается Nextcloud наравне с MySQL, а в документации даже назван предпочтительным. На Debian это заодно снимает вопрос про MySQL, которого там всё равно нет в виде пакета. При установке укажите --database "pgsql" вместо "mysql".

Nextcloud селфхостинг PHP nginx MariaDB Debian Ubuntu облако Linux