Nextcloud is usually introduced as a self-hosted Dropbox alternative. That describes what it replaces, not what you have to operate: behind the web interface sits a PHP application with a database, a cache, a storage backend and a job runner, and each part fails in its own way. This tutorial breaks the stack into its components, follows a file upload through it, and lists the checks that tell you an instance is healthy.
What is Nextcloud?
Nextcloud is an AGPLv3-licensed PHP application that turns a Linux server into a private file sync, share and collaboration platform, combining WebDAV file storage, calendars, contacts, chat and office documents in a single self-hosted stack.
The project ships in two lines from the same code base: Nextcloud Server, the community release, and Nextcloud Enterprise, which adds a support contract and a longer maintenance window. "Nextcloud Hub" is the marketing name for the bundle of four app groups shipped together: Files, Talk, Groupware (Mail, Calendar, Contacts) and Office. Technically, all of them are apps on top of one server core.
What Nextcloud is not: it is not a distributed object store and not a CDN. It is a request-driven PHP application whose throughput is bounded by PHP-FPM workers, database round trips and storage latency.
Prerequisites
- A Linux host with at least 2 vCPUs and 4 GB RAM for a small team instance
- A web server (nginx or Apache) plus PHP-FPM; recent Nextcloud releases run on PHP 8.1 to 8.3, and 8.3 is the version to pick for new installations
- MariaDB 10.6 or newer, MySQL 8.0 or newer, or PostgreSQL 12 or newer
- Redis for local cache and transactional file locking
- Shell access with
sudorights and a valid TLS certificate
A single skalierbare Cloud-VM with shared CPU is enough to run the full stack for a few dozen users; the components below can be split across hosts later without changing the application logic.
Which components make up a Nextcloud installation?
A Nextcloud installation consists of five parts: a web server with PHP-FPM, the Nextcloud PHP code, a relational database for metadata, an in-memory cache such as Redis for locking, and a storage backend that holds the actual file content.
| Component | Typical software | Role | Symptom when it fails |
|---|---|---|---|
| Web layer | nginx, Apache | TLS, static files, WebDAV routing | 502 errors, upload aborts |
| Application | PHP-FPM 8.3 | Runs the Nextcloud core and apps | Slow UI, worker exhaustion |
| Database | MariaDB, PostgreSQL | File metadata, shares, users | "Internal Server Error", sync loops |
| Cache | Redis | Local cache, file locking | "File is locked" messages |
| Storage | Local disk, S3 API | File content, previews, versions | Missing files, failed writes |
| Jobs | cron.php | Scans, previews, cleanup, mail | Stale shares, no notifications |
The important split is between metadata and content. The database knows every path, share and version; the storage backend only holds bytes. Copying the data directory without the matching database dump produces an instance that cannot see its own files.
graph TD A["Client: Web, Desktop, Mobile"] --> B["Reverse proxy and TLS"] B --> C["Web server plus PHP-FPM"] C --> D["Nextcloud code in /var/www/nextcloud"] D --> E["Database: MariaDB or PostgreSQL"] D --> F["Redis: cache and file locking"] D --> G["Primary storage: local disk or S3 object store"] D --> H["Background jobs via cron.php"] B --> I["notify_push: client push over WebSocket"] I --> F
Matching infrastructure at centron
No hardware needed to follow along: ccloud³ VMs with full root access, billed by the hour and ready in seconds. Rent a cloud server →
How does a file upload move through the stack?
A file upload from the desktop client is split into chunks, sent to the WebDAV endpoint /remote.php/dav/uploads/, assembled on the storage backend by a final MOVE request, and only then registered as a single entry in the oc_filecache table.
That two-phase behaviour explains a whole class of problems. Uploads that die at 99 percent are usually not a network issue but a timeout on the assembling MOVE request, which is a single long-running PHP call. Raise request_terminate_timeout in PHP-FPM and the proxy read timeout together, not one of them alone.
sequenceDiagram participant C as Desktop client participant P as PHP-FPM participant DB as Datenbank participant S as Storage C->>P: PUT chunks to /remote.php/dav/uploads/ P->>S: write chunk files C->>P: MOVE .file to target path P->>DB: acquire lock, update oc_filecache P->>S: assemble final object P-->>C: 201 Created and new ETag
Browser uploads and mobile clients use the same DAV namespace, and every client polls /remote.php/dav/files/<USER>/ for changes. On instances with many clients this polling dominates the request count, which is what the notify_push app (Client Push) removes by pushing change events over a WebSocket instead.
Where does Nextcloud store data and configuration?
Nextcloud keeps its configuration in config/config.php inside the web root, its code and apps next to it, and user file content in the data directory or in an external object store, depending on the objectstore setting.
| Path | Contents |
|---|---|
/var/www/nextcloud/config/config.php |
Database credentials, trusted_domains, Redis, datadirectory |
/var/www/nextcloud/apps/ |
Shipped apps, replaced on upgrade |
/var/www/nextcloud/custom_apps/ |
Apps installed from the app store |
/var/www/nextcloud/data/ |
User files, versions, trash bin |
/var/www/nextcloud/data/appdata_<INSTANCEID>/ |
Previews, app caches, theming |
/var/www/nextcloud/data/nextcloud.log |
Application log in JSON lines |
The data directory must sit outside the document root or be blocked by the web server. A default installation places it inside the web root and protects it with .htaccess on Apache; with nginx you deny access explicitly or move the directory to /var/nextcloud/data.
For larger instances, primary storage can be moved to an S3-compatible bucket. In that mode the data directory only holds logs, previews and app data, while every user file becomes an object named urn:oid:<fileid>. The bucket is then unreadable without the database, so back up both together and keep the retention windows aligned.
Background jobs and cron
Nextcloud performs file scans, preview generation, share expiry, activity mails and cleanup through cron.php, which must be executed every five minutes by a system cron job or a systemd timer.
$ sudo -u www-data crontab -l
*/5 * * * * php -f /var/www/nextcloud/cron.phpSwitch the mode explicitly and confirm it:
$ sudo -u www-data php /var/www/nextcloud/occ background:cron
Set mode for background jobs to 'cron'The alternative AJAX mode only runs jobs while someone has a browser tab open, so nightly tasks never fire on a low-traffic instance. Treat AJAX mode as a temporary state during setup, not a configuration.
Which use cases does Nextcloud actually fit?
Nextcloud fits four workloads well: file sync and share for teams, groupware as a Mail, Calendar and Contacts replacement, browser-based document editing through Collabora or OnlyOffice, and controlled external sharing with public links, passwords and expiry dates.
| Use case | Components involved | Operational note |
|---|---|---|
| Team file sync | Files, desktop clients, Redis | Add notify_push above ~20 clients |
| Groupware | Mail, Calendar, Contacts, IMAP server | CalDAV and CardDAV work with standard clients |
| Document collaboration | Office app plus Collabora or OnlyOffice | Editing server needs its own CPU budget |
| Chat and calls | Talk, coturn | Group calls beyond ~4 users need the High Performance Backend |
| External file exchange | Public links, Files Drop | Enforce link passwords and expiry by policy |
Poor fits are equally clear: build artefact storage with thousands of writes per minute, media streaming to many concurrent viewers, and anything that expects POSIX semantics on an S3 backend. Those belong on object storage or a dedicated file server, with Nextcloud mounted on top as an external storage if users need a view of the data.
Verify a running instance
Start from the outside. The status.php endpoint answers without authentication and shows whether the instance is installed and out of maintenance mode:
$ curl -s https://cloud.example.com/status.php
{"installed":true,"maintenance":false,"needsDbUpgrade":false,"version":"31.0.5.1","versionstring":"31.0.5","edition":"","productname":"Nextcloud","extendedSupport":false}Then check the application from the shell. All occ commands run as the web server user:
$ sudo -u www-data php /var/www/nextcloud/occ status
- installed: true
- version: 31.0.5.1
- versionstring: 31.0.5
- edition:
- maintenance: false
- needsDbUpgrade: false
- productname: NextcloudThree further commands cover the parts that silently drift:
$ sudo -u www-data php /var/www/nextcloud/occ app:list --shipped=false
$ sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
$ sudo -u www-data php /var/www/nextcloud/occ config:system:get memcache.lockingThe last command must print \OC\Memcache\Redis. An empty result means file locking runs against the database, which produces lock timeouts under concurrent sync.
Troubleshooting
- "Access through untrusted domain": the hostname is missing from
trusted_domains. Add it withocc config:system:set trusted_domains 1 --value=cloud.example.com. - "File is locked" that never clears: stale locks after a crashed PHP worker. Configure Redis for
memcache.locking, then clear leftovers withocc maintenance:repair. - Mixed content or redirect loops behind a proxy: Nextcloud detects HTTP instead of HTTPS. Set
overwriteprotocoltohttpsand list the proxy IP intrusted_proxies. - "Last background job execution ran X hours ago": the cron entry is missing or runs as the wrong user. Verify with
sudo -u www-data crontab -land checkdata/nextcloud.logfor job errors.
Next steps
You now have a component map, the request path for uploads, and a short list of commands that separate an application problem from an infrastructure problem. Before opening an instance to users, settle two decisions: where primary storage lives, local disk or object store, and how database and file data are backed up in one consistent operation. Both are cheap to change on day one and expensive to change at 500 GB.
Read next
- Back Up and Restore Nextcloud: Data, Database, Config
- Install Nextcloud All-in-One with Docker
- Install Nextcloud on Ubuntu 24.04 with nginx
- Mount Nextcloud via WebDAV on Linux, Windows and macOS
- Nextcloud vs ownCloud vs Seafile: Which One Fits?
- Run Nextcloud with Docker Compose
- Set Up Nextcloud Office: Collabora or OnlyOffice
- Updating Nextcloud: Web Updater, occ and a Rollback Plan
- Which Server for Nextcloud? Sizing RAM, CPU and Storage
Testen Sie Ihr Setup auf ccloud³
Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.