Файл docker-compose для Nextcloud со всем необходимым
Опубликовано:
Используемые термины: Nextcloud, Docker, Linux.
В инструкции будет приведен не только пример файла docker-compose, но и примеры команд для настройки и запуска приложения. В итоге, мы получим:
- Облачное решение Nextcloud с базовыми функциями.
- Возможность работы с документами при помощи Onlyoffice.
- Платформу для проведения видеоконференций с большим числом участников.
Для работы будет использоваться система на базе Linux. Подразумевается, что Docker и docker-compose уже установлены в системе.
Nextcloud с базовыми функциями
Для начала поднимаем облачный сервис для хранения файлов. Создаем каталог, где разместим docker файлы и переходим в него:
mkdir -p /opt/nextcloud && cd /opt/nextcloud
Создаем файл docker-compose:
vi docker-compose.yml
- services:
- postgres:
- image: postgres:${PG_VER}-alpine
- container_name: postgres
- hostname: postgres
- restart: unless-stopped
- volumes:
- - ./postgresql/data:/var/lib/postgresql/data
- environment:
- TZ: Europe/Moscow
- POSTGRES_DB: ${DB_NAME}
- POSTGRES_USER: ${DB_USER}
- POSTGRES_PASSWORD: ${DB_PASSWORD}
- redis:
- image: redis:alpine
- container_name: redis
- hostname: redis
- restart: unless-stopped
- environment:
- TZ: Europe/Moscow
- nextcloud:
- image: nextcloud:${NC_VER}
- container_name: nextcloud
- hostname: nextcloud
- restart: unless-stopped
- extra_hosts:
- - "${NC_DOMAIN}:host-gateway"
- depends_on:
- - postgres
- - redis
- volumes:
- - ./nextcloud:/var/www/html
- environment:
- TZ: Europe/Moscow
- VIRTUAL_HOST: ${NC_DOMAIN}
- NEXTCLOUD_TRUSTED_DOMAINS: ${NC_DOMAIN} 127.0.0.1
- NEXTCLOUD_OVERWRITEPROTOCOL: https
- NEXTCLOUD_ADMIN_USER: ${NC_ADMIN_USER}
- NEXTCLOUD_ADMIN_PASSWORD: ${NC_ADMIN_PASSWORD}
- POSTGRES_HOST: postgres
- POSTGRES_DB: ${DB_NAME}
- POSTGRES_USER: ${DB_USER}
- POSTGRES_PASSWORD: ${DB_PASSWORD}
- REDIS_HOST: redis
- caddy:
- image: caddy:${CD_VER}
- hostname: caddy
- container_name: caddy
- restart: unless-stopped
- environment:
- TZ: "Europe/Moscow"
- NC_DOMAIN: ${NC_DOMAIN}
- ports:
- - 80:80
- - 443:443
- volumes:
- - ./caddy/Caddyfile:/etc/caddy/Caddyfile
- - ./caddy/ssl:/etc/caddy/ssl
- cron:
- image: nextcloud:${NC_VER}
- hostname: cron
- container_name: cron
- restart: unless-stopped
- volumes:
- - ./nextcloud:/var/www/html
- entrypoint: /cron.sh
- depends_on:
- - nextcloud
- environment:
- TZ: "Europe/Moscow"
- POSTGRES_HOST: postgres
- POSTGRES_DB: ${DB_NAME}
- POSTGRES_USER: ${DB_USER}
- POSTGRES_PASSWORD: ${DB_PASSWORD}
- REDIS_HOST: redis
Описание сценария
Кратко опишем, что выполнит наш сценарий. Подробнее про работу с docker-compose можно прочитать в инструкции Шпаргалка по работе с docker-compose.
| Строки | Описание |
|---|---|
| 3 - 14 | Поднимаем контейнер с базой данных PostgreSQL. При инициализации мы создаем пользователя и базу. Значения передаем в виде переменных, значения которых мы потом укажем в файле .env. |
| 16 - 22 | Для кэширования данных используем Redis. |
| 24 - 47 | Описываем контейнер для запуска Nextcloud. Обратите внимание, что также как для PostgreSQL, часть параметров передаем переменными из .env файла. |
| 49 - 62 | Для проксирования http запросов мы будем использовать caddy. Данный контейнер будет слушать на портах 80 и 443. |
| 64 - 80 | Данный контейнер будет использоваться для запуска заданий Nextcloud по расписанию. |
Настройка и запуск
Для корректной работы сервиса нам нужно создать несколько конфигурационных файлов.
Сначала создадим файл .env:
vi .env
PG_VER=16
NC_VER=32
CD_VER=2.10
DB_USER=nextcloud
DB_PASSWORD=nextcloud123
DB_NAME=nextcloud
NC_DOMAIN=cloud.dmosk.local
NC_ADMIN_USER=admin
NC_ADMIN_PASSWORD=password123
* обратите внимание, что между знаком = не должно быть пробелов.
** вам необходимо указать свои значения:
- PG_VER / NC_VER / CD_VER — версии PostgreSQL, Nextcloud и Caddy соответственно. Лучше изучить документацию чтобы определиться с более правильными значениями или попробовать указать последние версии, посмотрев их на Docker Hub.
- DB_USER / DB_PASSWORD / DB_NAME — значения для первичной настройки базы данных. Имя пользователя, пароль и имя базы. Особое внимание стоит уделить паролю.
- NC_DOMAIN / NC_ADMIN_USER / NC_ADMIN_PASSWORD — данные для инициализации Nextcloud. Укажите ваш домен, на котором должен работать сервис, а также логин с паролем для входа в облако.
Создадим каталог для файлов веб-сервера caddy:
mkdir -p caddy
Если у нас используется внутренний домен и мы не можем из вне попасть на сервер, то необходимо сгенерировать самоподписанный сертификат. Данный вариант не самый лучший и некоторые службы могут работать некорректно, но для тестирования он подойдет.
Создадим каталог для хранения сертификатов:
mkdir -p caddy/ssl
И сгенерируем сертификат:
openssl req -new -x509 -days 1461 -nodes -out caddy/ssl/cert.pem -keyout caddy/ssl/cert.key -subj "/C=RU/ST=SPb/L=SPb/O=Global Security/OU=IT Department/CN=cloud.dmosk.local" -addext "subjectAltName=DNS:cloud.dmosk.local,IP:127.0.0.1"
* в данном примере будут созданы 2 файла caddy/ssl/cert.key и caddy/ssl/cert.pem для домена cloud.dmosk.local.
Создаем конфигурационный файл для caddy:
vi caddy/Caddyfile
{$NC_DOMAIN} {
tls /etc/caddy/ssl/cert.pem /etc/caddy/ssl/cert.key
redir /.well-known/carddav* /remote.php/dav 301
redir /.well-known/caldav* /remote.php/dav 301
header {
Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
}
handle {
reverse_proxy nextcloud:80
}
}
* обратите внимание на строку, где мы указываем путь до сертификатов. Если у вас внешний домен, доступный из вне, то кадди сам получит сертификаты от Let's Encrypt. Данную строку нужно удалить.
Запускаем контейнеры:
docker-compose up -d
Из состояние теперь можно посмотреть командой:
docker-compose ps
Для инициализации nextcloud понадобится какое-то время. Около минуты. Мы можем наблюдать за процессом, запустив непрерывное чтение логов:
docker logs nextcloud -f
После можно попробовать зайти в панель Nextcloud. Для этого в браузере вводим адрес, который указали в качестве имени. В моем примере https://cloud.dmosk.local.
Мы должны увидеть окно ввода логин и пароля. Вводим данные, которые указали в файле .env.
Оптимизация
Сразу после развертывания, Nextcloud будет отображать ошибки и предупреждения, без решения которых работа облачного сервиса будет не полностью полноценной. Рассмотрим по шагам, как оптимизировать работу приложения.
1. Укажем, что nextcloud может доверять проксированию из сети docker:
docker exec --user www-data nextcloud php occ config:system:set trusted_proxies 0 --value=$(docker inspect nextcloud -f '{{range .NetworkSettings.Networks}}{{.IPPrefixLen}}{{end}}' | xargs -I {} docker inspect nextcloud -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' | sed 's/\.[0-9]*$/\.0/')/$(docker inspect nextcloud -f '{{range .NetworkSettings.Networks}}{{.IPPrefixLen}}{{end}}')
2. Для запуска задач по расписанию используем cron, а также укажем окно обслуживания (тяжелые задания будут выполняться в данное время):
docker exec --user www-data nextcloud php occ config:app:set core backgroundjobs_mode --value="cron"
docker exec --user www-data nextcloud php occ config:system:set maintenance_window_start --type=integer --value=2
* в нашем примере наиболее долгие по времени операции будут запускаться после 02:00 ночи.
3. Выставляем телефонный регион по умолчанию:
docker exec --user www-data nextcloud php occ config:system:set default_phone_region --value="RU"
* в данном примере российский.
4. Сразу после развертывания Nextcloud, как правило, для оптимизации базы доступны миграции и команды для создания индексов. Выполняем команды:
docker exec --user www-data nextcloud php occ maintenance:repair --include-expensive
docker exec --user www-data nextcloud php occ db:add-missing-indices
5. Система будет выдавать предупреждение, если у нас не установлено приложение для обеспечения двухфакторной аутентификации. При этом, не обязательно его включать, но нужно, чтобы оно было. Выполняем команду:
docker exec --user www-data nextcloud php occ app:enable twofactor_totp
Готово. Можно пользоваться Nextcloud для работы с файлами.
Onlyoffice
Расширим функциональные возможности нашего сервиса, добавив возможность онлайн работы с документами. Для этого запустим контейнер onlyoffice.
Открываем на редактирование композ файл:
vi docker-compose.yml
Допишем в него:
...
- onlyoffice:
- image: onlyoffice/documentserver:${OO_VER}
- hostname: onlyoffice
- container_name: onlyoffice
- restart: unless-stopped
- extra_hosts:
- - "${NC_DOMAIN}:host-gateway"
- environment:
- JWT_ENABLED: true
- JWT_SECRET: ${OO_SECRET}
- USE_UNAUTHORIZED_STORAGE: true
- volumes:
- - ./onlyoffice/data:/var/www/onlyoffice/Data
* USE_UNAUTHORIZED_STORAGE — если вы используете не самоподписанный сертификат, то данная строка не нужна. Она позволяет делать запросы по https, если сертификат не может пройти валидацию.
Сгенерируем последовательность для токена:
openssl rand -hex 16
Фиксируем полученный результат. Он нам нужен для добавление системной переменной.
Откроем env файл:
vi .env
Допишем в него строку:
...
OO_VER=9.2
OO_SECRET=<Onfyoffice key>
* где Onfyoffice key — последовательность, которую мы получили командой openssl.
Запускаем новый контейнер:
docker-compose up -d
В нашем облачном приложении устанавливаем и включаем приложение onlyoffice:
docker exec --user www-data nextcloud php occ app:enable onlyoffice
Внесем изменение в конфигурацию веб-сервера кадди:
vi caddy/Caddyfile
Добавим внутрь нашей конфигурации для домена:
{$NC_DOMAIN} {
...
handle_path /onlyoffice/* {
reverse_proxy onlyoffice:80 {
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Prefix /onlyoffice
}
}
handle {
reverse_proxy nextcloud:80
}
}
Перезапустим контейнер с caddy:
docker restart caddy
Осталось настроить привязку в самом Nextcloud. Это также делается из командной строки.
Прочитаем наши переменные из энвайромент файла:
source .env
Укажем URL для подключения к Onlyoffice:
docker exec --user www-data nextcloud php occ config:app:set onlyoffice DocumentServerUrl --value="https://${NC_DOMAIN}/onlyoffice/"
Зададим токен безопасности:
docker exec --user www-data nextcloud php occ config:app:set onlyoffice jwt_secret --value="${OO_SECRET}"
Если мы используем самоподписанный сертификат, то необходимо отключить его проверку:
docker exec --user www-data nextcloud php occ config:app:set onlyoffice verify_peer_off --value="true"
Переходим в веб-интерфейс, настройку Onlyoffice и кликаем Сохранить.
Talk
Приложение Talk для реализации системы видеоконференции набрало большую популярность. Добавим в наш сценарий развертывание необходимых компонентов для его корректной работы.
Talk + Coturn
Возможность выполнять видеозвонки для небольшого числа участников требует развертывания приложения Talk и Coturn.
Устанавливаем в nextcloud приложение talk:
docker exec --user www-data nextcloud php occ app:install spreed
* исторически, nextcloud совместно со Struktur AG работали над интеграцией Spreed.ME в коробку. Поэтому id приложения называется не talk.
Проинсталлируем приложение notify_push для отправки push уведомлений:
docker exec --user www-data nextcloud php occ app:install notify_push
Открываем файл docker-compose:
vi docker-compose.yml
Добавляем в него сервис coturn:
...
- coturn:
- image: coturn/coturn:latest
- hostname: coturn
- container_name: coturn
- restart: unless-stopped
- environment:
- TZ: "Europe/Moscow"
- DETECT_EXTERNAL_IP: yes
- DETECT_RELAY_IP: yes
- network_mode: host
- command:
- - -n
- - --log-file=stdout
- - --lt-cred-mech
- - --fingerprint
- - --static-auth-secret=${TURN_SECRET}
- - --realm=${NC_DOMAIN}
- - --external-ip=$$(detect-external-ip)
- - --relay-ip=$$(detect-external-ip)
- - --total-quota=100
- - --bps-capacity=0
- - --stale-nonce=600
- - --no-multicast-peers
* обратите внимание на несколько моментов:
- network_mode: host — необходимое решение для Coturn, так как TURN серверу нужен прямой доступ к реальным IP-адресам клиентов.
- DETECT_EXTERNAL_IP — определение внешнего IP в облачных средах.
Сформируем секретный код для котурна:
openssl rand -hex 16
Открываем файл с системными переменными:
vi .env
Добавляем в него переменную со сформированным секретом:
...
TURN_SECRET=<TURN key>
Запускаем новый контейнер:
docker-compose up -d
Его состояние можно посмотреть командой:
docker-compose ps
Если на нашем хосте брандмауэр настроит на запрет, то открываем порт 3478 (tcp и udp). В зависимости от утилиты управления команды будут разные.
а) Для iptables (как правило, системы DEB):
iptables -I INPUT -p tcp --dport 3478 -j ACCEPT
iptables -I INPUT -p udp --dport 3478 -j ACCEPT
Для сохранения правил можно использовать
apt install iptables-persistent
netfilter-persistent save
б) Для firewalld (как правило, системы RPM):
firewall-cmd --add-port=3478/{tcp,udp}
firewall-cmd --add-port=3478/{tcp,udp} --permanent
Сервис готов к использованию. Но нужно его указать в настройках Nextcloud.
Открываем веб интерфейс и переходим в раздел Конференции. Добавляем TURN сервер и указываем наш домен с портом 3478:

Также необходимо прописать секретный ключ.
Проверяем подключение к сервису. Мы должны увидеть зеленую галочку:

Можно устраивать конференции на небольшое число участников.
High-performance backend (signaling)
Для более серьезных нагрузок (от 5 человек) рекомендуется развернуть высокопроизводительный сервер.
Нам нужно 5 секретов для безопасного взаимодействия компонентов. Можно придумать их самостоятельно, или сгенерировать одной командой:
seq 5 | xargs -I {} openssl rand -hex 16
Команда выдаст 5 строк, каждая из которых состоит из 32 символов. Сразу скопируйте их и подпишите, например:
# Janus
c178fcea4d2c0e45194cccb245283cff
# Hash
07e164de3c2ff5656ef10f115b3d54e3
# Block
e4bef0271402c471ba45e3d97fb3c2ac
# Internal secret
5aa3203091196cfb909af062b2022aae
# Nextcloud secret
f9b088e2cc8e4e175092f8663da498d9
Данные последовательности мы будем использовать в ходе настройки компонентов.
Открываем docker композе:
vi docker-compose.yml
Допишем в него новые сервисы:
...
- nats:
- image: nats:alpine
- hostname: nats
- container_name: nats
- restart: unless-stopped
- environment:
- TZ: "Europe/Moscow"
- janus:
- image: canyan/janus-gateway:latest
- hostname: janus
- container_name: janus
- restart: unless-stopped
- environment:
- TZ: "Europe/Moscow"
- network_mode: host
- volumes:
- - ./janus/janus.jcfg:/usr/local/etc/janus/janus.jcfg
- - ./janus/janus.transport.http.jcfg:/usr/local/etc/janus/janus.transport.http.jcfg
- signaling:
- image: strukturag/nextcloud-spreed-signaling:latest
- hostname: signaling
- container_name: signaling
- restart: unless-stopped
- extra_hosts:
- - "janus:host-gateway"
- - "coturn:host-gateway"
- - "${NC_DOMAIN}:host-gateway"
- environment:
- TZ: "Europe/Moscow"
- depends_on:
- - nats
- - janus
- volumes:
- - ./signaling/server.conf:/config/server.conf
* где:
- nats — обеспечиваем связь между компонентами. В нашем случае позволяет управлять комнатами и обмениваться служебными сообщениями между участниками.
- janus — универсальный WebRTC-сервер, который выступает в роли медиа-шлюза.
- signaling — для обмена управляющей информацией (установление, поддержание и завершение WebRTC-соединения).
Создадим каталог для хранения данных janus:
mkdir janus
Скачаем в него 2 оригинальных конфигурационных файла:
wget https://raw.githubusercontent.com/meetecho/janus-gateway/refs/heads/master/conf/janus.jcfg.sample.in -O janus/janus.jcfg
wget https://raw.githubusercontent.com/meetecho/janus-gateway/refs/heads/master/conf/janus.transport.http.jcfg.sample -O janus/janus.transport.http.jcfg
Откроем для редактирования основной конфигурационный файл:
vi janus/janus.jcfg
Приведем некоторые значения параметром к следующему виду:
configs_folder = "/usr/local/etc/janus"
plugins_folder = "/usr/local/lib/janus/plugins"
transports_folder = "/usr/local/lib/janus/transports"
events_folder = "/usr/local/lib/janus/events"
loggers_folder = "/usr/local/lib/janus/loggers"
full_trickle = true
turn_rest_api_key = "c178fcea4d2c0e45194cccb245283cff"
* если опция закомментирована, то комментарий нужно снять.
Создаем каталог для хранения файлов signaling:
mkdir signaling
Скачиваем конфигурационный файл в созданный каталог:
wget https://raw.githubusercontent.com/strukturag/nextcloud-spreed-signaling/refs/heads/master/server.conf.in -O signaling/server.conf
Открываем скачанный файл на редактирование:
vi signaling/server.conf
Приводим его к виду:
[http]
listen = 0.0.0.0:8080
[sessions]
hashkey = <Hash Key>
blockkey = <Block Key>
[nats]
url = nats://nats:4222
[clients]
internalsecret = <Internal Secret Key>
[backend]
backends = backend-1
[backend-1]
url = https://cloud.dmosk.local
secret = <Nextcloud Secret Key>
[mcu]
type = janus
url = ws://janus:8188
[turn]
apikey = <Janus Key>
secret = <Turn Server Key>
servers = turn:coturn:3478?transport=udp,turn:coturn:3478?transport=tcp
Можно запускать новые контейнеры:
docker-compose up -d
Делаем тестовый запрос:
curl -i http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' signaling):8080/api/v1/welcome
Мы должны увидеть, примерно, следующий ответ:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: nextcloud-spreed-signaling/2.1.0~docker
X-Spreed-Signaling-Features: audio-video-permissions, chat-relay, dialout, federation, hello-v2, incall-all, join-features, mcu, offer-codecs, recipient-call, serverinfo, simulcast, switchto, transient-data, transient-sessiondata, update-sdp, welcome
Date: Sat, 14 Feb 2026 20:55:19 GMT
Content-Length: 66
{"nextcloud-spreed-signaling":"Welcome","version":"2.1.0~docker"}
Открываем конфигурацию веб-сервера:
vi caddy/Caddyfile
Добавим внутри секции настройки домена:
{$NC_DOMAIN} {
...
handle_path /standalone-signaling/* {
reverse_proxy signaling:8080 {
header_up X-Forwarded-Prefix /standalone-signaling
}
}
handle {
reverse_proxy nextcloud:80
}
}
Перезапускаем caddy:
docker restart caddy
Попробуем сделать тестовый запрос. Для удобства ввода команды читаем системные переменные из .env файла:
source .env
И вводим:
curl -k --resolve ${NC_DOMAIN}:443:127.0.0.1 https://${NC_DOMAIN}/standalone-signaling/api/v1/welcome
Мы должны увидеть что-то на подобие:
{"nextcloud-spreed-signaling":"Welcome","version":"2.1.0~docker"}
Теперь необходимо привязать сервер к Nextcloud. В настройка последнего переходим в конференции:

Добавляем новый высокопроизводительный сервер и секретный ключ (Nextcloud):

Мы должны увидеть OK при проверке работоспособности:

Теперь у нас нет программных ограничений для проведения более масштабных конференций.