Self-Hosting Nextcloud: What I Set Up Differently From the Defaults
Advertisement
Nextcloud comes up regularly with clients who urgently want a self-hosted alternative to Dropbox or Google Drive. The motivation is usually a mix of cost (per-seat cloud storage pricing aggressively adds up for a team) and strict data residency reasons (keeping company files locked on infrastructure they exclusively control).
The installation itself is perfectly straightforward; a web installer heavily handles most of it. But what separates a Nextcloud instance that merely works from one that people actually keep using—instead of quietly sneaking back to whatever they used before—is a handful of specific settings. They are not strictly "wrong" by default, but they are absolutely not tuned for real-world use.
Cron, not AJAX
By absolute default, Nextcloud's background jobs (like file scanning, notifications, and cleanup tasks) run via AJAX. They are passively triggered by page loads in the browser.
This works technically, but it means background jobs only execute when someone randomly happens to have the web UI open. It can also make page loads feel sluggish since the browser is forced to do extra background work on the server's behalf.
Switching this to a dedicated system cron job (or even better, a systemd timer) running precisely every five minutes is a quick config change in the admin settings, plus exactly one line in the terminal:
# crontab for the web server user
*/5 * * * * php -f /var/www/nextcloud/cron.php
After this tiny change, background jobs run highly reliably on schedule, regardless of whether anyone is currently using the web interface. Plus, page loads no longer carry that heavy extra penalty.
Memory caching: APCu and Redis
Nextcloud's baseline performance—especially for the web UI and for desktop clients syncing thousands of small files—depends incredibly heavily on caching being configured properly.
Without it, every single request aggressively re-reads configuration and file-locking states straight from the database. The strongly recommended setup uses both: APCu for brutally fast local memory caching, and Redis for distributed file locking (which absolutely needs to be shared across requests, and across multiple app servers if you scale out).
// config/config.php
'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
'host' => '127.0.0.1',
'port' => 6379,
],
The difference this makes is instantly noticeable in the web UI. Folder navigation and file listing go from "noticeably waiting" to close to instant. The metadata Nextcloud desperately needs is finally coming directly from memory, instead of round-tripping to the database and physical filesystem on every single request.
Upload limits live in three different places
"I can't upload files larger than X" is easily one of the most common Nextcloud complaints. The reason is that the upload size limit needs to explicitly agree across PHP, the web server, and Nextcloud's own internal setting. Whichever limit is the absolute smallest simply wins.
; php.ini
upload_max_filesize = 16G
post_max_size = 16G
# nginx
client_max_body_size 16G;
// config/config.php
'upload_max_filesize' => '16G',
Missing any single one of these means uploads will violently fail at whatever the lowest limit happens to be. It often throws a vague error message that doesn't make it remotely obvious which of the three layers is the actual culprit. Setting all three consistently, even generously, aggressively avoids a highly confusing troubleshooting session the very first time someone tries to upload a massive video file.
Trusted domains, before anyone hits a wall
Nextcloud strictly refuses to load if accessed via a hostname that is not explicitly in its trusted_domains list. This is a very smart security measure, but it produces a wildly confusing error for the first person who accidentally tries the "wrong" URL (like an internal hostname, a raw IP address, or a new domain after a server migration).
// config/config.php
'trusted_domains' => [
'cloud.example.com',
'10.0.0.5',
],
Adding every single hostname or IP that should reasonably be allowed to reach the instance—including internal ones used for health checks or admin access—up front cleanly avoids this being the very first thing anyone has to debug.
Sizing expectations and backups
For a small team (a handful to a few dozen active users), Nextcloud runs very comfortably on the exact same kind of VPS that runs a standard WordPress site. The load per user is generally modest, unless people are doing a massive amount of simultaneous large file operations.
The thing that aggressively grows is storage, obviously. And that is the part actually worth planning for. The data directory desperately needs a solid backup strategy, just like a database does. For a service whose entire purpose is "the definitive place where company files live," restoring it correctly (file permissions, the data directory structure, the database, and the config all need to perfectly match) is worth testing at least once. Just like restoring a database backup, it is infinitely better to test it on a quiet afternoon before the day it is needed for real.
None of these specific changes are difficult, and none of them are things the default installer gets "wrong", exactly. They are simply the difference between a Nextcloud instance that technically works on day one, and one that still feels fast, reliable, and invisible a year in, after real usage and massive file volumes have had a chance to expose every default that wasn't quite tuned for them.
Advertisement