Nextcloud at production scale on a LYLIX VPS — storage, OCC, malware scanning
Nextcloud is the most common "file sync + collaboration" self-host. The default tutorial install works for a couple of users and a small library but falls over once you have real data or real users. This article covers the patterns that hold up.
Sizing
For a small office (5-25 users, ~100 GB total content):
- 4 GB RAM, 2 CPU cores.
- Disk: 2× your expected content size (Nextcloud holds thumbnails, versions, trash).
- PHP 8.1 or newer.
For larger or more active deployments, scale linearly. Active office video calls plus Talk plus heavy file sync = bigger.
Install path
Three reasonable options:
- AIO (All-in-One Docker) — Nextcloud's official one-command Docker setup. Easiest to operate; less flexibility.
- Snap — official on Ubuntu. Easy install, weird locations.
- Manual LEMP stack — full control, more setup work, what we walk through here.
Pick AIO if you want minimal ops. Pick manual if you want to understand what's happening.
Manual install — the structure
- nginx as reverse proxy + TLS terminator.
- PHP 8.1 FPM behind it.
- MariaDB or PostgreSQL for metadata.
- Redis for caching and file locking.
- Data dir outside the web root.
apt install nginx php8.1-fpm php8.1-{mysql,xml,gd,curl,mbstring,intl,bcmath,gmp,imagick,zip,bz2} \
mariadb-server redis-server
Database setup:
mysql -e "
CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY '<strong-password>';
GRANT ALL ON nextcloud.* TO 'nextcloud'@'localhost';
FLUSH PRIVILEGES;"
Nextcloud install:
cd /var/www
wget https://download.nextcloud.com/server/releases/latest.tar.bz2
tar xf latest.tar.bz2
chown -R www-data:www-data nextcloud
mkdir -p /srv/nextcloud-data
chown www-data:www-data /srv/nextcloud-data
Then nginx config (Nextcloud publishes a vetted nginx config in their docs — use it verbatim, it handles a lot of edge cases).
Run the install via OCC
occ is Nextcloud's CLI. Always use it for admin operations where possible — faster, scriptable, less webhook overhead.
cd /var/www/nextcloud
sudo -u www-data php occ maintenance:install \
--database "mysql" \
--database-name "nextcloud" \
--database-user "nextcloud" \
--database-pass "<password>" \
--admin-user "admin" \
--admin-pass "<admin-password>" \
--data-dir "/srv/nextcloud-data"
Post-install — the must-do list
- Set trusted_domains in
config/config.php— your hostname(s). - Set overwrite.cli.url to
https://cloud.example.com. - Configure Redisfor memcache and file locking:
'memcache.local' => '\\OC\\Memcache\\Redis', 'memcache.locking' => '\\OC\\Memcache\\Redis', 'redis' => [ 'host' => '/var/run/redis/redis-server.sock', 'port' => 0, ], - Set up cronfor background jobs:
And set Background jobs → Cron in admin UI.*/5 * * * * www-data php -f /var/www/nextcloud/cron.php - Enable HSTS, XSS protection headers in nginx.
- Install opcache, configure it for performance.
Storage strategies
Nextcloud's data dir gets big fast. Options:
- Local disk: simplest. Make sure the VPS disk is big enough; resize is easy. See Upgrading VPS plan.
- S3-compatible primary storage: Nextcloud can use Backblaze B2, Wasabi, or any S3-shaped backend. Configure in config.php as objectstore. Cheaper than local for cold/large data; latency is worse for active files.
- External storage mounts: per-user connections to S3, SMB, FTP. Useful for legacy share access; not great for primary storage.
Malware scanning
Nextcloud has the Files Antivirus app — installs ClamAV integration. Scan options:
- On upload: every uploaded file is scanned. Slow but thorough.
- Background: scheduled scans of existing files.
For most home/small-office deployments, background scanning nightly is the practical choice. On-upload doubles upload latency.
apt install clamav-daemon clamav-freshclam
sudo -u www-data php occ app:install files_antivirus
Configure mode and ClamAV path in the app settings.
Useful occ commands
# Maintenance mode toggle
sudo -u www-data php occ maintenance:mode --on
sudo -u www-data php occ maintenance:mode --off
# Re-scan files (after manual changes to data dir)
sudo -u www-data php occ files:scan --all
# User management
sudo -u www-data php occ user:add <name>
sudo -u www-data php occ user:resetpassword <name>
# Upgrade
sudo -u www-data php occ upgrade
Backup strategy
- Database: nightly mysqldump → off-host.
- Data dir: incremental (restic, borg) → off-host.
- config/ dir: in version control or backup as text.
See Restic with B2 for the off-host pairing.
Performance tuning
- PHP-FPM pool sizing: max_children proportional to RAM divided by 80 MB.
- Database tuning: innodb_buffer_pool_size = 30-50% of RAM.
- Use Redis for both memcache and file locking.
- Enable opcache. Significant improvement.
- Preview generator: use the Preview Generator app to pre-generate thumbnails on a schedule.
Common production headaches
- "Could not get lock" errors — Redis isn't being used for file locking. Configure as above.
- Files appear missing after manual data dir operations — run
occ files:scan --all. - Upgrade fails partway — put in maintenance mode, run upgrade from CLI, watch output.
- Performance degrades over time — usually files_versions and files_trashbin growing. Tune retention policies in config.
Also Read
Powered by WHMCompleteSolution