Nextcloud в Docker: персональное облачное хранилище
Полное руководство: PostgreSQL и Redis, фоновые задачи через cron вместо AJAX, HTTPS за реверс-прокси и то, что обычно ломается уже после успешной установки.
- Зачем свой Nextcloud вместо Dropbox
- Что понадобится перед стартом
- Шаг 1 — разделение томов: данные и конфигурация
- Шаг 2 — docker-compose.yml построчно
- Шаг 3 — config.php: домены, прокси, редис
- Шаг 4 — фоновые задачи через cron, а не AJAX
- Шаг 5 — HTTPS через реверс-прокси
- Производительность: PHP, кэш, миниатюры
- Бэкапы: почему нельзя копировать «на горячую»
- Безопасность
- Частые проблемы
Зачем свой Nextcloud вместо Dropbox
Nextcloud — не просто синхронизация файлов, а рабочее пространство целиком: календари, менеджер задач, совместное редактирование документов, галерея с распознаванием дублей и шифрование на лету через плагины. На собственном NAS всё это работает без лимитов "бесплатного тарифа" и без индексации ваших файлов чужой рекомендательной системой.
Плата за это — то, что раздачу нагрузки, фоновые задачи и бэкапы теперь настраиваете вы сами. Собственно этому и посвящена оставшаяся часть статьи: без грамотной настройки cron и кэша Nextcloud на слабом железе воспринимается как медленный и глючный, хотя причина обычно не в самом приложении, а в паре строк конфигурации.
Что понадобится перед стартом
- Synology NAS с Container Manager и отдельным томом (или разделом) под пользовательские файлы, не совпадающим с системным томом Docker.
- Домен или поддомен и уже настроенный реверс-прокси с TLS — как и для остальных сервисов на NAS, HTTP здесь не вариант.
- Представление о примерном объёме данных — от этого зависит, куда физически указывать том с файлами.
Шаг 1 — разделение томов: данные и конфигурация
01Три разных тома — не один
Частая ошибка — держать конфигурацию, базу данных и пользовательские файлы в одном примонтированном каталоге. Разделите их сразу: тогда бэкап конфигурации остаётся лёгким, а сами файлы можно держать на самом ёмком томе NAS, не таская с собой мегабайты метаданных при каждом снапшоте.
mkdir -p /volume1/docker/nextcloud/{config,db,cron}
mkdir -p /volume1/nextcloud_data
| Том | Что внутри | Куда бэкапить |
|---|---|---|
| /volume1/docker/nextcloud/config | config.php, сертификаты, кэш приложений | ежедневно, вместе с базой |
| /volume1/docker/nextcloud/db | данные PostgreSQL | ежедневно, дампом (шаг «бэкапы») |
| /volume1/nextcloud_data | пользовательские файлы | по расписанию Hyper Backup, отдельно от базы |
Шаг 2 — docker-compose.yml построчно
02База данных, кэш и приложение
PostgreSQL вместо MySQL — не религиозный выбор, а меньше сюрпризов с полнотекстовым поиском и блокировками при параллельной синхронизации нескольких клиентов. Redis здесь решает две задачи одновременно: кэш переходов между страницами и распределённые блокировки файлов (об этом — в шаге о производительности).
POSTGRES_DB=nextcloud POSTGRES_USER=nextcloud POSTGRES_PASSWORD=сгенерируйте-длинный-пароль NEXTCLOUD_ADMIN_USER=admin NEXTCLOUD_ADMIN_PASSWORD=другой-длинный-пароль NEXTCLOUD_TRUSTED_DOMAINS=cloud.мойдомен.ру
services:
db:
image: postgres:16-alpine
container_name: nextcloud-db
restart: unless-stopped
env_file: .env
volumes:
- /volume1/docker/nextcloud/db:/var/lib/postgresql/data
mem_limit: 512m
redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
mem_limit: 128m
app:
image: nextcloud:29-apache
container_name: nextcloud-app
restart: unless-stopped
depends_on:
- db
- redis
env_file: .env
environment:
POSTGRES_HOST: db
REDIS_HOST: redis
REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
TRUSTED_PROXIES: "127.0.0.1"
ports:
- "127.0.0.1:8082:80"
volumes:
- /volume1/docker/nextcloud/config:/var/www/html
- /volume1/nextcloud_data:/var/www/html/data
mem_limit: 1g
cron:
image: nextcloud:29-apache
container_name: nextcloud-cron
restart: unless-stopped
depends_on:
- db
- redis
volumes:
- /volume1/docker/nextcloud/config:/var/www/html
- /volume1/nextcloud_data:/var/www/html/data
entrypoint: /cron.sh
mem_limit: 256m
Обратите внимание на два тома в сервисах app и cron — они указывают на одни и те же каталоги. Это не опечатка: фоновые задачи должны видеть ту же файловую структуру и конфигурацию, что и веб-приложение, иначе синхронизация состояния между ними банально не произойдёт.
Шаг 3 — config.php: домены, прокси, редис
03Донастройка после первого запуска
После инициализации через переменные окружения часть параметров всё равно проще прописать вручную в config.php — особенно то, что касается работы за реверс-прокси и блокировок Redis:
'trusted_domains' => [
'cloud.мойдомен.ру',
],
'overwriteprotocol' => 'https',
'overwrite.cli.url' => 'https://cloud.мойдомен.ру',
'trusted_proxies' => ['127.0.0.1'],
'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'filelocking.enabled' => true,
'redis' => [
'host' => 'redis',
'port' => 6379,
'password' => 'значение REDIS_PASSWORD из .env',
],
overwriteprotocol и trusted_proxies Nextcloud за HTTPS-прокси генерирует ссылки на http://, из-за чего ломается загрузка файлов через WebDAV и синхронизация десктопным клиентом — при этом веб-интерфейс в браузере может выглядеть рабочим, что сбивает с толку при диагностике.
Шаг 4 — фоновые задачи через cron, а не AJAX
По умолчанию Nextcloud предлагает запускать фоновые задачи (очистка временных файлов, пересчёт хранилища, отправка уведомлений) через AJAX — то есть только пока кто-то открывает вкладку в браузере. На домашнем сервере, где в интерфейс заходят раз в день, это означает, что задачи фактически не выполняются.
Сервис cron из compose-файла выше уже решает эту проблему — образ Nextcloud содержит собственный скрипт /cron.sh, который запускает occ system:cron каждые пять минут в бесконечном цикле. Остаётся только подтвердить режим в самом приложении: Настройки → Основные → Фоновые задачи → Cron.
Шаг 5 — HTTPS через реверс-прокси
В Nginx Proxy Manager (или аналоге) хост указывает на IP_NAS:8082. Обязательно увеличьте лимит на размер загружаемого тела запроса — иначе большие файлы будут обрываться на середине загрузки с неинформативной ошибкой 413:
client_max_body_size 10G; proxy_read_timeout 3600; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
Производительность: PHP, кэш, миниатюры
- APCu для локального кэша, Redis — для распределённого (как в config.php выше). APCu держит кэш в памяти самого PHP-процесса и не требует сети — заметно быстрее для однонодовой установки.
- PHP memory_limit не ниже 512 МБ — редактирование офисных документов и превью крупных изображений упираются в лимит по умолчанию на слабых конфигурациях.
- Предпросчёт миниатюр (
preview:generate-all) черезoccпосле массовой загрузки старого архива фото — иначе первые открытия альбома генерируют превью синхронно и ощутимо тормозят. - Индекс полнотекстового поиска отключайте, если он не нужен — фоновая индексация документов заметно грузит CPU на слабых NAS.
Бэкапы: почему нельзя копировать «на горячую»
Консистентный бэкап требует согласованного состояния трёх частей одновременно: файлов, базы данных и конфигурации. Простое копирование тома с файлами, пока база продолжает писать транзакции, может дать рассинхронизацию между тем, что Nextcloud думает о файлах, и тем, что реально лежит на диске.
#!/bin/bash STAMP=$(date +%Y%m%d-%H%M) DEST=/volume1/docker/nextcloud/backups mkdir -p "$DEST" docker exec -u www-data nextcloud-app php occ maintenance:mode --on docker exec nextcloud-db pg_dump -U nextcloud nextcloud | gzip > "$DEST/db-$STAMP.sql.gz" tar -czf "$DEST/config-$STAMP.tar.gz" -C /volume1/docker/nextcloud config docker exec -u www-data nextcloud-app php occ maintenance:mode --off find "$DEST" -name "*-2*.gz" -mtime +14 -delete
Режим обслуживания (maintenance:mode --on) блокирует запись новых файлов на несколько секунд, пока снимается дамп базы и архив конфигурации — короткая пауза вместо риска получить несогласованный бэкап. Сами пользовательские файлы на /volume1/nextcloud_data бэкапятся отдельно штатным Hyper Backup по расписанию — так как они не изменяются на уровне транзакций базы, для них моментальной консистентности не требуется.
Безопасность
- Двухфакторная аутентификация в настройках безопасности — обязательна для аккаунта администратора.
- Security & Setup Warnings в панели администратора — Nextcloud сам подсвечивает большинство проблем конфигурации, включая отсутствующие HTTP-заголовки безопасности.
- Ограничьте количество попыток входа — включённое приложение Brute-force settings по умолчанию, но не будет лишним добавить ограничение и на уровне реверс-прокси.
- Обновляйте приложения из встроенного каталога осторожно — сторонние приложения выполняются с теми же правами, что и само ядро Nextcloud.
Частые проблемы
| Симптом | Вероятная причина |
|---|---|
| «Доступ через недоверенный домен» | адрес отсутствует в trusted_domains в config.php |
| Синхронизация ломается на HTTPS, хотя в браузере всё открывается | не настроены overwriteprotocol и trusted_proxies |
| Уведомления и очистка временных файлов не работают | фоновые задачи всё ещё в режиме AJAX, а не Cron |
| Ошибка 413 при загрузке больших файлов | не увеличен client_max_body_size на реверс-прокси |
| «Есть блокировка файла» при параллельном редактировании | Redis для memcache.locking не настроен или недоступен |
| Медленное открытие альбомов с фото | миниатюры не сгенерированы заранее через occ preview:generate-all |
После того как cron переведён в правильный режим, домены и прокси настроены, а Redis отвечает за блокировки — Nextcloud на домашнем NAS ощущается ощутимо быстрее, чем сразу после установки «по умолчанию», без единого изменения в самом железе.