Setup Nextcloud 29 for private photo/video storage and sharing using Ubuntu and docker compose on Intel NUC minipc
Hardware
Intel(R) Client Systems NUC10i7FNK (6 core i7-10710U, 64GB, 4TB nvme) + Ubuntu 24.04 noble
Prepare folders and scripts
mkdir -p /docker/nextcloud/var/www/html mkdir -p /docker/mariadb/var/lib/mysql vi nextcloud.yml vi ./nextcloud_update.sh chmod +x ./nextcloud_update.sh ./nextcloud_update.sh
Update scriptÂ
./nextcloud_update.sh
nextcloud_update.sh
#!/bin/bash docker compose -f nextcloud.yml ps docker compose -f nextcloud.yml down ; docker compose -f nextcloud.yml up -d --build --force-recreate; docker compose -f nextcloud.yml ps docker compose -f nextcloud.yml logs --follow
docker compose file
nextcloud.yml
docker-compose.yml
services: db: image: mariadb:10.11.7 container_name: cloud-db restart: always command: --transaction-isolation=READ-COMMITTED --log-bin=mysqld-bin --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed volumes: - /docker/mariadb/var/lib/mysql:/var/lib/mysql:rw - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - type: tmpfs target: /tmp environment: - MYSQL_ROOT_PASSWORD=db_admin_pass - MYSQL_PASSWORD=db_user_pass - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MARIADB_AUTO_UPGRADE=yes - REDIS_HOST=redis - REDIS_PORT=6379 redis: image: redis:alpine container_name: cloud-cache restart: always app: image: nextcloud:29.0.1 container_name: cloud-server hostname: cloud.example.com restart: always ports: - 8880:80 links: - db - redis volumes: - /docker/nextcloud/var/www/html:/var/www/html:rw - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - type: tmpfs target: /tmp:exec devices: - /dev/dri:/dev/dri environment: - MYSQL_PASSWORD=db_user_pass - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_HOST=db - OVERWRITEHOST=cloud.example.com - OVERWRITEPROTOCOL=https - NEXTCLOUD_ADMIN_USER=nc_admin_user - NEXTCLOUD_ADMIN_PASSWORD=nc_admin_pass - NEXTCLOUD_UPLOAD_LIMIT=20G - PHP_UPLOAD_LIMIT=32G - PHP_MEMORY_LIMIT=32G - APACHE_BODY_LIMIT=0
nginx configuration
server { listen 80; server_name cloud.example.com; return 301 https://$server_name$request_uri; location / { } } server { listen 443 ssl; http2 on; server_name cloud.example.com; add_header Strict-Transport-Security 'max-age=15552000; includeSubDomains'; ssl_certificate /etc/ssl/private/cloud-example-com.pem; ssl_certificate_key /etc/ssl/private/cloud-example-com.pem; ssl_trusted_certificate "/etc/ssl/certs/cloud-example-com.ca"; client_max_body_size 36G; client_body_timeout 800s; ssl_protocols TLSv1.3 TLSv1.2; ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA HIGH !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"; ssl_session_cache shared:SSL:20m; ssl_session_timeout 1h; ssl_prefer_server_ciphers on; ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 8.8.4.4 valid=300s; resolver_timeout 5s; 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; } location /.well-known/pki-validation { try_files $uri $uri/ =404; } return 301 /index.php$request_uri; } location = /robots.txt { allow all; log_not_found off; access_log off; } location / { add_header X-protocol $server_protocol always; include /etc/nginx/mime.types; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://10.0.0.2:8880; } location /s/blank.mp4 { return 501 'NO FILE'; } }
add plugins
- https://apps.nextcloud.com/apps/memories
- https://apps.nextcloud.com/apps/recognize or https://apps.nextcloud.com/apps/facerecognition
- https://apps.nextcloud.com/apps/previewgenerator
- https://apps.nextcloud.com/apps/workflow_media_converter
Tuning
that have to be done every container version update
To get in nextcloud container
docker exec -it cloud-server bash
Prepare mirrors list for apt
apt update apt install lsb-release
UA mirrors example
cat <<EOF >/etc/apt/sources.list deb http://debian.volia.net/debian $(lsb_release -sc) main contrib non-free deb-src http://debian.volia.net/debian $(lsb_release -sc) main contrib non-free deb http://mirror.mirohost.net/debian-security $(lsb_release -sc)-security main contrib non-free non-free-firmware deb-src http://mirror.mirohost.net/debian-security $(lsb_release -sc)-security main contrib non-free deb http://debian.netforce.hosting/debian $(lsb_release -sc)-updates main contrib non-free non-free-firmware deb-src http://debian.netforce.hosting/debian $(lsb_release -sc)-updates main contrib non-free EOF
use ffmpeg 6
cat <<EOF >>/etc/apt/sources.list deb http://debian.ids-services.de/debian-multimedia/ $(lsb_release -sc) main deb-src http://debian.ids-services.de/debian-multimedia/ $(lsb_release -sc) main EOF apt update -oAcquire::AllowInsecureRepositories=true apt install -y --allow-unauthenticated deb-multimedia-keyring
apt update apt install -y --allow-unauthenticated sudo vim git wget exiftool vainfo intel-media-va-driver-non-free ffmpeg # add HW media conversion support (for Intel graphics) groupadd -g 109 render usermod -a -G video www-data usermod -a -G render www-data
install some tools and compile ImageMagick
# Compile latest ImageMagick apt install -y build-essential autoconf libtool apt build-dep -y imagemagick libmagickcore-dev libde265 libheif cd /usr/src/ git clone https://github.com/strukturag/libde265.git git clone https://github.com/strukturag/libheif.git cd libde265/ ./autogen.sh ./configure make -j 6 make install cd /usr/src/libheif/ ./autogen.sh ./configure make -j 6 make install cd /usr/src/ #wget https://www.imagemagick.org/download/ImageMagick.tar.gz #wget https://imagemagick.org/download/ImageMagick.tar.gz #wget https://imagemagick.org/archive/ImageMagick.tar.gz wget https://download.imagemagick.org/archive/ImageMagick.tar.gz tar xf ImageMagick.tar.gz cd ImageMagick-7* ./configure --with-heic=yes make -j 6 make install ldconfig
Optional switch back from ffmpeg 6.0.1 to 5.1.4
apt-cache policy ffmpeg apt remove ffmpeg apt install ffmpeg=7:5.1.4-0+deb12u1
compile php-imagick
cd /usr/src/ wget http://pecl.php.net/get/imagick-3.7.0.tgz tar -xvzf imagick-3.7.0.tgz cd imagick-3.7.0/ phpize ./configure make -j 6 make install
set new limits and restart apache
echo "LimitRequestBody 0" > /etc/apache2/conf-enabled/apache-limits.conf sed -i '/memory_limit/d' /usr/local/etc/php/conf.d/nextcloud.ini sed -i '/upload_max_filesize/d' /usr/local/etc/php/conf.d/nextcloud.ini sed -i '/post_max_size/d' /usr/local/etc/php/conf.d/nextcloud.ini echo "memory_limit=48G" >>/usr/local/etc/php/conf.d/nextcloud.ini echo "upload_max_filesize=32G" >>/usr/local/etc/php/conf.d/nextcloud.ini echo "post_max_size=32G" >>/usr/local/etc/php/conf.d/nextcloud.ini service apache2 reload
use recognize
sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:remove facerecognition" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:install recognize" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ recognize:download-models"
use facerecognition
sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:remove recognize" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:install facerecognition" docker-php-ext-configure bz2 docker-php-ext-install bz2 apt install -y libavdevice-dev libavfilter-dev libavformat-dev apt install -y libavcodec-dev libswresample-dev libswscale-dev apt install -y libavutil-dev cd /usr/src/ git clone https://github.com/davisking/dlib.git cd dlib/dlib mkdir build cd build cmake -DBUILD_SHARED_LIBS=ON .. make sudo make install cd /usr/src/ git clone https://github.com/goodspb/pdlib.git cd pdlib phpize ./configure --enable-debug # you may need to indicate the dlib install location # PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --enable-debug make sudo make install echo "extension=pdlib.so" > /usr/local/etc/php/conf.d/docker-php-ext-pdlib.ini cd /var/www/html/ sudo -u www-data /bin/bash -c "./occ config:app:set facerecognition max_image_area --value 786432" sudo -u www-data /bin/bash -c "./occ config:app:set facerecognition min_image_size --value 128" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ face:setup -M 32G -m 1" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ face:setup -M 32G -m 4" sudo -u www-data /bin/bash -c "./occ face:background_job -t 900"
Cleanup build directory
cd /usr/src/ rm ImageMagick.tar.gz rm imagick-*.tgz rm -Rf ImageMagick-* rm -Rf imagick-*
Crontab
on host system
*/5 * * * * /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=10G /usr/local/bin/php -f /var/www/html/cron.php"
Check installations
Check php-imagick
php -r 'phpinfo();' |grep ImageMagick
Check ImageMagick
convert -version
Check Intel graphics codec support
vainfo
Check ffmpeg
ffmpeg -codecs |grep -e 265 -e 264
Check logs
docker compose -f nextcloud.yml logs --follow
Nextcloud cli commands
see https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/occ_command.html
from host system (examples)
/usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ status" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ config:system:get version" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "NC_debug=true PHP_MEMORY_LIMIT=512M ./occ app:list" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:remove recognize" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:install memories" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:install previewgenerator" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:install workflow_media_converter" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ app:update --all" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ db:add-missing-indices -vvv" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ maintenance:repair" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ maintenance:mode --on" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ maintenance:mode --off" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=512M ./occ trashbin:cleanup --all-users" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ files:scan --all --generate-metadata --no-interaction -vvv" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ preview:generate-all -vvv" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ memories:index" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ memories:index --force"
cli for recognize
/usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ recognize:cluster-faces" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ recognize:classify"
cli for facerecognition
/usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "./occ face:reset --all" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "./occ face:stats" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "./occ face:progress" /usr/bin/docker exec cloud-server sudo -u www-data /bin/bash -c "./occ face:background_job -t 900"
from inside the container (examples)
sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=2G ./occ preview:generate-all -vvv" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=10G /usr/local/bin/php -f /var/www/html/occ memories:index" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=10G /usr/local/bin/php -f /var/www/html/occ recognize:cluster-faces" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=10G /usr/local/bin/php -f /var/www/html/occ recognize:classify" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=2G ./occ recognize:download-models" sudo -u www-data /bin/bash -c "PHP_MEMORY_LIMIT=32G ./occ memories:index --force"
clear files locks in Redis
/usr/bin/docker exec cloud-cache redis-cli flushall
Previous Nextcloud related articles
Batch convert using workflow_media_converter example
mariadb upgrade docker 10.6.8 10.10.2
nextcloud cli commands examples
video encoding HW acceleration for nextcloud in docker