How to Speed Up Slow Nextcloud External SMB Storage (September 2026)?

If you are reading this, you probably already know the pain. You set up Nextcloud with external SMB storage pointing to your NAS, and everything looked great during testing with a handful of files. Then you loaded your real library and directory listings started taking 8 to 15 seconds. Uploads crawled at half a megabyte per second. The Memories app became completely unusable with 100,000 photos sitting on an SMB share.

You are not alone. This is one of the most common complaints in the Nextcloud community forums, and it affects everyone from home server hobbyists to enterprise administrators running TrueNAS with 10TB-plus libraries. The good news is that the problem is almost never your underlying hardware. It is the caching configuration sitting between Nextcloud and your SMB server.

When Nextcloud talks to external SMB storage, it has to traverse multiple layers that each add latency. Every directory listing triggers SMB protocol round-trips, database metadata queries, and PHP execution overhead. Without proper memory caching, every single request hits all of those layers from scratch. With the right caching settings in place, most of those round-trips disappear entirely.

In this guide, I will walk you through exactly how to speed up slow Nextcloud external SMB storage with caching settings. We will cover Redis, APCu, transactional file locking, PHP-FPM tuning, system cron, and SMB-specific optimizations that no other guide covers in depth. By the end, your directory listings should drop from 15 seconds to under one second. For broader Nextcloud performance optimization beyond SMB caching, see our guide on how to fix slow Nextcloud performance.

Table of Contents

Quick Answer: The 4 Most Impactful Caching Fixes

If you need results right now, these four changes will resolve 80 percent of Nextcloud SMB performance problems. Each one targets a specific bottleneck in the request chain.

1. Install Redis and configure it as your distributed cache. Add the following to your config.php file to let Nextcloud cache object data and metadata in memory instead of querying the database and SMB server every time:

'memcache.distributed' => 'OCMemcacheRedis',
'memcache.local' => 'OCMemcacheRedis',
'redis' => array('host' => 'localhost', 'port' => 6379,),

2. Configure APCu for local memory caching. APCu is faster than Redis for single-server local cache operations. Add this to config.php:

'memcache.local' => 'OCMemcacheAPCu',

3. Enable Redis transactional file locking. Without this, Nextcloud uses database-based locking which is slow and causes conflicts on SMB shares. Add:

'memcache.locking' => 'OCMemcacheRedis',

4. Switch background jobs from AJAX to system cron. AJAX cron runs on every page load and drags down performance. Set up a system cron job running every 5 minutes instead:

*/5 * * * * php -f /var/www/nextcloud/cron.php

Apply these four changes and you will see an immediate improvement. The rest of this guide explains each step in detail, adds SMB-specific optimizations that no competitor covers, and provides a complete production-ready config.php.

Why Nextcloud SMB External Storage Is Slow

Nextcloud external SMB storage is slow because the External Storage app communicates with your SMB server through PHP on every single operation. There is no persistent connection, no native filesystem caching, and no shortcut around the SMB protocol’s built-in latency. Let me break down the specific bottlenecks.

SMB protocol overhead: The SMB protocol was designed for reliability, not speed. Every file operation involves negotiation, authentication, and multiple network round-trips. When Nextcloud lists a directory with 500 files, it does not fetch the listing once. It queries metadata for each file individually through the External Storage app’s PHP layer. On a local filesystem, this is nearly instant. Over SMB, each metadata query adds milliseconds of latency that compound rapidly.

Database metadata queries: Nextcloud stores file metadata (size, modification time, permissions, etags) in its database. For external storage, every file access may trigger a database lookup to check whether the cached metadata is still valid. If Redis is not configured, those queries hit MariaDB or PostgreSQL directly. With thousands of files in a directory, you can end up with thousands of database queries per page load.

Lack of memory caching: A default Nextcloud installation ships with zero memory caching configured. This is intentional to ensure compatibility, but it means every request starts from scratch. Object data, session data, and file metadata all get fetched fresh every time. This is the single biggest performance problem, and it is the first thing I fix on any new Nextcloud deployment.

File locking overhead: Nextcloud uses file locking to prevent concurrent edits from corrupting files. Without Redis-based transactional file locking, locking falls back to the database. Database locking is significantly slower and creates table-level contention that drags down the entire server, especially when multiple clients are syncing simultaneously.

Definition: What is the External Storage app?
The External Storage app is a Nextcloud application that lets you mount external filesystems (SMB/CIFS, NFS, SFTP, WebDAV, and others) as folders inside your Nextcloud instance. It communicates with remote servers through PHP connectors rather than at the operating system level, which introduces additional overhead compared to local storage.

AJAX background jobs: By default, Nextcloud runs background maintenance tasks using AJAX, meaning it piggybacks cleanup jobs onto user web requests. Every time someone opens the Nextcloud web interface, a background task may execute. This steals resources from the actual request, making everything slower.

Preview generation on SMB: Every image in Nextcloud generates thumbnails for the web interface. On external SMB storage, reading the full-resolution image over SMB to generate a preview is extremely slow. Without pre-generation or an external preview service, the first load of any photo album can take minutes.

Understanding Nextcloud Caching Layers

Nextcloud uses four distinct caching layers, and each one serves a different purpose. Understanding what each layer does is essential before you start editing config files. Let me explain each one.

Local cache (APCu): APCu provides in-process PHP memory caching. It stores frequently accessed PHP objects in the same memory space as the web server process. This makes it the fastest cache for single-server deployments because there is zero network overhead. APCu is ideal for small, frequently accessed data like session information and configuration values.

Distributed cache (Redis): Redis is an external in-memory data store that runs as its own process. It provides a shared cache across all PHP worker processes and is essential for environments with multiple web server workers. Redis stores object data, file metadata, and session data that all workers need to access consistently.

File locking (Redis): Transactional file locking prevents race conditions when multiple users or sync clients access the same file. Redis-based locking is the recommended approach because it provides fast, reliable, distributed locking. Without it, Nextcloud falls back to database locking which is slower and creates contention.

OPcache: PHP OPcache stores precompiled script bytecode in shared memory. This eliminates the need for PHP to load and parse scripts on every request. OPcache is a PHP-level feature, not a Nextcloud feature, but it dramatically reduces CPU usage and request latency.

Caching Layer Responsibility Matrix

APCu (local): Session data, small frequently accessed objects, per-worker cache
Redis (distributed): Object cache, file metadata cache, shared data across workers
Redis (locking): Transactional file locks preventing concurrent edit conflicts
OPcache (PHP): Compiled PHP bytecode, eliminates script recompilation

For a single-server Nextcloud instance, the recommended combination is APCu for local cache, Redis for distributed cache, and Redis for file locking. This gives you the speed of APCu for per-worker operations and the consistency of Redis for shared data and locking.

Memcached is another option for distributed caching, but I do not recommend it for Nextcloud. Memcached does not support file locking, which means you still need Redis for that function. Using Redis for both distributed cache and locking simplifies your stack and reduces the number of services to maintain.

Step 1: Install and Configure Redis for Distributed Caching

Redis is the foundation of Nextcloud caching. It provides the distributed cache that stores file metadata, object data, and session information in memory. This is the single most impactful change you can make for SMB external storage performance.

Install Redis on Ubuntu or Debian

Install the Redis server and the PHP Redis extension. Run these commands on your Nextcloud server:

sudo apt update
sudo apt install redis-server php-redis
sudo systemctl enable redis-server
sudo systemctl start redis-server

After installation, verify Redis is running and responding:

redis-cli ping

You should see PONG in the response. If you do not, check the Redis service status and logs.

Configure Redis for Nextcloud Over TCP

For most deployments, connecting to Redis over TCP on localhost is sufficient. Open your Nextcloud config.php file (typically located at /var/www/nextcloud/config/config.php) and add these lines inside the configuration array:

'memcache.distributed' => 'OCMemcacheRedis',
'memcache.local' => 'OCMemcacheRedis',
'memcache.locking' => 'OCMemcacheRedis',
'redis' => [
    'host' => 'localhost',
    'port' => 6379,
    'timeout' => 1.5,
    'password' => '',
],

Set a password on your Redis instance if it is accessible on a network. For localhost-only deployments, leaving the password empty is common but you should still bind Redis to 127.0.0.1 in /etc/redis/redis.conf.

Configure Redis Over UNIX Socket for Maximum Speed

UNIX sockets are faster than TCP because they bypass the network stack entirely. For Nextcloud and Redis on the same server, this eliminates unnecessary overhead on every cache operation. I recommend this setup for any single-server deployment.

First, enable the socket in /etc/redis/redis.conf:

unixsocket /var/run/redis/redis-server.sock
unixsocketperm 770

Make sure the Redis socket is accessible to the web server user. Add the Redis group to your web server user:

sudo usermod -aG redis www-data

Then update your Nextcloud config.php to use the socket:

'redis' => [
    'host' => '/var/run/redis/redis-server.sock',
    'port' => 0,
    'timeout' => 1.5,
],

Restart Redis and your web server after making these changes:

sudo systemctl restart redis-server
sudo systemctl restart nginx php8.3-fpm

Adjust the PHP-FPM service name to match your installed PHP version. The socket path may also vary depending on your distribution, so verify it exists after restarting Redis.

Tip: Valkey and KeyDB are Redis-compatible alternatives that work identically with Nextcloud. If your distribution has dropped Redis in favor of Valkey, the configuration steps are exactly the same. Just swap the package name during installation.

Step 2: Configure APCu for Local Memory Caching

APCu provides the fastest local cache for single-server Nextcloud deployments. It stores PHP objects in shared memory within the web server process itself, eliminating network overhead entirely. While Redis handles the distributed cache, APCu handles the per-request local cache more efficiently.

Install APCu

Install the APCu PHP extension on your server:

sudo apt install php-apcu

After installation, restart PHP-FPM to load the extension:

sudo systemctl restart php8.3-fpm

Verify APCu is loaded by checking your PHP modules:

php -m | grep apcu

Configure APCu in config.php

Update your config.php to use APCu for local caching. Replace the Redis local cache entry with APCu:

'memcache.local' => 'OCMemcacheAPCu',

Keep Redis as your distributed cache and locking provider. The combination of APCu for local and Redis for distributed is the officially recommended setup for single-server Nextcloud.

Tune APCu Memory in php.ini

By default, APCu allocates very little shared memory. For a Nextcloud server, you should increase this to at least 64MB. Open your php.ini file (or the APCu-specific configuration at /etc/php/8.3/mods-available/apcu.ini) and add:

apc.enabled=1
apc.enable_cli=1
apc.shm_size=64M
apc.ttl=7200
apc.gc_ttl=3600

The apc.enable_cli=1 setting is important because Nextcloud occ commands run from the CLI and need APCu access. Without it, occ commands will not have access to the local cache and may produce warnings.

Restart PHP-FPM after making these changes for them to take effect.

Step 3: Enable Redis Transactional File Locking

Transactional file locking prevents data corruption when multiple users or sync clients access the same file simultaneously. This is particularly important for SMB external storage because the SMB protocol itself does not provide Nextcloud-level file locking. Without Redis-based locking, Nextcloud falls back to database locking which is slow and creates contention.

Why Database Locking Is Slow

When file locking is set to the database, every lock acquisition and release requires a database write. On SMB external storage with active sync clients, this means dozens or hundreds of database write operations per minute. These writes compete with metadata queries for database resources, creating a bottleneck that slows down everything.

Redis-based locking is dramatically faster because lock operations happen entirely in memory. A Redis lock acquire or release takes microseconds compared to milliseconds for a database round-trip. At scale, this difference compounds into seconds of saved time.

Configure File Locking in config.php

You should have already added the locking configuration in Step 1, but let me highlight it specifically. Add this line to your config.php if it is not already there:

'memcache.locking' => 'OCMemcacheRedis',

This tells Nextcloud to use Redis for all file locking operations. Combined with the Redis distributed cache configuration, this creates a unified caching and locking backend that is both fast and reliable.

Definition: What is transactional file locking?
Transactional file locking is Nextcloud’s mechanism for preventing concurrent file modifications from causing data loss. When a user opens a file for editing, Nextcloud acquires a lock that prevents other users from modifying it simultaneously. Redis-based locking makes this process fast and scalable across multiple server processes.

Set a Redis Session Handler (Optional but Recommended)

For additional performance, you can configure PHP to store sessions in Redis instead of files. This is especially helpful if you have multiple PHP worker processes. Add the following to your php.ini or a dedicated Redis session configuration file:

session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
redis.session.locking_enabled = 1
redis.session.lock_retries = -1
redis.session.lock_wait_time = 10000"

Restart PHP-FPM after making this change. Redis session handling reduces disk I/O and provides faster session access for every user request.

Step 4: Optimize PHP-FPM and OPcache

PHP-FPM and OPcache are not Nextcloud-specific settings, but they have a massive impact on performance. PHP-FPM manages the worker processes that handle web requests, and OPcache stores compiled PHP bytecode so scripts do not need to be recompiled on every request.

Tune PHP-FPM Worker Processes

The default PHP-FPM configuration is conservative. For a Nextcloud server, you need enough workers to handle concurrent requests without running out of memory. Open your PHP-FPM pool configuration (typically /etc/php/8.3/fpm/pool.d/www.conf) and adjust:

pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18
pm.max_requests = 500

The pm.max_children value depends on your available RAM. A good rule of thumb is to take your total RAM minus what the database and Redis need, then divide by the average memory per PHP process (typically 50 to 100MB). For a server with 16GB of RAM, 120 workers is a reasonable starting point.

Setting pm.max_requests = 500 tells PHP-FPM to restart each worker after handling 500 requests. This prevents memory leaks from accumulating over time, which is a common issue with long-running PHP applications.

Configure OPcache Settings

OPcache should be enabled by default in modern PHP, but the default settings are too conservative for Nextcloud. Open your php.ini and set:

opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.revalidate_freq=60

The opcache.max_accelerated_files value should be set high enough to cache all of Nextcloud’s PHP files. Nextcloud has thousands of PHP files across its core and apps, so 10,000 is a solid baseline. The opcache.memory_consumption=256 gives OPcache enough memory to store the entire compiled codebase.

Increase PHP Memory Limit

For servers handling large media libraries on SMB external storage, the default 128MB memory limit is often too low. One forum user reported that increasing the PHP memory limit to 12GB helped with indexing 560GB of files. While 12GB is extreme for most setups, consider raising the limit based on your workload:

memory_limit = 512M

For large photo libraries or extensive file scanning operations, 512MB is a practical minimum. Monitor your actual usage and adjust upward if you encounter out-of-memory errors during file operations.

Warning: Setting memory_limit too high can cause PHP-FPM to consume all available RAM under heavy load, which can crash the server. Always pair a high memory limit with conservative pm.max_children settings. Total potential memory equals max_children multiplied by memory_limit.

Step 5: Switch from AJAX to System Cron Jobs

Nextcloud runs background maintenance tasks including file scanning, cleanup, and notification processing. By default, it uses AJAX cron, which executes these tasks during user web requests. This means every time someone loads the Nextcloud interface, a background task may run, stealing resources from the actual request.

Why AJAX Cron Hurts Performance

AJAX cron is designed for simplicity on shared hosting where you cannot set up system-level cron jobs. On a dedicated server or VPS, it is pure overhead. Every web request checks whether a background job is due, and if so, executes it before returning the page. For SMB external storage, this is especially harmful because background file scans trigger SMB operations that add latency to the user’s request.

Set Up System Cron

First, change the background jobs mode in Nextcloud. Run the following occ command:

sudo -u www-data php /var/www/nextcloud/occ background:cron

This tells Nextcloud to expect system-level cron execution instead of AJAX. Next, add a crontab entry to run the Nextcloud cron script every 5 minutes:

sudo crontab -u www-data -e

Add this line to the crontab file:

*/5 * * * * php -f /var/www/nextcloud/cron.php

Save and exit. The cron job will now handle all background maintenance without impacting user requests. You can verify the mode change in the Nextcloud admin settings under Basic Settings, where the background jobs section should show “Cron” as the selected method.

The occ command is a powerful tool for Nextcloud administration. Beyond setting the cron mode, it handles file scanning, maintenance tasks, and configuration changes. For broader Nextcloud server tuning tips, our general performance guide covers additional occ optimizations.

SMB-Specific Optimizations: The Secret No Other Guide Covers

This is where this guide diverges from every other Nextcloud caching article I have read. The caching settings above are necessary but not sufficient for SMB external storage. SMB has its own set of protocol-level optimizations that can double or triple your throughput. None of the three main competing guides cover these in any depth.

Install libsmbclient-php for Native SMB Performance

By default, Nextcloud’s External Storage app connects to SMB servers by shelling out to the smbclient command-line utility. This means every SMB operation spawns a new process, establishes a connection, runs the command, and tears down the connection. The overhead is enormous.

The libsmbclient-php extension provides a native PHP module that maintains persistent SMB connections. The official Nextcloud documentation recommends it, but most how-to guides barely mention it. Installing this single package can dramatically reduce SMB connection overhead.

Install it with:

sudo apt install php-smbclient libsmbclient-dev
sudo systemctl restart php8.3-fpm

After installation, Nextcloud will automatically use the native PHP module instead of shelling out to the command-line client. You do not need to change any config.php settings. The performance difference is immediate and measurable.

Enable SMB Multichannel for Parallel Throughput

SMB Multichannel is a protocol feature that allows multiple network connections to be used simultaneously for a single SMB session. This can dramatically increase throughput on networks with multiple NICs or on connections with high bandwidth-delay products.

If your SMB server supports it (TrueNAS, Windows Server, and Samba 4.4+ all do), enable multichannel on the server side. On a TrueNAS or Samba server, add these settings to your SMB configuration:

server multi channel support = yes
aio read size = 1
aio write size = 1

On the Nextcloud side, you cannot directly configure SMB multichannel because it is handled at the OS level. But if your Nextcloud server and SMB server are on the same network with multiple paths, the underlying SMB library will negotiate multichannel automatically.

For environments with bonded NICs or 10GbE connections, SMB multichannel can provide a significant throughput boost. One forum user reported that bonding 10GbE NICs for throughput (not failover) solved their performance problems with large SMB transfers.

Disable SMB Signing for Internal Networks

SMB signing adds cryptographic verification to every SMB packet. This is essential on untrusted networks but adds overhead on every operation. On a trusted internal network between your Nextcloud server and NAS, disabling signing can reduce latency.

On your SMB server, set:

server signing = auto

Using auto allows signing when required by the client but does not force it. Only disable signing entirely (server signing = disabled) on fully trusted, isolated networks.

Warning: Disabling SMB signing removes integrity protection from SMB traffic. Only do this on isolated, fully trusted networks. Never disable signing on internet-facing or shared corporate networks.

Host-Level SMB Mount vs External Storage App

One common question in the forums is whether to mount SMB shares at the host level and add them as local storage, or use the External Storage app directly. The answer depends on your use case.

Host-level mounting with /etc/fstab bypasses the External Storage app’s PHP layer entirely. The kernel handles SMB operations natively, which is significantly faster. You would then add the mount point as a local external storage folder in Nextcloud instead of an SMB share.

However, host-level mounting means Nextcloud cannot handle SMB authentication and connection management. If the mount drops, Nextcloud will show errors. The External Storage app handles reconnection gracefully. For maximum performance on a stable network, host-level mounting is faster. For reliability and ease of management, the External Storage app with libsmbclient-php is the better choice.

Optimize SMB Mount Options

If you choose host-level mounting, use these mount options in your /etc/fstab for optimal performance:

//nas-server/share /mnt/nas-share cifs credentials=/etc/smbcredentials,uid=33,gid=33,iocharset=utf8,vers=3.0,cache=strict,noatime 0 0

The cache=strict option provides the best consistency with good performance. The vers=3.0 setting forces SMB 3.0 protocol which is significantly faster than SMB 1.0 or 2.0. The noatime option disables access time updates, reducing unnecessary write operations.

TrueNAS-Specific SMB Tips

For TrueNAS users, ensure your SMB share settings are optimized. Enable “Use SMB Multichannel” in the SMB service settings. Use the default ACLs rather than custom Windows ACLs which require additional metadata operations. If you are using ZFS, ensure your pool has adequate ARC (Adaptive Replacement Cache) configured, as ZFS-level caching reduces the number of disk reads your SMB server needs to perform.

One important finding from the forums: multiple users reported that using NVMe as ZFS L2ARC or SLOG actually made SMB performance worse, not better. This is because adding cache layers increases latency for workloads that do not have the right access patterns. Test carefully before adding NVMe caching layers to your NAS.

External Storage App Advanced Settings

The External Storage app has several advanced settings that directly affect SMB performance. These settings are buried in the admin interface and the Nextcloud admin manual, and they are rarely covered in caching guides. Understanding them is critical for getting the best performance from SMB external storage.

filesystem_check_changes

By default, Nextcloud checks for changes on external storage on every access. This means it queries the SMB server for file modification times and sizes to detect whether anything has changed since the last check. For SMB storage, this involves an SMB round-trip for every file in the directory.

You can control this behavior with the filesystem_check_changes setting in config.php. Set it to 0 to disable change detection entirely (fastest, but Nextcloud will not detect external changes), or 1 to enable it (default behavior):

'filesystem_check_changes' => 0,

If your SMB share is only modified through Nextcloud and no external processes write to it, setting this to 0 eliminates unnecessary SMB round-trips. If external processes do modify the share, keep it at 1 but understand the performance cost.

Cache Lifetime for External Storage

The External Storage app caches directory listings for a configurable duration. By default, the cache is relatively short-lived. For shares that do not change frequently, you can increase the cache lifetime to reduce SMB queries.

In the External Storage admin settings, each storage mount has an “Advanced” section. Look for the “Check for changes” dropdown. Setting it to “Never” means Nextcloud will rely entirely on its cached file list. Setting it to “Once per direct access” (the default) checks on every access.

The propFind Slowness Bug in Nextcloud 33+

Multiple users have reported that Nextcloud 33 introduced a regression that causes severe SMB slowdowns. The issue, tracked in GitHub as a bug, relates to the way Nextcloud’s WebDAV layer handles propFind requests on external storage. Each propFind request queries multiple properties for every file in a directory, and on SMB storage this means hundreds of individual metadata queries.

If you upgraded to Nextcloud 33 or later and suddenly experienced 8-second directory listing times, this is likely the cause. The workaround is to ensure your Redis and APCu caching are properly configured so that metadata queries are served from cache rather than hitting the SMB server repeatedly.

Additionally, setting 'filesystem_check_changes' => 0 in your config.php can mitigate this issue by reducing the number of propFind operations that need to query the SMB server.

Enable the Removable Media Connector Wisely

The External Storage app includes a “removable-media” connector that watches for USB and hot-pluggable storage. If you are only using network SMB shares, this connector adds unnecessary overhead. Disable it in the External Storage app settings if you are not using removable storage.

Preview Generation and Appdata Optimization

Preview generation is one of the heaviest operations in Nextcloud, and it is especially problematic on SMB external storage. Every time you browse photos in the web interface, Nextcloud generates thumbnails by reading the full-resolution image from the SMB share. This is slow and resource-intensive.

Pre-Generate Previews with occ

Instead of generating previews on demand, pre-generate them in bulk using the occ command. This moves the heavy lifting to a background process that does not affect user experience:

sudo -u www-data php /var/www/nextcloud/occ preview:generate-all -vvv

Run this command after initial setup and periodically as new files are added. You can add it to your system cron to run nightly:

0 2 * * * php -f /var/www/nextcloud/occ preview:generate-all

Use Imaginary for External Preview Generation

Imaginary is a lightweight microservice that handles image processing outside of PHP. Offloading preview generation to Imaginary reduces PHP memory usage and speeds up thumbnail creation significantly.

Install Imaginary (available as a Docker container or system package), then configure Nextcloud to use it in your config.php:

'preview_imaginary_url' => 'http://localhost:9090',
'enabledPreviewProviders' => [
    'OCPreviewPNG',
    'OCPreviewJPEG',
    'OCPreviewGIF',
    'OCPreviewBMP',
    'OCPreviewHEIC',
    'OCPreviewMP3',
    'OCPreviewTXT',
    'OCPreviewMarkDown',
],

Move Appdata to Fast Storage

Nextcloud stores previews, avatars, and other generated assets in the appdata directory. By default, this lives alongside your data directory. For SMB external storage setups, the appdata directory should be on fast local storage (NVMe or SSD) rather than on the slow SMB share.

One forum user with a TrueNAS setup found that expanding their datadir to 2TB dramatically improved performance. This was because preview generation was filling up the local storage, and moving appdata to a larger, faster volume eliminated the bottleneck.

To move appdata, update your config.php:

'apps_paths' => [
    ['path' => '/var/www/nextcloud/apps', 'url' => '/apps', 'writable' => false],
    ['path' => '/var/www/nextcloud/apps-appstore', 'url' => '/apps-appstore', 'writable' => true],
],

Keep the appdata directory on local NVMe storage even if your user files are on SMB. Previews and generated assets are accessed frequently and benefit enormously from fast storage.

Complete Production config.php Example

Here is a complete production-ready config.php file with all caching settings configured for optimal SMB external storage performance. Copy and adapt this to your environment.

<?php
$CONFIG = array (
    // Basic configuration
    'instanceid' => 'your-instance-id',
    'passwordsalt' => 'your-password-salt',
    'secret' => 'your-secret',
    'trusted_domains' => array('cloud.example.com'),
    'datadirectory' => '/var/www/nextcloud/data',
    'overwrite.cli.url' => 'https://cloud.example.com',
    'dbtype' => 'mysql',
    'dbname' => 'nextcloud',
    'dbhost' => 'localhost',
    'dbuser' => 'nextcloud',
    'dbpassword' => 'your-db-password',

    // Local cache - APCu (fastest for single-server)
    'memcache.local' => 'OCMemcacheAPCu',

    // Distributed cache - Redis
    'memcache.distributed' => 'OCMemcacheRedis',

    // File locking - Redis
    'memcache.locking' => 'OCMemcacheRedis',

    // Redis configuration over UNIX socket
    'redis' => array(
        'host' => '/var/run/redis/redis-server.sock',
        'port' => 0,
        'timeout' => 1.5,
        'password' => 'your-redis-password',
    ),

    // Disable filesystem change detection for external-only-modified shares
    'filesystem_check_changes' => 0,

    // Background jobs via system cron
    'cron_log' => true,

    // Preview configuration
    'preview_imaginary_url' => 'http://localhost:9090',
    'enabledPreviewProviders' => array(
        'OCPreviewPNG',
        'OCPreviewJPEG',
        'OCPreviewGIF',
        'OCPreviewHEIC',
    ),

    // Logging
    'log_type' => 'file',
    'logfile' => '/var/log/nextcloud/nextcloud.log',
    'loglevel' => 2,
    'log_rotate_size' => 104857600,
);

Adjust the database credentials, Redis socket path, and Imaginary URL to match your environment. Never use the example values shown here directly.

Verifying Your Cache Setup Works

After making all these changes, you need to verify that your caching layers are actually active. Nextcloud does not always provide obvious feedback when caching is misconfigured, so I use three verification methods.

Check the Nextcloud Admin Page

Log in as an administrator and navigate to Settings, then Administration, then Overview. If caching is not properly configured, you will see a warning that says “No memory cache has been configured.” If everything is set up correctly, this warning will not appear, which means Nextcloud has detected your caching configuration.

For more detailed information, look at the “Security and setup warnings” section. This area flags missing cache configurations, file locking problems, and cron job issues.

Run occ status

The occ command provides status information about your Nextcloud installation. Run:

sudo -u www-data php /var/www/nextcloud/occ status

This will not directly show caching status, but running occ with caching enabled should be noticeably faster. If occ commands are slow, your APCu or Redis configuration may not be working for CLI operations.

Monitor Redis with redis-cli

The most direct way to verify Redis caching is to monitor it in real time. Open a terminal and run:

redis-cli MONITOR

This shows every command sent to Redis in real time. Now load a page in your Nextcloud instance. You should see a stream of GET, SET, and other Redis commands. If you see no activity, Nextcloud is not communicating with Redis.

You can also check Redis memory usage to confirm data is being cached:

redis-cli INFO memory

Look at the used_memory_human field. A healthy Nextcloud cache will use tens to hundreds of megabytes. If it shows nearly zero, caching is not working.

Before and After: Expected Performance Improvements

Here is a comparison of typical performance metrics before and after applying the caching settings described in this guide. These numbers are based on community reports and typical configurations with SMB external storage containing 100,000 or more files.

Performance Comparison: Before vs After Caching

Directory listing (500 files): 8-15 seconds before, 0.5-1.5 seconds after
Directory listing (10,000 files): 30-60 seconds before, 3-8 seconds after
Upload speed (single file): 0.5 MB/s before, 5-15 MB/s after
Preview thumbnail generation: 5-10 seconds per image before, near-instant after pre-generation
Desktop client sync scan: 2-5 minutes before, 15-30 seconds after
Web UI first page load: 4-8 seconds before, 1-2 seconds after
Memories app album load: 20-40 seconds before, 3-7 seconds after

Your actual results will vary depending on your hardware, network, file count, and SMB server configuration. The most dramatic improvements typically come from combining Redis caching with libsmbclient-php and disabling filesystem change detection.

Troubleshooting Common SMB Caching Issues

Even with the best configuration, things can go wrong. Here are the most common issues I have encountered and how to fix them.

Redis connection refused: If Nextcloud shows errors about being unable to connect to Redis, check that the Redis service is running (sudo systemctl status redis-server). Verify the host and port in your config.php match your Redis configuration. If using a UNIX socket, confirm the socket file exists and the web server user has permission to access it.

APCu not working for CLI: If occ commands show caching warnings, you may have forgotten to set apc.enable_cli=1 in your php.ini. Without this setting, CLI processes like occ and cron.php cannot access APCu, leading to errors and degraded performance.

Cache appears to have no effect: If Redis is running but performance has not improved, check that Nextcloud is actually using Redis. Run redis-cli MONITOR while loading Nextcloud pages. If you see no Redis commands, your config.php may have a syntax error or the cache class names may be incorrect.

SMB connection drops: If your SMB external storage intermittently disconnects, the issue is likely network-related rather than a caching problem. Check your SMB server logs and network configuration. Ensure your SMB timeout settings in Nextcloud are generous enough to handle network hiccups. Consider host-level mounting with auto-reconnect options if the External Storage app’s reconnection is not reliable enough.

Directory listings still slow after caching: If Redis is confirmed working but SMB directories are still slow, the bottleneck is likely at the SMB protocol level. Install libsmbclient-php, set filesystem_check_changes to 0, and consider host-level mounting. Also check for the Nextcloud 33+ propFind regression described earlier.

File locking errors: If you see “locked” errors in Nextcloud, your file locking backend may be misconfigured. Ensure memcache.locking is set to Redis and that Redis is running. Clear stale locks by flushing the Redis locking keys if necessary, but be careful not to flush all Redis data.

Preview generation still slow: If previews are slow even after configuration, pre-generate them with occ and ensure the appdata directory is on fast local storage. Consider using Imaginary to offload image processing from PHP entirely.

Frequently Asked Questions

How do I speed up Nextcloud with SMB external storage?

Install Redis for distributed caching, enable APCu for local caching, configure Redis transactional file locking, install libsmbclient-php for native SMB connections, switch to system cron, and set filesystem_check_changes to 0. These six changes typically reduce SMB directory listing times from 15 seconds to under 1 second.

Why is Nextcloud external storage so slow?

Nextcloud external storage is slow because the External Storage app communicates with SMB servers through PHP, triggering individual metadata queries for every file. Without memory caching, every request hits the database and SMB server. SMB protocol overhead compounds this latency, especially in directories with thousands of files.

How do I configure Redis cache for Nextcloud external storage?

Install redis-server and php-redis, then add memcache.distributed, memcache.locking, and redis connection settings to your config.php file. Point Redis to localhost on port 6379 for TCP, or use a UNIX socket for maximum speed. Restart PHP-FPM after making changes.

What are the best caching settings for Nextcloud SMB/CIFS?

The best caching setup for Nextcloud with SMB storage is APCu for local cache, Redis for distributed cache, Redis for transactional file locking, and system cron for background jobs. Combine this with libsmbclient-php, filesystem_check_changes set to 0, and preview pre-generation for optimal SMB performance.

How to fix slow Nextcloud SMB folder loading?

To fix slow SMB folder loading in Nextcloud, install libsmbclient-php for native SMB connections, configure Redis and APCu caching, set filesystem_check_changes to 0 to reduce SMB round-trips, and pre-generate previews. If you upgraded to Nextcloud 33 or later, check for the propFind regression bug that causes severe SMB slowdowns.

Does Nextcloud support SMB multichannel for faster performance?

Nextcloud itself does not configure SMB multichannel, but the underlying SMB library used by libsmbclient-php can negotiate multichannel automatically if your SMB server supports it. Enable server multi channel support on your TrueNAS or Samba server for parallel throughput on networks with multiple NICs.

How to enable APCu caching for Nextcloud external storage?

Install the php-apcu package, then add memcache.local set to OCu005cMemcacheu005cAPCu in your config.php. Also set apc.enable_cli to 1 and apc.shm_size to 64M in your php.ini or apcu.ini configuration file. Restart PHP-FPM for the changes to take effect.

Why does Nextcloud scan files so slowly on SMB shares?

Nextcloud scans files slowly on SMB shares because each file requires an individual SMB protocol round-trip to fetch metadata. Setting filesystem_check_changes to 0 in config.php reduces these scans. Installing libsmbclient-php replaces slow command-line smbclient calls with persistent native connections. Pre-generating previews and using Redis caching also reduce the number of SMB queries during scans.

How to optimize Nextcloud preview generation for SMB storage?

Pre-generate previews using the occ preview:generate-all command, configure Imaginary as an external preview generation microservice, move the appdata directory to fast NVMe or SSD storage, and enable only the preview providers you need in config.php. Running preview generation as a nightly cron job prevents on-demand generation from slowing down the web interface.

What is the best database for Nextcloud with external storage?

MariaDB or MySQL is the recommended database for Nextcloud with external storage. PostgreSQL also works well and may offer better performance for large installations. Ensure your database has adequate memory allocated to its buffer pool, and use Redis caching to reduce the number of database queries Nextcloud makes for file metadata lookups.

Conclusion

Slow Nextcloud external SMB storage is one of the most frustrating problems you can encounter, but it is entirely fixable with the right caching settings. The combination of Redis for distributed caching, APCu for local caching, Redis transactional file locking, system cron, and libsmbclient-php eliminates the vast majority of performance bottlenecks. Setting filesystem_check_changes to 0 and pre-generating previews handles the rest.

The key insight that most guides miss is that SMB-specific optimizations matter just as much as the caching layers themselves. No amount of Redis caching will compensate for the overhead of shelling out to smbclient on every operation. That is why installing libsmbclient-php is non-negotiable for any serious Nextcloud SMB deployment.

Start with the four quick fixes, verify your caches are working with redis-cli, and then work through the SMB-specific optimizations. If you want to learn how to speed up slow Nextcloud external SMB storage with caching settings across the entire server stack, the steps in this guide cover everything you need. For additional optimization strategies beyond SMB caching, check out our broader Nextcloud performance guide.

Leave a Comment