Table of Contents

Nextcloud™


Required packages

sudo apt install php8.x php8.x-common php8.x-gmp php8.x-mbstring php8.x-readline php8.x-xmlrpc php8.x-bcmath php8.x-curl php8.x-igbinary php8.x-mcrypt php8.x-redis php8.x-zip php8.x-bz2 php8.x-fpm php8.x-imagick php8.x-mysql php8.x-soap php8.x-cli php8.x-gd php8.x-intl php8.x-opcache php8.x-xml    

Optimized PHP Configuration

Key PHP Settings

PHP settings are typically found in php.ini/etc/php/8.x/fpm/php.ini

memory_limit = 512M
; Minimum recommended by Nextcloud; increase to 1G+ for heavy usage or large files.
 
upload_max_filesize = 2G
; Set to match your largest expected file size (e.g., 2G for 2 GB).
 
post_max_size = 2G
; Should match or exceed upload_max_filesize.
 
max_execution_time = 300
; Increase for long-running tasks like file uploads or cron jobs (300 seconds = 5 minutes).
 
date.timezone = America/New_York
; Set to your server's timezone to avoid warnings.
 
output_buffering = Off
; Nextcloud recommends disabling this to avoid issues with certain operations.

OPcache Settings (Performance Boost)

OPcache caches precompiled PHP bytecode, significantly speeding up Nextcloud. Add these to php.ini or a separate file like /etc/php/8.x/fpm/conf.d/10-opcache.ini

opcache.enable = 1
; Enable OPcache.
 
opcache.memory_consumption = 128
; Memory for cached scripts (128 MB is a good starting point; increase to 256 MB if RAM allows).
 
opcache.interned_strings_buffer = 8
; Memory for string interning (8 MB is sufficient for most cases).
 
opcache.max_accelerated_files = 10000
; Max number of files to cache; adjust based on Nextcloud’s file count.
 
opcache.revalidate_freq = 60
; How often to check for file changes (60 seconds balances performance and freshness).
 
opcache.save_comments = 1
; Required by Nextcloud to preserve code comments in bytecode.
 
opcache.enable_cli = 0
; Disable for CLI to avoid unnecessary overhead in cron jobs.

Optional: JIT (PHP 8.0+)

For CPU-intensive tasks (e.g., image processing), enable the JIT compiler:

opcache.jit_buffer_size = 100M
opcache.jit = tracing
; "tracing" mode offers the best performance for web apps like Nextcloud.

Enable JIT in Opcache

Edit /etc/php/8.x/fpm/conf.d/10-opcache.ini

; configuration for php opcache module
; priority=10
zend_extension=opcache.so
opcache.enable_cli=1
opcache.jit_buffer_size=100M
opcache.jit=tracing

Check JIT is enabled

sudo php -i | grep -q 'opcache.jit_buffer_size => [^0]' && echo "JIT is enabled" || echo "JIT is disabled" 

Optimized PHP-FPM Configuration

PHP-FPM settings are typically in a pool configuration file like /etc/php/8.1/fpm/pool.d/www.conf. The default settings are often too conservative for Nextcloud, leading to slow response times or errors under load.

Process Manager Settings

pm = dynamic
; "dynamic" adjusts the number of child processes based on load; use "static" for dedicated servers with predictable traffic.
 
pm.max_children = 120
; Max number of child processes; calculate as (Total RAM - 1G for OS/other services) / 50-100 MB per process.
; Example: 4 GB RAM → ~60-80 children; 8 GB RAM → ~120-150 children.
 
pm.start_servers = 12
; Initial processes; set to ~10-20% of max_children.
 
pm.min_spare_servers = 6
; Minimum idle processes; set to ~5-10% of max_children.
 
pm.max_spare_servers = 18
; Maximum idle processes; set to ~15-25% of max_children.
 
pm.max_requests = 500
; Restart child processes after this many requests to prevent memory leaks.

Tuning Tips


Additional PHP-FPM Settings

request_terminate_timeout = 300
; Match max_execution_time to handle long uploads gracefully.
 
process.priority = -19
; Optional: Boost priority (requires root and SYS_NICE capability).

Nextcloud-Specific Tweaks

Referral manuals — by Nextcloud Documentation

'memcache.local' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
    'host' => 'localhost',
    'port' => 6379,
],
 
  <?php
$CONFIG = array (
... ... ... 
...
),
'memcache.local' => '\\OC\\Memcache\\Redis',
'filelocking.enabled' => 'true',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' =>
array (
'host' => 'localhost',
'port' => 6379,
'timeout' => 0,
'dbindex' => 0,
),
); 

Install Redis (sudo apt install redis-server on Debian) and ensure it’s running.

sudo apt install redis-server php-redis
sudo ps ax | grep redis
sudo netstat -tlnp | grep redis

Clearing Redis Cache

sudo redis-cli
  SELECT <dbIndex>
  FLUSHDB
*/5 * * * * www-data php -f /var/www/nextcloud/cron.php

Validation


Scaling Adjustments

This configuration provides a solid starting point for Nextcloud, balancing performance and resource efficiency. Fine-tune based on your server’s actual usage patterns and hardware capabilities.


Solved Problems

mjs configuration error

Error description

Your webserver does not serve `.mjs` files using the JavaScript MIME type. This will break some apps by preventing browsers from executing the JavaScript files. You should configure your webserver to serve `.mjs` files with either the `text/javascript` or `application/javascript` MIME type.

Solution

Edit /etc/nginx/mime.types

   application/javascript                           js mjs;

Remove configuration in nginx conf

#    include mime.types;
#    types {
#        text/javascript js mjs;
#    }

PHP imagick module

Error description

The PHP module “imagick” in this instance has no SVG support

Solution

Install php-imagick moduel with associated packages

sudo apt install php-imagick imagemagick

Incorrect row format found

Error description

Incorrect row format found in your database. ROW_FORMAT=Dynamic offers the best database performances for Nextcloud. Please update row format on the following list: …

Solution

Create the script and run with root permission with following:

#!/bin/bash
 
# Prompt for database credentials
read -p "Enter Database Name: " DB_NAME
read -p "Enter Username: " DB_USER
read -s -p "Enter Password: " DB_PASS
echo
 
# Execute all ALTER TABLE statements in one query
mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -Bse "
SELECT CONCAT('ALTER TABLE \`', TABLE_NAME, '\` ROW_FORMAT=DYNAMIC;') 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_SCHEMA = '$DB_NAME' 
AND ENGINE = 'InnoDB'
" | mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME"