A Nextcloud update can fail in three distinct places: the file copy, the database migration and the apps. This tutorial covers both supported update paths, the Web Updater and occ upgrade, and the rollback that puts a broken instance back into a working state. Every command assumes an installation at /var/www/nextcloud running as the user www-data.
What does a Nextcloud update change?
A Nextcloud update replaces the PHP code in the installation directory, runs database migrations through occ upgrade and updates the enabled apps, while user files in the data directory stay untouched.
That split matters for the rollback. The code directory and the database change together, so they have to be restored together. The data directory is only written to during an update when an app migrates its own storage, which is rare. In practice, a failed update means you restore two things: /var/www/nextcloud and the SQL dump.
While the update runs, Nextcloud sets 'maintenance' => true in /var/www/nextcloud/config/config.php. In that state the web UI returns a maintenance page, clients receive HTTP 503, and background jobs stop. Nothing writes to the database, which is exactly the window your backup has to cover.
Prerequisites
- Nextcloud 28 or newer, installed from the tarball (not a distribution package that manages its own upgrade path)
- Shell access with
sudoon a Linux host, for example a scalable Cloud VM running Debian or Ubuntu - The same PHP major version on the CLI and in PHP-FPM. Verify with
php -vand the PHP info in the Nextcloud admin settings mysqldumporpg_dump, plus free disk space of at least twice the size of/var/www/nextcloud- A maintenance window. The update itself takes a few minutes; the database migration on a large instance can take considerably longer
Check the current state before anything else:
$ sudo -u www-data php /var/www/nextcloud/occ status
$ sudo -u www-data php /var/www/nextcloud/occ app:list --output=json_pretty > /root/apps-before-update.jsonThe second command writes the enabled apps and their versions to a file. After the update you can compare against it to see which apps were disabled automatically.
Can you skip a major Nextcloud version?
No, Nextcloud supports upgrading only one major version at a time, so moving from 28 to 31 requires three separate upgrade runs: 28 to 29, then 29 to 30, then 30 to 31. Each run includes its own database migration.
The updater enforces this. If you point it at a release more than one major version ahead, it aborts with Updates between multiple major versions and downgrades are unsupported. Plan the chain in advance and check the PHP requirements of every intermediate release, since a jump across three majors usually crosses a PHP version boundary as well.
Back up before you update
Enable maintenance mode first so that no request writes to the database while the dump is running:
$ sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --on
$ sudo mysqldump --single-transaction --default-character-set=utf8mb4 -u root -p nextcloud > /var/backups/nextcloud-db-2026-08-17.sql
$ sudo rsync -Aax /var/www/nextcloud/ /var/backups/nextcloud-code-2026-08-17/
$ sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --offOn PostgreSQL, replace the dump line with sudo -u postgres pg_dump nextcloud > /var/backups/nextcloud-db-2026-08-17.sql. The -Aax flags on rsync preserve ACLs, extended attributes and ownership, which the Nextcloud file permissions depend on.
If your data directory sits inside /var/www/nextcloud/data, exclude it from the code copy with --exclude data/ and back it up on its own schedule. Copying several terabytes of user files before every point release is not a workable routine, and the code rollback does not need them.
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 →
Which update method should you use?
Use the Web Updater for a standard single-server installation from the official tarball, and use a manually extracted tarball plus occ upgrade when the installation is packaged, containerised or deployed by configuration management.
| Criterion | Web Updater / updater.phar | Manual tarball + occ upgrade |
|---|---|---|
| Downloads and extracts the release | Yes | No, you do it |
| Creates its own code backup | Yes, under data/updater-<instanceid>/backups/ |
No |
| Backs up the database | No | No |
| Works without a browser | Yes, via updater.phar on the CLI |
Yes |
| Suitable for read-only or packaged installs | No | Yes |
The updater's built-in backup contains the code directory only. It does not help if the database migration is the part that failed, which is the reason for the SQL dump above.
graph TD
A["occ status: read current version"] --> B["Backup: SQL dump and code directory"]
B --> C{"Which method?"}
C -->|"standard tarball install"| D["updater.phar"]
C -->|"packaged or managed install"| E["extract release tarball manually"]
D --> F["occ upgrade"]
E --> F
F --> G{"Update successful?"}
G -->|"yes"| H["maintenance:mode --off, verify"]
G -->|"no"| I["restore code and database together"]
Update with the Web Updater
The browser-based updater in Settings > Administration > Overview and the command line updater.phar are the same program. Running it from the shell avoids PHP timeouts and gives you the full error output, so prefer the CLI:
$ sudo -u www-data php /var/www/nextcloud/updater/updater.pharThe updater prints the current and the target version, then works through eleven steps: check for updates, verify integrity, enable maintenance mode, create the code backup, download, extract, replace entry points, move the new files into place, keep config.php and third-party apps, delete the old directory and clean up. Confirm the prompt with y.
At the end it asks whether to run occ upgrade right away. Answer y. If you answer n, the instance stays in maintenance mode until you run the upgrade yourself.
Non-interactive runs are possible with --no-interaction, but only use that once you have completed the same upgrade manually on a staging instance.
Update with occ and a manual tarball
Download the target release, extract it next to the current installation and move the configuration across. Replace <version> with the exact release you are upgrading to:
$ cd /var/www
$ sudo wget https://download.nextcloud.com/server/releases/nextcloud-<version>.tar.bz2
$ sudo wget https://download.nextcloud.com/server/releases/nextcloud-<version>.tar.bz2.sha256
$ sudo sha256sum -c nextcloud-<version>.tar.bz2.sha256
$ sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --on
$ sudo tar -xjf nextcloud-<version>.tar.bz2 -C /var/www --transform 's,^nextcloud,nextcloud-new,'
$ sudo cp /var/www/nextcloud/config/config.php /var/www/nextcloud-new/config/config.php
$ sudo chown -R www-data:www-data /var/www/nextcloud-new
$ sudo mv /var/www/nextcloud /var/www/nextcloud-old && sudo mv /var/www/nextcloud-new /var/www/nextcloud
$ sudo -u www-data php /var/www/nextcloud/occ upgradeThird-party apps that are not shipped with the release live in /var/www/nextcloud-old/apps and have to be copied into the new apps directory before occ upgrade runs, otherwise the upgrade disables them. Apps installed through the app store are placed in apps as well unless you configured a separate apps-extra path in config.php.
A successful run ends with Update successful followed by the maintenance mode being switched off automatically. If it does not switch off, do it explicitly:
$ sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --offVerify the update
Run the post-upgrade database tasks first. They are optional for correctness but the admin overview will flag them as warnings until they have run:
$ sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
$ sudo -u www-data php /var/www/nextcloud/occ db:add-missing-columns
$ sudo -u www-data php /var/www/nextcloud/occ db:add-missing-primary-keys
$ sudo -u www-data php /var/www/nextcloud/occ app:update --allThen confirm the state of the instance:
$ 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: falseThe two values that matter are maintenance: false and needsDbUpgrade: false. Check the public endpoint as well, since a working CLI says nothing about the web server configuration:
$ curl -s https://<your-domain>/status.php
{"installed":true,"maintenance":false,"needsDbUpgrade":false,"version":"31.0.5.1","versionstring":"31.0.5","edition":"","productname":"Nextcloud"}Finally, compare the enabled apps against the list you saved earlier and re-enable anything the upgrade disabled, provided a compatible release exists. Run the background job manually once to confirm cron still works: sudo -u www-data php /var/www/nextcloud/cron.php.
Roll back a failed update
Restore the code directory and the database dump from the same backup run. Restoring only one of the two leaves an old code base against a migrated schema, which will not start.
$ sudo systemctl stop php8.3-fpm
$ sudo mv /var/www/nextcloud /var/www/nextcloud-failed
$ sudo rsync -Aax /var/backups/nextcloud-code-2026-08-17/ /var/www/nextcloud/
$ sudo mysql -u root -p -e "DROP DATABASE nextcloud; CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
$ sudo mysql -u root -p nextcloud < /var/backups/nextcloud-db-2026-08-17.sql
$ sudo chown -R www-data:www-data /var/www/nextcloud
$ sudo systemctl start php8.3-fpm
$ sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --offAdjust the PHP-FPM unit name to your version. Stopping it before the restore prevents requests from hitting a half-restored directory.
If the code base is too broken to run occ at all, edit /var/www/nextcloud/config/config.php directly and set 'maintenance' => false after the restore. Keep /var/www/nextcloud-failed until the instance is confirmed healthy: it contains the log file that explains why the upgrade failed, at data/nextcloud.log if the data directory is inside the installation.
Troubleshooting
The updater aborts and reports a step already in progress. The updater tracks its position in data/updater-<instanceid>/.step. If a run was interrupted, delete that file and start over from the beginning: sudo rm /var/www/nextcloud/data/updater-*/.step.
PHP version mismatch. occ upgrade uses the CLI binary, the web UI uses PHP-FPM. If they differ, the update can succeed on the command line and still return errors in the browser. Compare php -v with the PHP version shown in the admin overview and set the CLI explicitly if needed, for example sudo -u www-data /usr/bin/php8.3 /var/www/nextcloud/occ upgrade.
Apps are disabled after the upgrade. Apps without a release compatible with the new major version are disabled automatically. Check with occ app:list, then either wait for a compatible release or force installation with sudo -u www-data php /var/www/nextcloud/occ app:enable <appid> --force. Forcing an incompatible app is a common cause of white pages after an update.
Next steps
Keep the SQL dump and the code copy from the last two successful updates. That is usually enough to recover from a regression that only becomes visible days later.
Before the next major upgrade, replay the same sequence on a clone of the instance. The commands above work unchanged on a copy, and a dry run tells you the actual duration of the database migration on your dataset instead of an estimate.
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
- What Is Nextcloud? Architecture, Components and Use Cases
- 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.