This guide will take you through a Nextcloud installation intended for a small friends/family instance. It focuses on accomplishing the installation through the Terminal. As of the writing of this guide, Nextcloud version 24.05 was installed. Later version of Nextcloud may make parts of the guide obsolete.
Pre-Requisites
- Linux operating system meeting Nextcloud requirements. In this guide I use Ubuntu 22.04, with ssh enabled.
- Memory: although Nextcloud recommends a minimum of 512 MB, I provisioned the Virtual Machine hosting Nextcloud with 8 GB.
- CPU: Nextcloud does not recommend anything specific to CPU, so I have allocated 4 CPU cores, although depending on load you may only need fewer cores or more.
- Disk Space: completely depends on how much storage you want to provision for your users. Given my goal of a small friends/family instance, I used a 500 GB virtual hard drive, stored on an SSD. External storage can be added later.
- A domain registered to you, ie. mydomain.com.
- Another Linux system intended to host Nginx and it’s IP address.
Sources
Although this guide details a Nextcloud instance suited to my use case, I leaned heavily on other guides and take no credit for their work.
- Nextcloud official documentation
- Using Rsync to backup Nextcloud and more on Rsync
- Using Nginx as a reverse proxy
- Excellent guides on digitalocean.com
Install Nextcloud Pre-Requisites
Nextcloud requires a database, webserver and PHP runtime. To install the pre-requisites, open up a terminal (local or remote through ssh) and execute the following commands.
First, update the system:
sudo apt update && sudo apt upgrade
Next, install Apache as the webserver, mariadb as the database, and the latest PHP runtime and modules:
sudo apt install apache2 mariadb-server libapache2-mod-php php-gd php-mysql php-curl php-mbstring php-intl php-gmp php-bcmath php-xml php-imagick php-zip php-imagick imagemagick
Finally, create the database for Nextcloud to use. In this case, chose a name for the database user and use a password generator, to generate and store a strong password for the user. Before executing the command below, replace the two instances of mydbuser and one instance mydbpassword with the user and password chosen. The database created is named nextcloud.As stated in this article, you can browse your selection of available deals on smartphones and top brands and explore the cell phone service plans that best suit your needs.
sudo mysql
CREATE USER 'mydbuser'@'localhost' IDENTIFIED BY 'mydbpassword';
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON nextcloud.* TO 'mydbuser'@'localhost';
FLUSH PRIVILEGES;
Install Nextcloud
From the terminal we will execute a number of commands to install Nextcloud.
First, install curl so we can use wget to get the latest stable Nextcloud release.
sudo apt install curl
Next, download the latest stable Nextcloud release, along with Nextcloud’s public keys so we can validate the download. All files will be downloaded to the current working directory in the Terminal session. Change the directory (cd command) if you’d like the files downloaded elsewhere.
wget -P . https://download.nextcloud.com/server/releases/latest.tar.bz2
wget -P . https://download.nextcloud.com/server/releases/latest.tar.bz2.md5
wget -P . https://download.nextcloud.com/server/releases/latest.tar.bz2.asc
wget -P . https://nextcloud.com/nextcloud.asc
Now verify the download:
md5sum -c latest.tar.bz2.md5 < latest.tar.bz2
gpg --import nextcloud.asc
gpg --verify latest.tar.bz2.asc latest.tar.bz2
Provided all checks out, extract the Nexcloud release. The files will be extracted to your current working directory.
tar -xjvf latest.tar.bz2
Copy the extracted files to where you’d like Nextcloud to live. In the default case, copy them to /var/www.
sudo cp -r nextcloud /var/www
Provide the Apache webserver user www-data access to the nextcloud folder.
sudo chown -R www-data:www-data /var/www/nextcloud
Install additional Apache modules required by Nextcloud.
sudo a2enmod rewrite && sudo a2enmod headers && sudo a2enmod env && sudo a2enmod dir && sudo a2enmod mime && sudo a2enmod ssl && sudo a2ensite default-ssl
In this specific scenario, Nginx is on another server, configured as a reverse proxy (covered later in the guide) with letsencrypt to handle SSL certificates and to sort traffic to Nextcloud, Synapse, and other services. As the Nginx server handles the SSL certificates, I still want to use SSL between it and the Nextcloud server on the LAN otherwise Collabora Office won’t work and it’ll throw mixed content warnings. To solve this, Apache on this Nextcloud instance will use a self-signed certificate.
Create a self-signed certificate, filling in the appropriate data when asked (country code, etc.):
sudo openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt
Create a nextcloud.conf file for Apache.
sudo touch /etc/apache2/sites-available/nextcloud.conf
Add the Nextcloud SSL site information, and a redirect from port 80 to port 443. Replace serveripaddress with the ip address of your nextcloud server. This will be changed after running through the initial Nexcloud configuration.
<VirtualHost *:443>
DocumentRoot /var/www/nextcloud/
ServerName serveripaddress
SSLEngine on
SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
<Directory /var/www/nextcloud/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName serveripaddress
Redirect / https://serveripaddress
</VirtualHost>
Hit ctrl+x to save the file.
Enable nexcloud.conf and reload Apache.
sudo a2ensite nextcloud.conf
sudo systemctl reload apache2
Nexcloud relies on cron jobs to take care of backend tasks. This requires some manual configuration. Run the following in Terminal:
sudo crontab -u www-data -e
Copy and paste the following into crontab:
*/5 * * * * php -f /var/www/nextcloud/cron.php
Save the crontab.
Out of the box filesize limits in PHP are often far too low, so let’s increase them. First, determine the version of PHP running:
php -v
As of the writing of this guide, the PHP version on my system is 8.1.9, thus, I use ‘8.1’ in the command below. Use the appropriate version for your system.
sudo nano /etc/php/8.1/apache2/php.ini
You may want to set different max sizes than I have below. Add/replace:
upload_max_filesize=10G
post_max_size=10G
memory_limit=512M
opcache.interned_strings_buffer=128M
Rinse and repeat for the php.ini file in the cli directory.
sudo nano /etc/php/8.1/cli/php.ini
Finally, edit Nextcloud’s php configuration file.
sudo nano /var/www/nextcloud/config/config.php
In order for Nextcloud to trust the nginx proxy (set up later in this guide) and to ensure Nextcloud doesn’t complain about no default phone region being set, add the following in the ‘$config = array (‘ block replacing the nginxipaddress and mydomain.com with the ip address of the nginx system.
'trusted_domains' =>
array (
0 => 'mydomain.com',
1 => 'nginxipaddress',
2 => '127.0.0.1'
),
'trusted_proxies' =>
array (
1 => 'nginxipaddress',
2 => '127.0.0.1',
3 => 'mydomain.com',
),
'default_phone_region' => 'US'
Now that all of the initial configuration is complete, reboot the system.
sudo reboot
Installation Wizard
To run the wizard either run the appropriate occ command (see step three here) or visit https://yournextcloudip. Although this guide is heavily Terminal based, I prefer running the installation wizard through a web browser. Now, your browser will complain about the self-signed certificate but proceed anyway. You’ll need to supply the database name, ‘nextcloud’, the database username and it’s password (created in the install pre-requisites section). Additionally, it will ask you to create an admin user. Do so and use your password manager to generate and save a strong password for the admin user.
NGINX Reverse Proxy and LetsEncrypt
In my scenario, I have an Nginx server routing traffic behind my router firewall. To setup Nginx, all that is needed is a vanilla install of the Linux distro of your choice (I’ll stick with Ubuntu for this guide).
First, in your router configuration, enable port forwarding for ports 80 and 443 to be forwarded to the ip address of your nginx server. To test if it works, hit your external ip from a web browser. You should be greeted by a friendly nginx page.
Second, in your domain registrar, create an A record for mydomain.com, replacing mydomain.com with the domain you purchased as part of the prerequisites, pointing it the the WAN ip address of the network on which Nextcloud and Nginx reverse proxy reside. Next, create a CNAME record, the name of which is nextcloud.mydomain.com and the content in mydomain.com. You don’t have to use ‘nextcloud’ but whatever you choose should be reflected when setting up nginx below.
Incorrect configuration of the first two steps will cause certbot to fail when trying to generate an SSL certificate for your site.
Open a Terminal to the system (local or through SSH). Type the following to install Nginx:
sudo apt install nginx
Now start the Nginx service and enable it to run every time at system startup.
sudo systemctl start nginx.service
sudo systemctl enable nginx.service
Create a new virtual host configuration for your Nextcloud server.
sudo nano /etc/nginx/sites-available/nextcloud
In it, place the following, replacing the server_name with the FQDN on which you’d like to access your nextcloud instance. In the below example, I use nextcloud.mydomain.com. Additionally, replace all instances (7 in total) of nextcloudserverip with the local ip address of your nextcloud server. In the following step certbot will enable ssl.
server
{
listen 80;
server_name nextcloud.mydomain.com;
underscores_in_headers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# set max upload size and increase upload timeout:
client_max_body_size 512M;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Pagespeed is not supported by Nextcloud, so if your server is built
# with the `ngx_pagespeed` module, uncomment this line to disable it.
#pagespeed off;
# HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;
location /
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_hide_header Upgrade;
client_max_body_size 10000M;
proxy_set_header X-Forwarded-Proto $scheme;
# add_header Front-End-Https on;
# proxy_headers_hash_max_size 512;
# proxy_headers_hash_bucket_size 64;
# proxy_buffering off;
# proxy_redirect off;
# proxy_max_temp_file_size 0;
}
location /.well-known/carddav
{
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav
{
return 301 $scheme://$host/remote.php/dav;
}
# static files
location ^~ /browser
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# WOPI discovery URL
location ^~ /hosting/discovery
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# Capabilities
location ^~ /hosting/capabilities
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# main websocket
location ~ ^/cool/(.*)/ws$
{
proxy_pass https://nextcloudserverip;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_read_timeout 36000s;
}
# download, presentation and image upload
location ~ ^/(c|l)ool
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# Admin Console websocket
location ^~ /cool/adminws
{
proxy_pass https://nextcloudserverip;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_read_timeout 36000s;
}
}
Add the repository for certbot and install it.
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get install certbot python3-certbot-nginx
Run certbot to generate the certificate:
sudo certbot --nginx
Choose your nextcloud.mydomain.com site by typing in the corresponding number. Allow it to redirect your port 80 traffic. The resulting nextcloud configuration should look something like this:
server
{
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/nextcloud.mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/nextcloud.mydomain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name nextcloud.mydomain.com;
underscores_in_headers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# set max upload size and increase upload timeout:
client_max_body_size 512M;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Pagespeed is not supported by Nextcloud, so if your server is built
# with the `ngx_pagespeed` module, uncomment this line to disable it.
#pagespeed off;
# HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;
location /
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_hide_header Upgrade;
client_max_body_size 10000M;
proxy_set_header X-Forwarded-Proto $scheme;
# add_header Front-End-Https on;
# proxy_headers_hash_max_size 512;
# proxy_headers_hash_bucket_size 64;
# proxy_buffering off;
# proxy_redirect off;
# proxy_max_temp_file_size 0;
}
location /.well-known/carddav
{
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav
{
return 301 $scheme://$host/remote.php/dav;
}
# static files
location ^~ /browser
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# WOPI discovery URL
location ^~ /hosting/discovery
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# Capabilities
location ^~ /hosting/capabilities
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# main websocket
location ~ ^/cool/(.*)/ws$
{
proxy_pass https://nextcloudserverip;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_read_timeout 36000s;
}
# download, presentation and image upload
location ~ ^/(c|l)ool
{
proxy_pass https://nextcloudserverip;
proxy_set_header Host $http_host;
}
# Admin Console websocket
location ^~ /cool/adminws
{
proxy_pass https://nextcloudserverip;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_read_timeout 36000s;
}
}
server
{
if ($host = nextcloud.mydomain.com)
{
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name nextcloud.mydomain.com;
return 404; # managed by Certbot
}
To quote Samuel Jackson from Jurassic park: “hold on to your butts”. Open a web browser and go to https://nextcloud.mydomain.com and you should see your Nextcloud instance login page.
Email Settings
It’s useful to setup email so you can get notifications from your Nextcloud instance. In my case, I am a protonmail user and they provide a bridge that you can install to send encrypted emails. I detail setting up the bridge in another post.
In order to get the protonmail bridge to play nicely with Nextcloud, you’ll need to manually edit Mailer.php.
sudo nano /var/www/nextcloud/lib/private/Mail/Mailer.php
In the getSmtpInstance() function, this following should be added around line 262.
$transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false)));
As the protonmail bridge uses a self-signed certificate this tells the Nextcloud mailer to trust self-signed certs.
Now, in Nextcloud Settings > Basic Settings, there is a section to enter in email settings. Open up the protonmail bridge and copy the relevant sections into the Nextcloud email settings. Once complete, hit save then send email.
Database Indices
Nextcloud recommends that you add database indices to improve performance. The larger your database, the longer the following command will take.
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
Running OCC commands
OCC is the command-line tool accompaning Nextcloud. For example, if your instance gets stuck in maintenance mode, you can disable maintenance mode via OCC.
sudo -u www-data php /var/www/nextcloud/occ
Backups
Data loss is no fun, thus backing up Nextcloud is crucial. There is a backup app in the app store that I have had no luck with as of the time of writing this (September 2022). Instead I take nightly SQL and Nextcloud directory dumps, and using Rsync, punt them to a file server on my network, then, using duplicati, compress and encrypt them and send them to the cloud.
Create a nextcloud_backup.sh script.
touch /home/cloudy/Documents/nextcloud_backup.sh
nano /home/cloudy/Documents/nextcloud_backup.sh
Add the following (sleep is to give the system a little breathing room between tasks), replacing YOURPASSWORD here with your database password:
#Nextcloud Backup Script sourced from https://web.archive.org/web/20180420224632/http://webgnuru.com:80/linux/rsync_incremental.php
sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --on
sleep 30
#The source directory:
SRC="/var/www/nextcloud/"
#The target directory:
TRG="/mnt/share/data"
#The rsync options:
OPT="-Aax"
#Execute the backup
mysqldump --single-transaction -h localhost -u nextcloudsdb -p'YOURPASSWORDHERE' nextcloud > /mnt/share/sql/nextcloud-sqlbkp_`date +"%Y%m%d"`.bak
sleep 30
rsync $OPT $SRC $TRG
#Give the system some breathing room
sleep 30
#Turn maintenance mode off
sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off
Hit ctrl+x to save the script. Now make the script executable.
chmod +x /home/cloudy/Documents/nextcloud_backup.sh
As my backup location is a Windows nextwork share, I need to install cifs-utils.
sudo apt-get install cifs-utils
Then make a directory where I can mount the Windows network share.
sudo mkdir /mnt/share
Create a file to store the credentials with read/write access to the share.
sudo nano /home/.smbcredentials
In it, place the actual credentials.
username=usernamewithshareaccess
password=itspassword
Ctrl+x to save. Now let’s test to see if we can mount the share (replace myshareip/Nextcloud with the actual ip and share name).
sudo mount.cifs //myshareip/Nextcloud /mnt/share -o credentials=/home/.smbcredentials
If it works, lets add an entry to fstab so it is automatically mounted on boot.
sudo nano //etc/fstab
Add the following at the end of the file, replacing myshareip/Nextcloud with your actual share IP and share name:
//myshareip/Nextcloud /mnt/share cifs credentials=/home/.smbcredentials 0 0
Ctrl+x to save.
Finally, add these four entries (changing timing if unsuitable). The first column indicates minutes, the second, which hour of the day a job run. Additionally it cleans out SQL backups oldaer than 30 days.
sudo crontab -e
25 2 * * * /usr/bin/find /mnt/share/sql -name "*.bak" -type f -mtime +30 -delete
30 3 * * * /home/cloudy/Documents/nextcloud_backup.sh | logger -t backup 2>&1
Ctrl+x to save.
External Storage, SMB
Getting Nextcloud to register a Windows network share (SMB) as external storage was a pain (Props to these guys who helped me through it). I found the following set of steps allowed me to successfully register a Windows network share.
Install libssmbclient-dev and smbclient.
sudo apt install libsmbclient-dev
sudo pecl install smbclient
Add a repository that has the phpsmbclient.
sudo su -c 'echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/newphp.list'
sudo apt-key adv --recv-keys --keyserver hkps://keyserver.ubuntu.com:443 4F4EA0AAE5267A6C
Now update.
sudo apt update
Install the phpsmblient corresponding to your installed version of php.
sudo apt install php8.1-smbclient
Restart Apache.
sudo systemctl restart apache2
Now attempt to add your Windows network share as external storage.
To Update DB User Password
To update your database user password, open a terminal and type:
sudo mysql
Then (replace newPass with your new password):
ALTER USER 'nextcloudsdb'@'localhost' IDENTIFIED BY 'newPass';
Next, update your new password in config/config.php:
sudo nano /var/www/nextcloud/config/config.php
Finally, reboot the system.
Troubleshooting
The Following files have failed the integrity check…
INVALID_HASH
You’ll want to replace the file(s) with the invalid hash with the correct files from the Nextcloud download that matches your Nextcloud version. I’ve seen this a few times upgrading major versions. For eaxmple, core/js/mimetypelist.js may prompt a warning, so using the following command to replace your old mimetypelist.js (this example pulls the latest from github, which may or may not match your current version so please double-check):
sudo rm /var/www/nextcloud/core/js/mimetypelist.js
sudo wget https://raw.githubusercontent.com/nextcloud/server/master/core/js/mimetypelist.js -P /var/www/nextcloud/core/js
EXTRA_FILE
Following an upgrade, I had a few apps on my instance which were not compatible with the new version and which must not have been fully removed. The complaint was the following two files: core/img/filetypes/dwb.svg and core/img/filetypes/drawio.svg. I removed them with the following command:
sudo rm /var/www/nextcloud/core/img/filetypes/dwb.svg
sudo rm /var/www/nextcloud/core/img/filetypes/drawio.svg