HowTo: Upgrade to Nextcloud 26 on Debian Bullseye


  • This HowTo does not apply to any Nextcloud container/VM/snap appliance, but is for bare metal installs on Debian Bullseye only!
  • This HowTo was written with best efforts, but without guarantee. I cannot be held responsible for any damage to your system or data!


Nextcloud 26 is about to be released on 2023-03-21, which drops support for PHP 7.4, the PHP version shipped by the current stable Debian Bullseye.

The upcoming Debian Bookworm release is expected this summer, but it ships PHP 8.2, which is not supported by Nextcloud 25 yet.

Since there is no Nextcloud version which supports both, PHP 7.4 of Debian Bullseye and PHP 8.2 of Debian Bookworm, an upgrade is impossible, using official system packages and unmodified Nextcloud versions only.

This HowTo walks you through two possible solutions to get you unstuck and Nextcloud upgraded to version 26 on Debian Bullseye.

First, do a backup!

As always, before doing any such changes to your production server, create/update a full system backup and a dedicated backup of your Nextcloud data and database. At best try the steps first on a testing clone of your Nextcloud server to sort out surprises in the middle of the process. If not the case already, incorporate these steps into your general server maintenance routines.

1. Ondrej’s PHP repository

Ondrej Sury is the official Debian PHP (and Apache2, …) package maintainer and maintains additional APT repositories from where one can install latest software on older Debian versions.

His PHP repo can be used to install PHP 8.1 on Debian Bullseye. However, using this repository implies a number of risks you need to be aware of and which may bite you in the long term. This is hence not the preferred solution in the author’s personal opinion, especially if you are not experienced with APT, solving package conflicts and downgrading packages manually via dpkg CLI:

  • If you install PHP via unversioned meta package like apt install php-fpm, you basically switch to a rolling release model, as on Ondrej’s repository these packages always pull the very latest PHP version. This can either lead to multiple concurrent PHP installs or break your Nextcloud, which does not support latest PHP once released, like currently PHP 8.2.
    Usually this can be solved by installing the versioned packages explicitly (needed for PHP 8.1 anyway) like apt install php8.1-fpm, but there are official Debian packages which depend on unversioned meta packages, like phpMyAdmin. APT pinning can be used to prevent meta package installs from this repository.
  • The repository ships not only PHP, but also newer versions of system libraries, which some of the PHP packages depend on. This can cause conflicts if other Debian packages depend on the version provided by the official Debian repository.
    It can furthermore cause issues if you later need to remove the repository, e.g. because you upgraded to Debian Bookworm, not supported by the PHP repo yet, or because your company demands to remove any 3rd party repositories (while there is no reason to not trust Ondrej if one trusts Debian). If you then e.g. try to install development headers (*-dev packages) for one of these libraries, APT errors out with conflicts due to the version mismatch between runtime library and development headers.
    With bi-directional version dependencies which cannot be solved without a downgrade, apt cannot solve it, but manual downloads and downgrades via dpkg are required. A downgrade may even be needed after a Bookworm upgrade, since the PHP repo ships package versions beyond any official Debian repo.

However, for Nextcloud-only systems, or with some knowledge or support, these are acceptable risks, which can be further minimised by applying some strict APT pinning, e.g. with the following here document command block:

cat << 'EOF' > /etc/apt/preferences.d/php
Package: *
Pin: origin
Pin-Priority: -1

Package: php8.1-* libapache2-mod-php8.1 libpcre2-* libgd3 libgd-dev
Pin: origin
Pin-Priority: 500

Install the repository itself this way:

sudo curl -sSLo /usr/share/keyrings/
echo 'deb [signed-by=/usr/share/keyrings/] bullseye main' | sudo tee /etc/apt/sources.list.d/php.list
sudo apt update

Then you can install PHP 8.1 and all needed modules, using the versioned php8.1-* package names. Remember to adjust webserver configs in case, pointing to the new PHP 8.1 socket, or using the unversioned generic socket /run/php/php-fpm.sock. On Apache2, these commands will do:

a2dismod php7.4
a2enmod php8.1
a2disconf php7.4-fpm
a2enconf php8.1-fpm
systemctl restart apache2

Also don’t forget to port custom configs you may have done from /etc/php/7.4 to /etc/php/8.1. After verified that Nextcloud and everything works well with the new PHP instance, you may remove the old PHP 7.4 packages:

apt purge $(dpkg --get-selections | mawk '/php7.4/{print $1}')

This may additionally remove the old unversioned meta packages, which is fine. Just verify that nothing unwanted is removed before confirming it.

2. Upgrading to Debian Bookworm

Even that Debian Bookworm has not been released yet, but is the Debian testing branch, at time of writing, the first two package freezing stages have been passed, which means that all larger library/runtime system transitions and backend software upgrades have been finished, including PHP 8.2, MariaDB 10.11, PostgreSQL 15 and Python 3.11. While new upstream software versions can still be merged and you will see a significantly larger amount of available package upgrades following apt update compared to a stable Debian release, large surprises and breaking changes are not expected anymore (while no guarantee can be given!).

While a distribution upgrade always bears risks, nowadays Debian maintainers usually have CI/CD pipelines to test and take care of smooth distro upgrades. However, it cannot be ruled out that you need to apply configuration changes manually, especially if you changed them manually before (instead of using own drop-in/overrides configs, like conf.d directories and similar). I tested the Bullseye to Bookworm upgrade with a typical Nextcloud installation, Apache2, Nginx and Lighttpd webserver, multiple times, and so far no major quirks appeared, respectively they have been sorted in the meantime. I’ll keep this topic updated in case any issues appear, and how to resolve them.

The bonus of upgrading to Bookworm is that you lift the whole system onto a future-prove stage, including latest PHP 8.2. This may be necessary anyway earlier or later, as long as you do not prefer setting up the system from scratch, which is always a recommended clean alternative to major distribution upgrades.

First of all upgrade all packages to the latest stage, using the current package lists:

apt update
apt upgrade
apt full-upgrade

Carefully check the outputs for any error and sort them out before doing further changes.

Then migrate package the package lists from Bullseye to Bookworm:

sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list
sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list.d/*.list
apt update

Again, carefully check the output of the last command. There may be 3rd party software lists which have no bookworm suite yet, including Ondrej’s PHP repository if your applied it before, or SBC vendor repositories. Often, packages from bullseye suites can be installed and run on Bookworm as well. But also check whether you really need affected lists. If they were only to provide newer software versions, like Ondrej’s PHP repo, they may not be needed on Bookworm so that you can remove them:

rm /etc/apt/sources.list.d/php.list
rm /etc/apt/preferences.d/php
rm /usr/share/keyrings/

Then apply the actual distribution upgrade:

apt upgrade
apt full-upgrade
head -4 /etc/os-release

Two currently known quirks may need to be solved:

  • The mariadb-server package was left removed instead of upgraded to v10.11.
  • The Redis configuration needs to explicitly allow failing to bind on IPv6 now, which previously was implicit. Only relevant if you do not use IPv6, but save to apply in any case.
apt install mariadb-server
sed -i '/^bind ::1$/c\bind -::1' /etc/redis/redis.conf
systemctl restart redis-server

If you use PostgreSQL, you need to migrate the database from v13 to v15:

systemctl stop postgresql
pg_dropcluster 15 main
pg_upgradecluster 13 main
pg_dropcluster 13 main
systemctl start postgresql

In case you installed the versioned PHP packages before, you need to install PHP 8.2 and all needed modules, using the php8.2-* package names. Remember to adjust webserver configs in case, pointing to the new PHP 8.2 socket, or using the unversioned generic socket /run/php/php-fpm.sock. On Apache2, these commands will do:

a2dismod php7.4
a2enmod php8.2
a2disconf php7.4-fpm
a2enconf php8.2-fpm
systemctl restart apache2

Also don’t forget to port custom configs you may have done from /etc/php/7.4 to /etc/php/8.2. After verified that Nextcloud and everything works well with the new PHP instance, you may remove the old PHP 7.4 packages:

apt purge $(dpkg --get-selections | mawk '/php7.4/{print $1}')

This may additionally remove the old unversioned meta packages, which is fine. Just verify that nothing unwanted is removed before confirming it.

Finally, if the kernel was upgraded, do a reboot, otherwise at least restart systemd via systemctl daemon-reexec. If everything worked well, you can autoremove obsolete packages:

apt autopurge

Now remember that Nextcloud 25 does not support PHP 8.2. However, aside of a few deprecation warnings, it does actually work fine, and we only need it to run the update to Nextcloud 26, which does support PHP 8.2. To allow this, we need to do a little temporary hack:

sed -i 's/>= 80200/>= 80300/' /var/www/nextcloud/lib/versioncheck.php

In case, adjust the path to your Nextcloud installation directory.

Now you should be able to perform the update to Nextcloud 26.


If you run into any issues or have any feedback, please reply to this topic. This is meant to stay work-in-progress as I will keep it updated with recent info, solutions for possible new quirks etc.


Hi ! Thank you very much for this HowTo !
I think you forgot to add the package php8.1 in the here document.


Package: php8.1 php8.1-* libapache2-mod-php8.1 libpcre2-* libgd3 libgd-dev
Pin: origin
Pin-Priority: 500

Without this edit, I obtain an error when trying to install the basic php8.1 package.

php, php8.1 etc are just meta packages which pull in any actual PHP implementation, like libapache2-mod-php8.1 (the default which I’d not recommend) , php8.1-fpm (which I’d recommend) or php8.1-cgi. Pick one of those, preferably PHP-FPM for any production system, instead of the meta package.

Just a bit of fun when upgrading Bullseye to Bookworm is for some reason if you use non-standard ports in Apache it will no longer work. I’ve spent hours troubleshooting and looking at configuration and log files trying to figure out why I couldn’t connect to port 444 which I use to access it internally. I use a reverse proxy to handle the external connections.

To see if the ports are being blocked I did broad port scans and noticed 444 never responded while port 443 did. Soon as I changed the port from 444 to 443 (standard https) in the apache ini file for nextcloud it worked. Oddly enough firewall is not enabled nor installed. Iptables shows nothing is being blocked so makes me wonder did something changed in Apache in terms of security?

Figured I throw this out there if you use non-standard ports.

Thank you for this tutorial! Have already racked my brain how I can solve this stupid situation. I wonder how many thousands of people are affected when they update from bullseye to bookworm! Hope the realize it before the update… :see_no_evil:


How did you changed the ports, i.e. in which config file?

I just tested:

  1. Changed ports in /etc/apache2/ports.conf
  2. Adjusted default vhost accordingly in /etc/apache2/sites-enabled/000-default.conf
  3. Upgraded to Bookworm, including Apache2 to v2.4.57-2 and PHP to v8.2.7-1 (current latest von Debian Bookworm APT repo)

Nextcloud is reachable on changed port 81. Since I have no HTTPS enabled on this test instance, I did not test port 441. But the at least /etc/apache2/ports.conf remained unchanged.

This is such a wonderful resource. Thank you so much for posting this; you saved me from hours of frustration and unproductive effort! Thank you, thank you, thank you!

I had no problem with Nextcloud 25 to Nextcloud 26 and Debian Bullseye to Debian Bookworm see here.

1 Like

Theroetically this is not possible at all because NC26 does not support PHP7.4! That is why the upgrade to NC26 does not come with me at all.
At best you can raise debian to bookworm and then in the console NC25 to NC26. I will try this as soon as I have time.
But I can’t imagine that the upgrade from NC25 to NC26 worked. Probably you had already upgraded PHP to 8.X before.

The updater.phar is self-containing, has independent PHP requirements, is not invoking versioncheck.php and checks for available updates on its own. So indeed it should be possible to just run

sudo -u www-data php /path/to/nextcloud/updater/updater.phar

after upgrading Debian to Bookworm, and have all done in one step, without touching Nextcloud core files.

I am running currently another NC25 test instance on Debian Bullseye (PHP 7.4) for some hours, checking admin panel and running both, occ update:check and the updater.phar regularly, and I do not get the update offered. On my last test instance, after upgrading to Debian Bookworm, the update was offered immediately. I have not found it in the code, but while it contradicts devnull’s case, it all looks like there is some mechanism to not have it offered in the first place, if an incompatible PHP version does the check. And this applies for both, updater.phar, occ update:check and the admin panel (the latter two share the same code and cache anyway).

1 Like

I have 6x NC25 running with php 7.4 on debian 11. None of them shows the update to NC26. For me it’s clear why: PHP 7.4 is not supported with NC26 so the update is not possible.
But lets see if it works with the way you above (updating debian to bookworm and then run the updater in CLI).

Maybe channel “beta”?

I tried it with beta channel as well and it didn’t make a difference, also not after upgrading to the current NC25 RC. However, switching to beta channel is not applicable for production systems most of the time anyway: If an NC26 upgrade was offered, it would be a beta or RC version, if any available.

The motto of the day: No risk, no fun! :metal:
I mounted my helmet and threw myself off the cliff…
First I upgraded Debian from 11 to 12.
After a reboot, NC25 stopped working as suspected. The reason is that PHP7.4 was uninstalled but PHP8.2 is missing.
Therefore I installed all PHP packages:

apt install php-apcu php-bcmath php-bz2 php-cgi php-cli php-curl php-fpm php-imagick php-intl php-json php-mbstring php-mysql php-opcache php-readline php-sqlite3 php-xml php-zip php-gd php8.2-gmp

Don’t forget to enable the cache in “/etc/php/8.2/cli/php.ini” “apc.enable_cli=1” and set memory from 128M to 512M in “/etc/php/8.2/fpm/php.ini”.
Then enable PHP:

a2enmod mpm_event
a2enconf php8.2-fpm
systemctl restart apache2

NC25 still does not work because now the message appears that it is not compatible with PHP8.2.
Now I have raised NC25 to NC26 with the above command “sudo -u www-data php /path/to/nextcloud/updater/updater.phar”.
Immediately the update to NC26.0.2 is offered and executed.
Now NC26 is running.

I think thanks to the helmet everything worked! :stuck_out_tongue_winking_eye:


Side note: With this you have both installed and enabled: PHP-FPM with its Apache handler, as well as the internal Apache PHP module. I am surprised that those do not conflict loudly, probably because FPM works only with event or worker MPM while the module works only with prefork MPM. You however should have seen related warnings when running a2enmod. Nowadays, PHP-FPM is recommend for most or all setups. So you should be able to disable and uninstall the PHP module:

a2dismod php8.2
a2dismod mpm_prefork
a2enmod mpm_event
a2enmod php8.2-fpm
systemctl restart apache2
# check whether everything is working
apt purge libapache2-mod-php

Reverting this in opposite order re-enables the PHP module. The module has the downside that every single client connection uses (in case spawns) an own Apache process (prefork MPM) with a whole new PHP instance. This slows down client connections and increases RAM usage significantly on concurrent access, and it breaks caching in PHP. The event MPM will spawn a number moreless static Apache processes with a fixed number of worker threads which can hence each handle a large number of requests. And PHP-FPM can maintain one OPcache and APCu instance for all Nextcloud visitors, being a performance benefit and uses less peak RAM, especially when multiple clients access concurrently.

1 Like

Thanks for the explanation. I tried it but get:

a2enmod php8.2-fpm
ERROR: Module php8.2-fpm does not exist!

No clue why. :man_shrugging:
Edit: Strange, it has worked before i think.
Edit2: Side note, update to NC27 is now also possible on stable channel after update debian and PHP!

Ah sorry, it is a config, not a module:

a2enconf php8.2-fpm
1 Like

Ah perfect, now it has worked! :+1:
I will edit my post.

After the relatively soft landing before, I put my helmet on and jumped again… :sunglasses:
On the second server, php8.2 was already installed after the debian upgrade. So all i had to do is:

a2enmod mpm_event
a2enconf php8.2-fpm
systemctl restart apache2

And then start the NC update.
Works fine so far. :+1:

1 Like

I updated more instances and it worked fine. But now, with the most important one, I’m stuck. :astonished:
The update command has updated from 25.0.7 to 25.0.8. The problem now is that I can not update to 26.x.x because this is not available. It says 25.0.8 is the latest.
Any idea how to get him to continue to update to 26.x.x?

This is expected if there is a newer subversion available. Easiest is to apply the latest offered update before doing the Debian/PHP upgrade.

However, you can apply the NC 25.0.8 update now, re-apply the versioncheck.php patch for PHP 8.2 support and should then be offered NC26. It should be also possible to skip the patch and use the CLI updater instead:

sudo -u www-data php /var/www/nextcloud/updater/updater.phar