Nextcloud docker-compose setup
What is Nextcloud
Nextcloud is an open-source software suite for secure file storage and team collaboration.
- Self-Hosted alternative: Replaces services like Google Drive.
- Complete Control: On-premises or in the cloud deployment to maintain full data ownership.
Features
Features deployed in this Nextcloud docker-compose based deployment are:
- Files hosting - like google drive
- Web based collaborative document editing of word, spreadsheet, PowerPoint files - like google docs, sheets, slides
- Text, Audio, Video messaging and conference - like google meet or whatsapp
Architecture
- nextcloud container hosts the main nextcloud application
- Nextcloud container uses PostgreSQL container as database and Redis container for caching.
- collabora/code container hosts the collaborative document editing server
- aio-talk container hosts the high performance backend for nextcloud talk
- Apache reverse proxy container exposes nextcloud, collaboara/code, aio-talk container to the clients. Nextcloud container also accesses the collabora/code and aio-talk containers using the reverse proxy.
Docker Containers
This setup uses the following containers declared in a docker compose file
- Nextcloud app:
- nextcloud:apache - main Nextcloud application
- postgres:alpine - PostgreSQL database for Nextcloud
- redis:alpine - Redis caching for Nextcloud
- Backends for Nextcloud plugins:
- collabora/code - collaborative document editing backend for Nextcloud
- aio-talk - nextcloud talk backend application
- httpd - Apache reverse proxy to expose nextcloud, collabora, nextcloud-talk applications
- paulczar/omgwtfssl - Self-signed certificates generation for local domains of nextcloud, collabora, nextcloud talk applications
Configure Nextcloud container
Apps in Nextcloud
- Apps extend the functionality of a Nextcloud installation (like plugins)
- The following additional apps are installed our nextcloud installation
- richdocuments - enables nextcloud office collaborative document editing features (word, spreadsheets, slides)
- spreed - enables nextcloud talk for audio/video conferencing and chats
Install and configure Nextcloud apps with occ commands
- Nextcloud occ (OwnCloud Console) is the built-in command-line interface to manage and administer the Nextcloud installation
- The following occ commands are run in the nextcloud server to install and configure apps and features to use external real-time document editing and audio/video messaging containers
# # set default app to dashboard
# php occ config:system:set defaultapp --value=dashboard
# rely on system cron to update nextcloud periodically
php occ background:cron
# install nextcloud office app
php occ app:install richdocuments
# install nextcloud talk app
php occ app:install spreed
# install nextcloud drawio app
php occ app:install drawio
# # install nextcloud built in code server instead of a separate collabora online server
# php -d memory_limit=512M occ app:install richdocumentscode
# occ commands for collabora/code server configurations in nextcloud - https://github.com/nextcloud/richdocuments/blob/main/docs/install.md#configure-the-app-from-the-commandline
# set collabora online server URL
php occ config:app:set richdocuments wopi_url --value="https://$COLLABORA_FQDN"
# Disable SSL certificate verification (use only for testing!)
[ "$SKIP_CERT_VERIFY" = "true" ] && export disable_cert_verification="yes" || export disable_cert_verification="no"
php occ config:app:set richdocuments disable_certificate_verification --value="$disable_cert_verification"
# occ commands for nextcloud talk server configuration in nextcloud - https://nextcloud-talk.readthedocs.io/en/latest/occ/#talksignalingadd
# add high performance backend (signaling server) for nextcloud talk
php occ talk:signaling:add "https://${SIGNAL_FQDN}" "${SIGNALING_SECRET}"
# add stun server for nextcloud talk
php occ talk:stun:add "${SIGNAL_FQDN}:3478"
# remove default stun server
php occ talk:stun:delete "stun.nextcloud.com:443"
# configure turn server for nextcloud talk
php occ talk:turn:add "turn" "${SIGNAL_FQDN}:3478" "udp,tcp" --secret="${TURN_SECRET}"
Setup Nextcloud to run behind Reverse Proxy with SSL termination
- An apache reverse proxy is used to expose nextcloud, collabora/code and aio-talk conatainers to the clients instead of directly exposing the containers.
- The reverse proxy also handles SSL termination, so SSL certificates need not be configured in the application containers.
- The following occ commands are run in the nextcloud server to declare that a reverse proxy is running to expose nextcloud application with SSL termination. Please note that the reverse proxy’s network IP address is dynamically derived using its docker container name
# 1. Enforce HTTPS for all generated Nextcloud absolute URLs
php occ config:system:set overwriteprotocol --value="https"
# 2. Dynamically fetch the "proxy" container IP and append it safely to trusted_proxies
proxy_ip=$(getent hosts proxy | awk '{print $1}')
php occ config:system:set trusted_proxies 0 --value="$proxy_ip"
php occ config:system:set trusted_proxies 1 --value="127.0.0.1"
php occ config:system:set trusted_proxies 2 --value="app"
# 3. Lock down the public-facing domain name
php occ config:system:set overwritehost --value="$NEXTCLOUD_FQDN"
# 4. Ensure background cron jobs generate correct URLs in emails/notifications
php occ config:system:set overwrite.cli.url --value="https://$NEXTCLOUD_FQDN"
# # config.php location in nextcloud container is /var/www/html/config/config.php. Check here if the values are set correctly
Run shell scripts just after installation in Nextcloud
- Nextcloud runs any scripts present in the
/docker-entrypoint-hooks.d/post-installationfolder of the container. Hence the folder containing required occ commands to install and configure required applications is mounted at the container’s/docker-entrypoint-hooks.d/post-installationfolder location - If the post-installation scripts could not run correctly due to some reason, they can be run again using the following scripts
docker exec -u www-data -i app sh < .\nextcloud\appHooks\post-installation\00_indicate_rev_proxy_https.sh
docker exec -u www-data -i app sh < .\nextcloud\appHooks\post-installation\01_install_apps.sh
To run scripts from Linux based workstations, use the following commands instead
docker exec -u www-data -i app sh < ./nextcloud/appHooks/post-installation/00_indicate_rev_proxy_https.sh
docker exec -u www-data -i app sh < ./nextcloud/appHooks/post-installation/01_install_apps.sh
Reverse proxy container setup
Reverse proxy virtual host for nextcloud
# nextcloud reverse proxy apache configuration
Listen 443
# SSL Cipher Suite:
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES
# SSL Protocol support:
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder off
SSLSessionTickets off
# enable ssl stapling if you are using a valid certificate from a trusted CA and have OCSP support enabled on the CA side
SSLUseStapling Off
# SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
# Pass Phrase Dialog:
SSLPassPhraseDialog builtin
# Inter-Process Session Cache:
#SSLSessionCache "dbm:${SRVROOT}/logs/ssl_scache"
SSLSessionCache "shmcb:logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300
# Prevent timeout limits on heavy processing paths like /login
ProxyTimeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
<VirtualHost _default_:443>
ServerName ${NEXTCLOUD_FQDN}
# ServerAdmin admin@example.com
# Logging
ErrorLog "logs/nextcloud-error.log"
CustomLog "logs/nextcloud-access.log" combined
# SSL Configuration
SSLEngine on
SSLCertificateFile "conf/certs/${NEXTCLOUD_FQDN}.crt"
SSLCertificateKeyFile "conf/certs/${NEXTCLOUD_FQDN}.key"
# Security Headers
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
# Nextcloud Discovery Redirects
# <IfModule mod_rewrite.c>
# RewriteEngine on
# RewriteRule ^/.well-known/carddav https://%{SERVER_NAME}/remote.php/dav [R=301,L]
# RewriteRule ^/.well-known/caldav https://%{SERVER_NAME}/remote.php/dav [R=301,L]
# </IfModule>
Redirect 301 /.well-known/carddav /remote.php/dav
Redirect 301 /.well-known/caldav /remote.php/dav
Redirect 301 /.well-known/webfinger /index.php/.well-known/webfinger
Redirect 301 /.well-known/nodeinfo /index.php/.well-known/nodeinfo
# Proxy Core Settings
ProxyRequests Off
ProxyPreserveHost On
ProxyAddHeaders On
# Real IP Forwarding Headers
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
# WebSocket Support Mapping (Required for Real-time Push and Nextcloud Talk)
ProxyPassMatch ^/(.*)/ws$ ws://app/$1/ws
# Main Reverse Proxy Pass
# ProxyPassReverse intercepts and rewrites the "Location" header during redirects
ProxyPass / http://app/
ProxyPassReverse / http://app/
# SSLProxyEngine On
# SSLProxyCheckPeerCN on
# SSLProxyCheckPeerExpire on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
</VirtualHost>
# see the logs in container at /usr/local/apache2/logs/ folder
Reverse proxy virtual host for collabora/code
########################################
# Reverse proxy for Collabora Online
########################################
<VirtualHost _default_:443>
AllowEncodedSlashes NoDecode
ServerName ${COLLABORA_FQDN}:443
# ServerAdmin admin@example.com
# Logging
ErrorLog "logs/errorCollabora.log"
TransferLog "logs/accessCollabora.log"
# SSL configuration
SSLProxyEngine On
SSLCertificateFile "conf/certs/${COLLABORA_FQDN}.crt"
SSLCertificateKeyFile "conf/certs/${COLLABORA_FQDN}.key"
# Security Headers
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
# Proxy core settings
ProxyPreserveHost On
ProxyRequests Off
ProxyAddHeaders On
# static html, js, images, etc. served from coolwsd
# browser is the client part of Collabora Online
ProxyPass /browser http://collabora:9980/browser retry=0
ProxyPassReverse /browser http://collabora:9980/browser
# WOPI discovery URL
ProxyPass /hosting/discovery http://collabora:9980/hosting/discovery retry=0
ProxyPassReverse /hosting/discovery http://collabora:9980/hosting/discovery
# Capabilities
ProxyPass /hosting/capabilities http://collabora:9980/hosting/capabilities retry=0
ProxyPassReverse /hosting/capabilities http://collabora:9980/hosting/capabilities
# Main websocket
ProxyPassMatch "/cool/(.*)/ws$" ws://collabora:9980/cool/$1/ws nocanon
# Admin Console websocket
ProxyPass /cool/adminws ws://collabora:9980/cool/adminws
# Download as, Fullscreen presentation and Image upload operations
ProxyPass /cool http://collabora:9980/cool
ProxyPassReverse /cool http://collabora:9980/cool
# Compatibility with integrations that use the /lool/convert-to endpoint
ProxyPass /lool http://collabora:9980/cool
ProxyPassReverse /lool http://collabora:9980/cool
SSLProxyVerify None
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
</VirtualHost>
Reverse proxy virtual host for aio-talk
<VirtualHost _default_:443>
AllowEncodedSlashes NoDecode
SSLProxyEngine On
ProxyPreserveHost On
ServerName ${SIGNAL_FQDN}:443
# ServerAdmin admin@example.com
# Logging
ErrorLog "logs/talk-error.log"
TransferLog "logs/talk-access.log"
# SSL Configuration
SSLEngine on
SSLCertificateFile "conf/certs/${SIGNAL_FQDN}.crt"
SSLCertificateKeyFile "conf/certs/${SIGNAL_FQDN}.key"
# Security Headers
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
# Proxy Core Settings
ProxyRequests Off
ProxyPreserveHost On
ProxyAddHeaders On
RewriteEngine On
# Real IP Forwarding Headers
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
ProxyPass / http://talk_hpb:8081/ upgrade=websocket
# SSLProxyEngine On
# SSLProxyCheckPeerCN on
# SSLProxyCheckPeerExpire on
SSLProxyVerify None
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
</VirtualHost>
Nextcloud proxy apache dockerfile
- The reverse proxy container exposes nextcloud, collabora and nextcloud talk container services to the internet
- The docker file below adds required files (virtual host config files) and modifications to httpd image (enabling required modules)
FROM httpd:alpine
COPY --chmod=664 nextcloud.conf /usr/local/apache2/conf/nextcloud.conf
COPY --chmod=664 collabora.conf /usr/local/apache2/conf/collabora.conf
COPY --chmod=664 signal.conf /usr/local/apache2/conf/signal.conf
COPY --chmod=664 self_signed/true.conf /usr/local/apache2/conf/extra/self_signed/true.conf
COPY --chmod=664 self_signed/false.conf /usr/local/apache2/conf/extra/self_signed/false.conf
RUN set -ex; \
sed -i \
-e '/^Listen /d' \
-e 's/^#\(LoadModule .*mod_proxy.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_proxy_http.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_ssl.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_headers.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_proxy_wstunnel.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_socache_shmcb.so\)/\1/' \
/usr/local/apache2/conf/httpd.conf; \
echo "Include conf/nextcloud.conf" | tee -a /usr/local/apache2/conf/httpd.conf; \
echo "Include conf/collabora.conf" | tee -a /usr/local/apache2/conf/httpd.conf; \
echo "Include conf/signal.conf" | tee -a /usr/local/apache2/conf/httpd.conf;
Nextcloud Docker compose setup with required containers
services:
# Postgres DB for nextcloud. Reference: https://hub.docker.com/_/postgres
db:
# Note: Check the recommend version here: https://docs.nextcloud.com/server/latest/admin_manual/installation/system_requirements.html#server
image: postgres:alpine
container_name: db
restart: always
volumes:
- db:/var/lib/postgresql:Z
env_file:
- db.env
# Redis for nextcloud. Reference - https://hub.docker.com/_/redis
redis:
image: redis:alpine
container_name: redis
restart: always
# main nextcloud app container. Reference - https://hub.docker.com/_/nextcloud
app:
image: nextcloud:apache
container_name: app
hostname: app
restart: always
ports:
- 8080:80
volumes:
# NOTE: The `volumes` config of the `cron` and `app` containers must match
- nextcloud:/var/www/html:z
- ./nextcloud/appHooks/post-installation:/docker-entrypoint-hooks.d/post-installation
# - /nas:/nas
# - ./nextcloud/appHooks/before-starting:/docker-entrypoint-hooks.d/before-starting
environment:
POSTGRES_HOST: db
REDIS_HOST: redis
NEXTCLOUD_TRUSTED_DOMAINS: "${NEXTCLOUD_FQDN} app 127.0.0.1"
NEXTCLOUD_ADMIN_USER: ${NEXTCLOUD_UNAME}
NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_PWD}
NEXTCLOUD_FQDN: ${NEXTCLOUD_FQDN}
COLLABORA_FQDN: ${COLLABORA_FQDN}
SIGNAL_FQDN: ${SIGNAL_FQDN}
SIGNALING_SECRET: ${SIGNALING_SECRET}
SKIP_CERT_VERIFY: ${SKIP_CERT_VERIFY} # true for local self-signed certs; false for CA-issued valid SSL certificates
TURN_SECRET: ${TURN_SECRET}
env_file:
- db.env
depends_on:
- db
- redis
- proxy
networks:
- default
- proxy-tier
# Apache reverse-proxy to expose nextcloud to the clients. Reference: https://hub.docker.com/_/httpd
proxy:
build: ./proxy
restart: always
container_name: proxy
hostname: proxy
ports:
- 443:443
volumes:
- ./certs:/usr/local/apache2/conf/certs:ro,z
networks:
proxy-tier:
aliases:
- ${NEXTCLOUD_FQDN}
- ${COLLABORA_FQDN}
- ${SIGNAL_FQDN}
environment:
NEXTCLOUD_FQDN: ${NEXTCLOUD_FQDN}
COLLABORA_FQDN: ${COLLABORA_FQDN}
SIGNAL_FQDN: ${SIGNAL_FQDN}
# keep this false when moving to CA-issued valid SSL certificates
SKIP_CERT_VERIFY: ${SKIP_CERT_VERIFY}
# Collabora online server for nextcloud to enable document processing. Reference: https://hub.docker.com/r/collabora/code
# https://cloud.thesysadminhub.com/s/FNKyP43y35HGDTJ?dir=/
# https://docs.nextcloud.com/server/28/admin_manual/office/example-docker.html#install-the-collabora-online-server
collabora:
image: collabora/code:latest
hostname: collabora
container_name: collabora
restart: unless-stopped
environment:
domain: ${COLLABORA_FQDN}
dictionaries: en
username: ${COLLABORA_UNAME}
password: ${COLLABORA_PWD}
aliasgroup1: https://${NEXTCLOUD_FQDN}:443
extra_params: "--o:ssl.enable=false --o:ssl.termination=true"
# keep this false when moving to CA-issued valid SSL certificates
SKIP_CERT_VERIFY: ${SKIP_CERT_VERIFY}
cap_add:
- MKNOD
ports:
- 127.0.0.1:9980:9980
networks:
- default
- proxy-tier
# nextcloud talk server for nextcloud to enable audio/video calls. Reference: https://hub.docker.com/r/nextcloud/aio-talk
nc-talk:
container_name: talk_hpb
image: ghcr.io/nextcloud-releases/aio-talk:latest
init: true
ports:
- 3478:3478/tcp
- 3478:3478/udp
- 8081:8081/tcp
environment:
- NC_DOMAIN=${NEXTCLOUD_FQDN}
- TALK_HOST=${SIGNAL_FQDN}
- TURN_SECRET=${TURN_SECRET} #this must be a long secretpasswordkey
- SIGNALING_SECRET=${SIGNALING_SECRET} #this must be a long secretpasswordkey
- TZ=${TIME_ZONE}
- TALK_PORT=3478
- INTERNAL_SECRET=${INTERNAL_SECRET} #this must be a long secretpasswordkey
- SKIP_CERT_VERIFY=${SKIP_CERT_VERIFY} # true for local self-signed certs; false for CA-issued valid SSL certificates
restart: unless-stopped
networks:
- default
- proxy-tier
volumes:
db:
nextcloud:
networks:
proxy-tier:
Nextcloud Admin settings
Nextcloud office admin settings
- Nextcloud office settings can be found at the settings/admin/richdocuments URL or Administration settings(top right)→Administration(left menu section)→Office menu in the web UI
- Validate that configurations made the post installation script in this UI

Nextcloud talk admin settings
- Nextcloud talk settings can be foound at the /settings/admin/talk URL or Administration settings(top right)→Administration(left menu section)→Talk menu in the web UI
- Validate that configurations made the post installation script in this UI



Nextcloud Cron job setup
- Nextcloud required a cron job to run every 5 mins.
- One way to run the cron job is to run the command
app php /var/www/html/cron.php - We can configure a Linux cron job to run this command every 5 mins as shown below
sudo crontab -e
*/5 * * * * docker exec -u www-data app php /var/www/html/cron.php
- A task scheduler task can also be run in windows similarly to run the cron job periodically

- Nextcloud needs to be configured as shown above to “Cron” mode either in UI or by running the command
php occ background:cron. This command can be run inside the nextcloud Docker container using the command
docker exec -u www-data app php occ background:cron
Self-signed certificate
- This docker setup uses a flag that specifies if we are using self-signed certificates for this nextcloud installation
- Use
SKIP_CERT_VERIFY=falseif the Nextcloud setup uses CA verified ssl certificates instead of self-signed certificates - When using self-signed certificate, make sure u trust these certificates in your browser by opening the URLs in browser manually (like https://nextcloud.local, https://collabora.local, https://signal.local) or using a group policy to manually add these self-signed certificates in the host machine
References
- Nextcloud docker container - https://github.com/nextcloud/docker
- Nextcloud docker setup github repo - https://github.com/nagasudhirpulla/nextcloud_docker_setup
Comments
Post a Comment