Back to Article List

Nextcloud stuck in maintenance mode: How to get out

Nextcloud stuck in maintenance mode: How to get out

This Nextcloud instance is currently in maintenance mode, which may take a while. The screen refreshes itself, nothing changes, and every minute it stays up your users are locked out. Before reaching for a fix, an honest note: sometimes it genuinely is just taking a while. Maintenance mode is the flag Nextcloud raises while the updater runs database migrations, and on a big instance the filecache migrations alone can grind for a long time. My instance carries roughly 400 GB and a filecache table in the millions of rows, and a major upgrade sits in maintenance mode for a solid stretch of it with nothing visibly wrong.

So the first decision is telling waiting from stuck, and there are three signals. Watch the upgrade output if you started it in a terminal, a healthy occ upgrade keeps printing migration steps. Watch nextcloud.log and the updater log next to it in the data directory, a working upgrade appends lines every few seconds while a wedged one went silent minutes ago (the log locations per install type are in where are the Nextcloud logs). And watch the box itself: top showing mysqld or php busy means work is happening. Quiet CPU, silent log, no database activity, that's stuck. I learned the difference the expensive way, losing most of a Sunday to a wedged upgrade at Nextcloud 32 that I made worse by force-killing things that turned out to be alive. Everything below is the sequence I wish I'd followed that day, in order, least destructive first.

Step 1: Let occ tell you what state you're in

Maintenance mode has two lookalike states and they need different fixes. Run any occ command, even a plain occ status:

sudo -u www-data php /var/www/nextcloud/occ status

If you see Nextcloud or one of the apps require upgrade - only a limited number of commands are available, the code on disk is newer than the database schema. Turning maintenance mode off now just swaps the maintenance screen for an update-needed screen, so finish the upgrade instead:

sudo -u www-data php /var/www/nextcloud/occ upgrade

Run in a terminal multiplexer if you're on SSH (tmux or screen), a dropped connection mid-migration is one of the classic ways instances end up half-upgraded. A completed run ends by turning maintenance mode off itself. If occ upgrade exits with an error instead, note which migration or app it names, that's step 4's problem. The upgrade documentation describes the full sequence the command walks through.

Step 2: occ maintenance:mode --off

When occ reports a normal installed state and the flag is simply still up (a backup script that died before its cleanup step is a frequent cause, mine toggles maintenance mode around database dumps), the official exit is one command:

sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off

Sometimes it refuses or appears to do nothing. The two causes I've met: config.php isn't writable by the web user, so the command can't flip the flag it needs to flip (the log will say so), or the instance is in the upgrade-pending state from step 1, where the flag isn't your real problem. Fix the file ownership on the config directory in the first case and rerun. A refusal here is information, it's telling you which step you're really on.

Step 3: Flip the flag in config.php by hand

The maintenance screen is driven by one line in /var/www/nextcloud/config/config.php:

'maintenance' => true,

Change true to false, save, reload. This is the manual override and it's safe exactly when nothing is mid-flight: no occ upgrade process running, no updater working, database quiet. I verify all three before touching the file:

ps aux | grep -E 'occ|updater' | grep -v grep
mysql -u root -p -e "SHOW PROCESSLIST;"

An empty first result and a processlist showing only sleeping connections means the coast is clear. That's what the waiting-versus-stuck check at the top was for. Flipping the flag under a live migration doesn't stop the migration, it lets users write to an instance in the middle of schema surgery, which is how you graduate from a stuck upgrade to restoring from backup. On Docker the same file sits in the config volume, or skip the editor entirely with the exec form in step 6.

Step 4: An app wedged the upgrade

When occ upgrade dies repeatedly at the same step, read which migration it names in the output or in nextcloud.log. In my experience the offender is almost never core, it's a third-party app whose migration fails against the new version. The way through is disabling that app and letting the rest of the upgrade finish:

sudo -u www-data php /var/www/nextcloud/occ app:disable calendar_addons
sudo -u www-data php /var/www/nextcloud/occ upgrade

Substitute the app the log names. Disabling loses the app's function until it ships a compatible release, it doesn't delete its data. Before upgrades I now check each third-party app's listing for a release supporting the target major, an app that hasn't updated for the previous major either is a strong hint to disable it up front. That Sunday on 32 came down to exactly this, an abandoned app failing its migration over and over, and forty minutes of my life would have been saved by reading the log line instead of rerunning the upgrade hoping for a different result. Once the instance is back, a stroll through my internal server error checklist is worth it if pages still misbehave, half-finished upgrades and 500s travel together.

Step 5: Repair after a rough exit

After any forced exit or interrupted upgrade I run the repair pass and the index check before calling it done:

sudo -u www-data php /var/www/nextcloud/occ maintenance:repair
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices

The first mends app registrations and mimetypes and similar internals, the second adds any database indices the upgrade meant to create before it was interrupted. Both are safe on a healthy instance too, they just find nothing. There's also occ maintenance:repair --include-expensive for the heavier checks, which I save for quiet hours since some of its passes walk the whole filecache. Then I load the admin overview and read the warnings, which is my standing habit before and after touching any instance anyway. A clean repair run plus a quiet overview is my definition of recovered, as opposed to merely serving pages again.

Step 6: The Docker and AIO forms

Same commands, wrapped in docker exec. For the official image:

docker exec -u www-data nextcloud php occ maintenance:mode --off

Swap nextcloud for whatever docker ps calls your container, and if you'd rather edit config.php directly, docker inspect on the container shows where the config volume lands on the host. For AIO, the Nextcloud container has a fixed name:

docker exec -u www-data nextcloud-aio-nextcloud php occ maintenance:mode --off

One AIO-specific note: its own interface manages updates, so an instance that's always in maintenance during the backup window is AIO's Borg backup doing its job, not a wedge. Give it time before intervening, the container logs (docker logs) show which phase it's in.

Step 7: When restoring beats forcing

There's a point where I stop climbing: migrations half-applied, occ throwing database errors it didn't throw an hour ago, repair commands failing. An instance forced back to life in that state can carry subtle schema damage that surfaces weeks later, which is far worse than an evening of downtime. If the pre-upgrade backup exists, restoring it and re-attempting the upgrade cleanly is the boring move that works, and my backup and restore playbook covers the exact restore order (database and data directory together, always). Restic to offsite storage means the restore costs me minutes, which changes the whole calculation about how long to fight a wedged instance.

Not getting stuck next time

Three habits, all learned from that Sunday. A backup immediately before every upgrade, unconditionally, it's the difference between step 7 being available and being theoretical. One major version at a time, 32 to 33 to 34, never skipping, skipped majors are unsupported territory and the updater enforces it for good reason. And patience on .0 releases: I sit out the first release of each major and join at .1 or .2, which is why my production box went to 34 at 34.0.2 while my test instance took the .0 bruises. A new major lands every four months. Waiting six weeks of that cycle costs nothing and skips the sharpest bugs, and it's the single cheapest insurance in this whole article.

Your idea deserves better hosting

24/7 support 30-day money-back guarantee Cancel anytime
Abonament

VPS.S1

$5.99 Save  17 %
$4.99 Lunar
  • 2 vCPU AMD EPYC
  • 2 GB RAMMEMORIE
  • 30 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse

VPS.S3

$14.99 Save  33 %
$9.99 Lunar
  • 4 vCPU AMD EPYC
  • 6 GB RAMMEMORIE
  • 70 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse

EPYC VPS.P1

$8.99 Save  22 %
$6.99 Lunar
  • 2 vCPU AMD EPYC
  • 4 GB RAMMEMORIE
  • 40 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

EPYC VPS.P2

$16.99 Save  24 %
$12.99 Lunar
  • 2 vCPU AMD EPYC
  • 8 GB RAMMEMORIE
  • 80 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

EPYC VPS.P4

$29.99 Save  23 %
$22.99 Lunar
  • 4 vCPU AMD EPYC
  • 16 GB RAMMEMORIE
  • 160 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

EPYC VPS.P5

$39.99 Save  25 %
$29.99 Lunar
  • 8 vCPU AMD EPYC
  • 16 GB RAMMEMORIE
  • 180 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

EPYC VPS.P6

$59.99 Save  25 %
$44.99 Lunar
  • 8 vCPU AMD EPYC
  • 32 GB RAMMEMORIE
  • 200 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

EPYC VPS.P7

$69.99 Save  29 %
$49.99 Lunar
  • 16 vCPU AMD EPYC
  • 32 GB RAMMEMORIE
  • 240 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

Genoa VPS.G2

$24.99 Save  20 %
$19.99 Lunar
  • 2 vCPUAMD EPYC Genoa generația a 4-a 9xx4 cu 3,25 GHz sau similar, pe arhitectura Zen 4. AMD EPYC G4
  • 4 GB DDR5MEMORIE
  • 50 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

Genoa VPS.G4

$44.99 Save  22 %
$34.99 Lunar
  • 4 vCPUProcesor AMD EPYC cu nuclee vCPU dedicate, pe hardware de server pentru companii. AMD EPYC G4
  • 8 GB DDR5MEMORIE
  • 100 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

Genoa VPS.G6

$89.99 Save  22 %
$69.99 Lunar
  • 8 vCPUProcesor AMD EPYC cu nuclee vCPU dedicate, pe hardware de server pentru companii. AMD EPYC G4
  • 16 GB DDR5MEMORIE
  • 200 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

Genoa VPS.G7

$159.99 Save  22 %
$124.99 Lunar
  • 8 vCPUProcesor AMD EPYC cu nuclee vCPU dedicate, pe hardware de server pentru companii. AMD EPYC G4
  • 32 GB DDR5MEMORIE
  • 250 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos. incluse
  • Backup automat gratuitInclude un spațiu de backup pe care îl poți configura pentru rulare zilnică, săptămânală sau lunară.

AMD Ryzen VPS.R1

$16.99 Save  18 %
$13.99 Lunar
  • 1 CPU dedicat AMD Ryzen 9 7950X cu 4,5 GHz sau similar, pe arhitectura Zen 4. vCPU
  • 4 GB DDR5MEMORIE
  • 50 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6 incluse Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos.
  • Backup automat inclus

AMD Ryzen VPS.R2

$29.99 Save  17 %
$24.99 Lunar
  • 2 CPU dedicate AMD Ryzen 9 7950X cu 4,5 GHz sau similar, pe arhitectura Zen 4. vCPU
  • 8 GB DDR5MEMORIE
  • 100 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6 incluse Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos.
  • Backup automat inclus

AMD Ryzen VPS.R4

$109.99 Save  18 %
$89.99 Lunar
  • 8 CPU dedicate AMD Ryzen 9 7950X cu 4,5 GHz sau similar, pe arhitectura Zen 4. vCPU
  • 32 GB DDR5MEMORIE
  • 400 GB NVMeSTOCARE
  • Trafic nelimitat
  • IPv4 & IPv6 incluse Suportul IPv6 este momentan indisponibil în Franța, Finlanda sau Țările de Jos.
  • Backup automat inclus

FAQ

Can I turn maintenance mode on deliberately before a backup?

Yes, and I do: occ maintenance:mode --on, run the database dump and file backup, then --off. It guarantees the database and files can't drift apart mid-backup. Script the --off in a trap or finally-block so a failed dump doesn't leave the flag up, that's the exact accident rung 2 exists for.

GPU products are in high demand at the moment. Fill the form to get notified as soon as your preferred GPU server is back in stock.