The complete guide to installing Nextcloud on Debian 10

Today we’re installing the free and open source cloud platform Nextcloud on a machine running Debian 10. Nextcloud is, in a nutshell, a secure self-hosted replacement for Dropbox, Google Docs and Google Calendar. You should own your data – not the big companies. The guide somewhat resembles the WordPress how-to – as we did then we set up a database, a web server and a website written in PHP that is meant to sit behind a reverse proxy giving it a secure connection to the internet.

Just a note: there are more simple ways of doing this, either by using Docker (link here) or by using Snaps (link here) – but you won’t get the same ability to tweak, configure or add third party apps. And most importantly, you won’t learn how it works.

I. The Database

We start off with installing a relational database management system.

apt -y install mariadb-server mariadb-client

Then we set it up, use a long secure password for the root user.


Now it’s time to create the database and database user Nextcloud will be using.

mysql -u root -p
CREATE USER 'nextcloud_user'@'localhost' IDENTIFIED BY 'super-secure-password'; CREATE DATABASE nextcloud_db; GRANT ALL PRIVILEGES ON nextcloud_db.* TO 'nextcloud_user'@'localhost'; FLUSH PRIVILEGES; QUIT
Code language: SQL (Structured Query Language) (sql)

II. The Web Server

Since Nextcloud is written in PHP, we have to install it (and some extensions).

apt -y install php php-{cli,xml,zip,curl,gd,cgi,mysql,mbstring,imagick,intl}

The last thing we have to install is our web server that will be hosting our Nextcloud instance.

apt -y install apache2 libapache2-mod-php

With that done we have to make a few adjustments to the PHP settings, search for and replace the following values in /etc/php/7.3/apache2/php.ini.

nano /etc/php/7.3/apache2/php.ini
date.timezone = Europe/Stockholm memory_limit = 512M upload_max_filesize = 500M post_max_size = 500M max_execution_time = 300

It’s time to download the latest version of Nextcloud (at the time of writing it is 18).

wget unzip
Code language: JavaScript (javascript)

Then we place it in our website folder (by default /var/www/html) and change the permissions, but first we delete the default website Apache installed.

rm /var/www/html/index.html cd nextcloud/ mv * /var/www/html/ mv .htaccess /var/www/html/ mv .user.ini /var/www/html/ chown -R www-data:www-data /var/www/html chmod -R 755 /var/www/html
Code language: JavaScript (javascript)

Since it’s more secure not storing your data in a subfolder to /var/www we create a dedicated folder for Nextcloud data outside of it.

mkdir /nextcloud-data chown -R www-data:www-data /nextcloud-data

Now we edit our Apache configuration so that it looks something like this – use your own email and website address.

nano /etc/apache2/sites-available/nextcloud.conf
<VirtualHost *:80> # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName # specifies what hostname must appear in the request's Host: header to # match this virtual host. For the default virtual host (this file) this # value is not decisive as it is used as a last resort host regardless. # However, you must set it for any further virtual host explicitly. #ServerName ServerAdmin DocumentRoot /var/www/html ServerName <Directory /var/www/html/> Options +FollowSymlinks AllowOverride All Require all granted <IfModule mod_dav.c> Dav off </IfModule> SetEnv HOME /var/www/html SetEnv HTTP_HOME /var/www/html </Directory> # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, # error, crit, alert, emerg. # It is also possible to configure the loglevel for particular # modules, e.g. #LogLevel info ssl:warn ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined # For most configuration files from conf-available/, which are # enabled or disabled at a global level, it is possible to # include a line for only one particular virtual host. For example the # following line enables the CGI configuration for this host only # after it has been globally disabled with "a2disconf". #Include conf-available/serve-cgi-bin.conf </VirtualHost>
Code language: PHP (php)

Then we activate our configuration and enable some needed Apache modules with the following commands.

unlink /etc/apache2/sites-enabled/000-default.conf ln -s /etc/apache2/sites-available/nextcloud.conf /etc/apache2/sites-enabled/ a2enmod rewrite a2enmod headers a2enmod env a2enmod dir a2enmod mime systemctl restart apache2
Code language: JavaScript (javascript)

If your IP address for the server is and your website address is, you have to do the following edits to the Nextcloud config in order to be able to access the website.

nano /var/www/html/config/config.php
Code language: JavaScript (javascript)
'trusted_domains' => array ( 0 => '', 1 => '', 2 => '', ),
Code language: PHP (php)

The website is now accessible! Head over to it by writing the servers IP address in your browser ( in our example case). Use the database account we created (nextcloud_user), the database (nextcloud_db) and our data folder (/nextcloud-data).

We could now say that we’re finished, but we are not! There still is some tweaks to be made…

III. Additional Fixes

If you head to http://your-ip-address/settings/admin/overview you can see if there are some errors. One I got was:

The database is missing some indexes. Due to the fact that adding indexes on big tables could take some time they were not added automatically. By running “occ db:add-missing-indices” those missing indexes could be added manually while the instance keeps running. Once the indexes are added queries to those tables are usually much faster.

This was fixed with the following commands.

cd /var/www/html/ apt install sudo sudo -u www-data php occ db:add-missing-indices
Code language: JavaScript (javascript)

Another error I got was:

Some columns in the database are missing a conversion to big int. Due to the fact that changing column types on big tables could take some time they were not changed automatically. By running ‘occ db:convert-filecache-bigint’ those pending changes could be applied manually. This operation needs to be made while the instance is offline. For further details read the documentation page about this.

This was fixed with:

sudo -u www-data php occ db:convert-filecache-bigint
Code language: CSS (css)

Then in order to get “pretty URL:s” we edit the Nextcloud config.

nano /var/www/html/config/config.php
Code language: JavaScript (javascript)
'overwrite.cli.url' => '', 'overwritehost' => '', 'htaccess.RewriteBase' => '/',
Code language: PHP (php)

Then we update Nextcloud with our new settings.

cd /var/www/html/ sudo -u www-data php occ maintenance:update:htaccess
Code language: JavaScript (javascript)

We’re almost done, but first we have to change how Nextcloud handles background tasks from using ajax to cron. We do this by adding a cronjob and then changing it in the website settings (http://your-ip-address/settings/admin).

crontab -u www-data -e
*/5 * * * * php -f /var/www/html/cron.php
Code language: JavaScript (javascript)

The final step in our journey is to set up caching, it will greatly improve the performance of your cloud. The caching solution we will be using is APCu, let’s install it!

apt install php-apcu systemctl restart apache2

After installing APCu we have to enable it, by writing the following in /var/www/html/config/config.php.

nano /var/www/html/config/config.php
Code language: JavaScript (javascript)
'memcache.local' => '\OC\Memcache\APCu',
Code language: PHP (php)

Then we enable it in the PHP settings by adding a line to /etc/php/7.3/apache2/php.ini.

nano /etc/php/7.3/apache2/php.ini

And that is it! You are now the owner of your very own cloud. 🙂

P.S. if you find something wrong with the guide please tell me so I can fix it!