Облачный сервер Nextcloud
Nextcloud — self-hosted облако (аналог Google Drive / Яндекс.Диска): веб-доступ к файлам и клиенты синхронизации для всех платформ. Данные хранятся на вашем железе, под вашим контролем.
Архитектура
| Компонент | Назначение | Пример адреса |
|---|---|---|
| Внешний nginx | HTTPS, reverse-proxy, точка входа | 192.168.3.47 |
| Сервер Nextcloud | Apache+PHP, БД, кеш, Docker-офис | 192.168.1.145 |
| Домен Nextcloud | для пользователей | nc.example.com |
| Домен Collabora | для офисного движка | collab.example.com |
Требования
- Контейнер LXC или ВМ с Ubuntu 24.04 LTS (минимум 2 ГБ RAM; для Collabora «рядом» — 4 ГБ).
- Хранилище для данных (отдельный диск/массив), смонтированное, например, в
/media/nextcloud. - Отдельный сервер/контейнер с nginx (reverse-proxy) — см. раздел про nginx.
- Доменные имена, указывающие на ваш публичный IP (например
nc.example.com,collab.example.com).
Установка Nextcloud
Системные пакеты
Обновляем список доступных пакетов:
sudo apt update
Устанавливаем веб-сервер, БД, PHP и сопутствующие модули:
sudo apt install -y apache2 mariadb-server libapache2-mod-php8.3 \
php8.3 php8.3-{gd,mysql,curl,mbstring,intl,gmp,bcmath,xml,zip,imagick,apcu,redis} \
redis-server unzip
Настройка PHP
Откройте конфиг PHP для Apache — /etc/php/8.3/apache2/php.ini — и задайте значения (если параметр есть — поправьте, если нет — добавьте):
memory_limit = 512M
upload_max_filesize = 10G
post_max_size = 10G
max_execution_time = 3600
max_input_time = 3600
output_buffering = Off
upload_max_filesize и post_max_size задают максимальный размер загружаемого файла (поставьте сколько нужно). output_buffering обязательно Off — иначе большие загрузки могут обрываться. Изменения применятся после перезапуска Apache (сделаем ниже).База данных
Заходим в консоль MariaDB от имени администратора:
sudo mariadb
Создаём саму базу данных — назовём её nextclouddb (с поддержкой эмодзи и любых символов):
CREATE DATABASE nextclouddb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
Создаём пользователя nextcloud, который будет обращаться к базе только с этого же сервера (localhost). Вместо <ВАШ_ПАРОЛЬ_БД> придумайте свой пароль и не потеряйте его — он понадобится при установке Nextcloud:
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY '<ВАШ_ПАРОЛЬ_БД>';
Выдаём этому пользователю полные права на нашу базу (и только на неё):
GRANT ALL PRIVILEGES ON nextclouddb.* TO 'nextcloud'@'localhost';
Применяем (сохраняем) выданные права — без этого они не вступят в силу:
FLUSH PRIVILEGES;
Выходим из консоли базы данных:
EXIT;
nextclouddb), пользователь (nextcloud) и пароль — понадобятся на шаге первого запуска Nextcloud: их вписывают в соответствующие поля. Держите их под рукой.Загрузка Nextcloud
/var/www.Переходим в папку веб-сервера:
cd /var/www
Скачиваем последнюю версию (официальный сайт):
sudo wget https://download.nextcloud.com/server/releases/latest.zip
Распаковываем архив (появится папка nextcloud):
sudo unzip latest.zip
Передаём папку во владение веб-серверу (пользователь www-data) — иначе Nextcloud не сможет писать файлы:
sudo chown -R www-data:www-data /var/www/nextcloud
Настройка Apache
.htaccess — нужны для чистых ссылок) и научим определять реальные адреса пользователей, приходящих через nginx.Включаем необходимые модули Apache:
sudo a2enmod rewrite headers env dir mime setenvif remoteip
Создаём конфиг сайта. Откройте новый файл /etc/apache2/sites-available/nextcloud.conf и впишите (подставьте свой ServerName и IP вашего nginx в RemoteIPInternalProxy):
<VirtualHost *:80>
DocumentRoot /var/www/nextcloud/
ServerName nc.example.com
# определять реальный IP пользователя за nginx:
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 192.168.3.47/24
# безопасные cookie:
Header always edit Set-Cookie ^(.*)$ "$1; Secure; HttpOnly; SameSite=Strict"
<Directory /var/www/nextcloud/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
LimitRequestBody 10737418240
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
</VirtualHost>
AllowOverride All обязателен — без него не работают .htaccess Nextcloud, а значит сломаются и чистые ссылки, и часть защиты. LimitRequestBody задаёт максимальный размер запроса (здесь 10 ГБ).Включаем наш сайт, отключаем дефолтный и перезапускаем Apache:
sudo a2ensite nextcloud
sudo a2dissite 000-default
sudo systemctl restart apache2
Первичная установка через occ
occ — это «пульт управления» Nextcloud из командной строки. Запускается от пользователя веб-сервера: sudo -u www-data php occ .... Установить можно и через браузер (мастер установки), но через команду — быстрее и нагляднее.Переходим в папку Nextcloud:
cd /var/www/nextcloud
Запускаем установку. Подставьте свои значения: пароль БД (из шага выше), логин и пароль администратора, и путь к хранилищу данных:
sudo -u www-data php occ maintenance:install \
--database mysql --database-name nextclouddb \
--database-user nextcloud --database-pass '<ВАШ_ПАРОЛЬ_БД>' \
--admin-user admin --admin-pass '<ПАРОЛЬ_АДМИНА>' \
--data-dir /media/nextcloud
--database-name (имя базы), --database-user (пользователь) и --database-pass (пароль). А --admin-user / --admin-pass — это логин и пароль, под которыми вы зайдёте в само облако через браузер.Ключевые параметры config.php
/var/www/nextcloud/config/config.php — главный конфиг Nextcloud. Откройте его редактором и проверьте/добавьте параметры ниже (подставляя свои домен и IP).Разрешённые домены, по которым открывается ваше облако:
'trusted_domains' => array('nc.example.com'),
Адрес, который Nextcloud использует в ссылках и фоновых задачах:
'overwrite.cli.url' => 'https://nc.example.com',
'overwriteprotocol' => 'https',
IP вашего внешнего nginx — чтобы Nextcloud правильно определял реальные адреса пользователей:
'trusted_proxies' => array('192.168.3.47'),
trusted_proxies обязательно укажите на IP вашего nginx — иначе Nextcloud будет видеть всех пользователей под одним адресом (адресом прокси), и сломается защита от перебора паролей.Путь к хранилищу данных и регион телефонов (для контактов):
'datadirectory' => '/media/nextcloud',
'default_phone_region' => 'RU',
Чистые ссылки (без index.php)
.../index.php/apps/files. Чтобы они были короткими и чистыми (.../apps/files), включаем перезапись адресов. Работает за счёт модуля mod_rewrite и .htaccess (мы их уже включили в разделе про Apache).Добавьте в config.php строку:
'htaccess.RewriteBase' => '/',
Затем попросите Nextcloud сгенерировать правила перезаписи в файле .htaccess:
cd /var/www/nextcloud
sudo -u www-data php occ maintenance:update:htaccess
mod_rewrite или в VirtualHost не стоит AllowOverride All (см. раздел Настройка Apache).Кеш и производительность
APCu + Redis
Устанавливаем APCu и Redis (если ещё не стоят):
sudo apt install -y php-apcu redis-server php-redis
Включаем APCu для командной строки (нужно для occ и фоновых задач):
echo "apc.enable_cli=1" | sudo tee /etc/php/8.3/mods-available/apcu-cli.ini
sudo ln -sf /etc/php/8.3/mods-available/apcu-cli.ini /etc/php/8.3/cli/conf.d/30-apcu-cli.ini
Настраиваем Redis на работу через быстрый локальный «сокет». Откройте /etc/redis/redis.conf и задайте:
unixsocket /run/redis/redis-server.sock
unixsocketperm 770
maxmemory 128mb
maxmemory-policy noeviction
Даём веб-серверу доступ к сокету Redis и перезапускаем его:
sudo usermod -aG redis www-data
sudo systemctl restart redis-server
Подключаем кеш в config.php (APCu — локальный, Redis — блокировки и общий кеш):
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' => array('host' => '/run/redis/redis-server.sock', 'port' => 0),
memcache.locking — блокировки файлов на нём ненадёжны. Для блокировок нужен именно Redis.Тюнинг под ограниченную память
nextcloud.log массовые «Connection refused», а в journalctl -u mariadb — «killed by OOM killer». Лечится ограничением воркеров Apache (ниже).Ограничиваем число процессов Apache. Откройте /etc/apache2/mods-available/mpm_prefork.conf и задайте:
ServerLimit 16
MaxRequestWorkers 12
MaxConnectionsPerChild 1000
Защищаем базу от убийства при нехватке памяти. Создайте файл /etc/systemd/system/mariadb.service.d/oom.conf:
[Service]
OOMScoreAdjust=-900
Применяем защиту:
sudo systemctl daemon-reload
sudo systemctl restart mariadb
Настраиваем саму MariaDB под небольшую память. Создайте /etc/mysql/mariadb.conf.d/90-nextcloud.cnf:
[mysqld]
innodb_buffer_pool_size = 256M
tmp_table_size = 64M
max_heap_table_size = 64M
max_connections = 40
innodb_flush_log_at_trx_commit = 2
skip-name-resolve
Настраиваем OPcache (ускоряет выполнение PHP). Создайте /etc/php/8.3/apache2/conf.d/99-nextcloud-opcache.ini:
opcache.enable=1
opcache.interned_strings_buffer=16
opcache.memory_consumption=256
opcache.max_accelerated_files=10000
opcache.save_comments=1
opcache.revalidate_freq=60
Перезапускаем Apache, чтобы настройки применились:
sudo systemctl restart apache2
Фоновые задачи (cron)
Открываем расписание пользователя www-data:
sudo -u www-data crontab -e
Добавляем строку:
*/5 * * * * php -f /var/www/nextcloud/cron.php
В настройках Nextcloud (Администрирование → Основные параметры) выберите режим фоновых задач «Cron».
Обновление Nextcloud
Бэкап перед обновлением
Сохраняем базу данных в сжатый файл:
mysqldump -uroot --single-transaction nextclouddb | gzip > /root/nc-db-$(date +%F).sql.gz
Сохраняем конфиг:
cp /var/www/nextcloud/config/config.php /root/config.php.bak
Обновление одной ступени
Включаем режим обслуживания (сайт станет недоступен на время):
cd /var/www/nextcloud
sudo -u www-data php occ maintenance:mode --on
Скачиваем нужную версию и проверяем её контрольную сумму (целостность):
wget https://download.nextcloud.com/server/releases/nextcloud-33.0.5.zip
wget https://download.nextcloud.com/server/releases/nextcloud-33.0.5.zip.sha256
sha256sum -c nextcloud-33.0.5.zip.sha256
Распакуйте новую версию в отдельную папку, перенесите туда из старой папки каталог config/ и ваши сторонние приложения, затем замените старую папку новой. После этого запускаем обновление базы:
sudo -u www-data php occ upgrade
Добавляем недостающие индексы и колонки (ускоряет БД):
sudo -u www-data php occ db:add-missing-indices
sudo -u www-data php occ db:add-missing-columns
Выключаем режим обслуживания и перезапускаем Apache (сбросить кеш старого кода):
sudo -u www-data php occ maintenance:mode --off
sudo systemctl restart apache2
occ upgrade — если для целевой версии уже есть совместимый релиз. Перед мажорным апгрейдом проверьте совместимость на apps.nextcloud.com.Collabora Office (Docker)
Установка Docker
Устанавливаем Docker и включаем его автозапуск:
sudo apt install -y docker.io
sudo systemctl enable --now docker
--security-opt apparmor=unconfined (см. ниже). Контейнеру LXC также нужен nesting и нужные права (на хосте Proxmox: pct set <id> -features nesting=1).Запуск Collabora CODE
aliasgroup1) и домен Collabora (в server_name).Скачиваем образ и запускаем контейнер:
sudo docker run -d --name collabora --restart unless-stopped \
-p 9980:9980 \
--security-opt apparmor=unconfined \
--security-opt seccomp=unconfined \
--cap-add MKNOD \
-e 'aliasgroup1=https://nc\.example\.com:443' \
-e 'server_name=collab.example.com' \
-e 'extra_params=--o:ssl.enable=false --o:ssl.termination=true' \
collabora/code
aliasgroup1 — доверенный адрес Nextcloud (точки экранированы, это регулярное выражение). ssl.termination=true — SSL расшифровывает nginx, а движок работает по HTTP внутри сети.Проверяем, что движок отвечает (ожидаем код 200):
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9980/hosting/discovery
Подключение в Nextcloud
Устанавливаем приложение-коннектор «Nextcloud Office»:
cd /var/www/nextcloud
sudo -u www-data php occ app:install richdocuments
Указываем адрес нашего движка Collabora (домен collab):
sudo -u www-data php occ config:app:set richdocuments wopi_url --value 'https://collab.example.com'
sudo -u www-data php occ config:app:set richdocuments public_wopi_url --value 'https://collab.example.com'
sudo -u www-data php occ config:app:set richdocuments disable_certificate_verification --value 'yes'
richdocumentscode (встроенный CODE) — оно принудительно гонит весь трафик через медленный proxy.php, и документы открываются пустыми. Используйте только внешний Docker-движок через wopi_url.Внешний nginx
Конфиг Nextcloud (nc.example.com)
Создайте файл /etc/nginx/sites-enabled/nc.example.com со следующим содержимым (подставьте свой домен и IP сервера Nextcloud):
map $http_upgrade $nc_connection_upgrade { default upgrade; "" close; }
server {
listen 80;
server_name nc.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name nc.example.com;
ssl_certificate /etc/letsencrypt/live/nc.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nc.example.com/privkey.pem;
client_max_body_size 10G;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.1.145; # IP сервера Nextcloud
proxy_read_timeout 900s;
proxy_request_buffering off;
proxy_buffering off;
proxy_max_temp_file_size 0;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $nc_connection_upgrade;
}
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
}
Конфиг Collabora (collab.example.com)
/cool/ws требует заголовков upgrade. HTTP/2 на этом домене лучше не включать (WebSocket надёжнее по HTTP/1.1).Создайте файл /etc/nginx/sites-enabled/collab.example.com:
map $http_upgrade $collab_upgrade { default upgrade; "" close; }
server {
listen 80;
server_name collab.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name collab.example.com;
ssl_certificate /etc/letsencrypt/live/collab.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/collab.example.com/privkey.pem;
location ^~ /browser { proxy_pass http://192.168.1.145:9980; proxy_set_header Host $host; }
location ^~ /hosting/discovery { proxy_pass http://192.168.1.145:9980; proxy_set_header Host $host; }
location ^~ /hosting/capabilities { proxy_pass http://192.168.1.145:9980; proxy_set_header Host $host; }
location ~ ^/cool {
proxy_pass http://192.168.1.145:9980;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $collab_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
}
}
Получаем SSL-сертификаты для обоих доменов:
sudo certbot --nginx -d nc.example.com -d collab.example.com
Проверяем конфигурацию и перезагружаем nginx:
sudo nginx -t && sudo systemctl reload nginx
Локальный доступ по доменам (split-DNS)
Вариант OpenWrt
Добавляем DNS-записи (подставьте свои домены и IP nginx):
uci add_list dhcp.@dnsmasq[0].address='/nc.example.com/192.168.3.47'
uci add_list dhcp.@dnsmasq[0].address='/collab.example.com/192.168.3.47'
Сохраняем и перезапускаем DNS-сервер:
uci commit dhcp
/etc/init.d/dnsmasq restart
/nc.example.com/192.168.3.47.Вариант Keenetic
Добавляем записи (подставьте свои домены и IP nginx):
ip host nc.example.com 192.168.3.47
ip host collab.example.com 192.168.3.47
Сохраняем конфигурацию роутера:
system configuration save
system configuration save обязательна — без неё после перезагрузки роутера записи сбросятся. Посмотреть их можно командой show running-config (строки ip host).Проверка
С любого устройства в локальной сети выполните:
nslookup nc.example.com
В ответе должен быть внутренний IP nginx (например 192.168.3.47), а не публичный. Значит, трафик идёт локально. SSL по имени домена при этом остаётся валидным.
Обслуживание
Логи и их ротация
/media/nextcloud/nextcloud.log со временем разрастается (бывает до сотен МБ). Ротация автоматически режет его на части и сжимает.Создайте файл /etc/logrotate.d/nextcloud:
/media/nextcloud/nextcloud.log {
weekly
rotate 8
size 50M
compress
delaycompress
copytruncate
su www-data www-data
}
Превью для быстрой галереи
Устанавливаем приложение:
sudo -u www-data php occ app:install previewgenerator
Ограничиваем размеры превью (компактнее и быстрее):
sudo -u www-data php occ config:app:set previewgenerator squareSizes --value "256"
sudo -u www-data php occ config:system:set jpeg_quality --value "80"
Ставим защитный лимит памяти на генерацию (чтобы большое фото не съело всю память):
sudo -u www-data php occ config:system:set preview_max_memory --value 256 --type integer
Запускаем разовый прогрев в фоне с низким приоритетом (не мешает работе; --workers — под число дисков/ядер):
nohup nice -n 19 ionice -c 3 sudo -u www-data php occ preview:generate-all --workers=4 &
occ config:app:set previewgenerator widthSizes --value "1024".Шпаргалка обслуживания
Сервисы: статус и перезапуск
Посмотреть, работают ли ключевые сервисы (active = работает):
systemctl status apache2 mariadb redis-server docker --no-pager
Перезапустить веб-сервер / базу / кеш:
sudo systemctl restart apache2
sudo systemctl restart mariadb
sudo systemctl restart redis-server
Коротко проверить, активен ли сервис (отвечает active / inactive):
systemctl is-active apache2 mariadb redis-server
Режим обслуживания
Включить / выключить / проверить режим обслуживания:
cd /var/www/nextcloud
sudo -u www-data php occ maintenance:mode --on
sudo -u www-data php occ maintenance:mode --off
sudo -u www-data php occ maintenance:mode
База данных
Войти в консоль базы (от администратора) или под пользователем Nextcloud:
sudo mariadb nextclouddb
mysql -u nextcloud -p nextclouddb
Посмотреть размер базы и крупнейшие таблицы (выполняется внутри консоли БД):
SELECT table_name, ROUND((data_length+index_length)/1024/1024,1) AS mb
FROM information_schema.tables WHERE table_schema='nextclouddb'
ORDER BY mb DESC LIMIT 10;
Сделать резервную копию базы / восстановить из копии:
mysqldump -uroot --single-transaction nextclouddb | gzip > /root/nc-db-$(date +%F).sql.gz
zcat /root/nc-db-2026-01-01.sql.gz | mysql -uroot nextclouddb
occ — частые команды
/var/www/nextcloud от пользователя www-data.# статус и версия
sudo -u www-data php occ status
# проверка конфигурации (ошибки и рекомендации)
sudo -u www-data php occ setupchecks
# список приложений
sudo -u www-data php occ app:list
# список пользователей
sudo -u www-data php occ user:list
# пересканировать файлы (если что-то добавляли в хранилище мимо Nextcloud)
sudo -u www-data php occ files:scan --all
# прочитать / изменить параметр конфигурации
sudo -u www-data php occ config:system:get memcache.local
# починка/обслуживание (повторная генерация .htaccess, ремонт)
sudo -u www-data php occ maintenance:update:htaccess
sudo -u www-data php occ maintenance:repair
Логи
Следить за логом Nextcloud / ошибками Apache / журналом сервиса в реальном времени:
tail -f /media/nextcloud/nextcloud.log
tail -f /var/log/apache2/error.log
journalctl -u mariadb -f
Проверить, были ли падения базы из-за нехватки памяти (OOM):
journalctl -u mariadb | grep -i oom
Collabora / Docker
Список запущенных контейнеров и их состояние:
docker ps
Лог Collabora / перезапуск контейнера:
docker logs --tail 50 collabora
docker restart collabora
Проверить, что движок отвечает (ожидаем код 200):
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9980/hosting/discovery
Система
Память / место на диске / нагрузка и самые «прожорливые» процессы:
free -h
df -h
ps aux --sort=-%mem | head