Ramblings of an aging IT geek
← Ramblings of an aging IT geek
homelab

nextcloud, again, and this time it sticks

A third attempt at self-hosting Nextcloud, doing the unglamorous database, cache and reverse-proxy work properly so it actually stays fast.

A homelab setup on a shelf

This is the third time I've stood up Nextcloud. The first two were abandoned because they were slow, and a file sync that's slow is a file sync you stop trusting. The difference this time is that I stopped treating it as a one-click app and started treating it as a PHP application with a database that has real requirements.

The previous installs failed for boring, predictable reasons. SQLite for the database, no caching layer, Apache doing everything in one container, and the snap package quietly doing things I couldn't see. Every time I opened the files view it took a beat too long, and over months that beat eroded my confidence until I gave up and went back to syncthing.

what actually mattered

Three things did most of the work this round.

First, Postgres instead of SQLite. Nextcloud's file cache table gets large and SQLite simply isn't built for concurrent access at that scale. The web UI went from sluggish to instant the moment I migrated.

Second, Redis for file locking and caching. Without it, transactional file locking falls back to the database and you get spurious "file is locked" errors under any real load. The config block is small:

'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
    'host' => 'redis',
    'port' => 6379,
],

The homelab box running the stack

Third, a real reverse proxy in front. I'm running the official fpm image behind nginx, with the recommended caching headers and the .well-known redirects that otherwise leave a permanent warning in the admin panel.

the unglamorous checklist

The admin overview page has a security and setup warnings section, and the right move is to get it to zero before declaring victory. Mine flagged:

  • missing OPcache interned strings buffer, fixed in php.ini
  • the maintenance window not being set, so background jobs don't fight with users
  • phone region unset, which breaks contact parsing silently

None of these are hard. They're just the sort of thing you skip when you're rushing, and then they accumulate into a system that feels off.

The result is a Nextcloud that opens instantly, syncs reliably across three machines and a phone, and hasn't given me a locking error in two weeks. The lesson, third time around, is that the boring infrastructure work is the entire job. The app was never the problem. My unwillingness to do the database properly was.