How to: Install Nextcloud with an NFS data directory

From Thomas-Krenn-Wiki
Jump to navigation Jump to search

This article describes how to install Nextcloud Server on Ubuntu 26.04 LTS. Apache with PHP-FPM is used as the web server, while MariaDB provides the required database.

The actual Nextcloud user data is stored on an NFS-mounted storage system. The NFS storage is used as the primary Nextcloud data directory and is not integrated through the Nextcloud “External Storage” app.

This guide uses the following example values:

  • Nextcloud address: cloud.example.com
  • NFS server: nfs.example.com
  • NFS export: /nextcloud
  • Local NFS mount point: /srv/nextcloud-data
  • Nextcloud directory: /var/www/nextcloud
  • Database name: nextcloud
  • Database user: nextcloud

Adjust these values to match your environment.

Note: In this setup, the NFS storage is part of the primary Nextcloud storage. If the NFS server is unavailable, the Nextcloud data directory will also be unavailable.

Requirements

The following components are required for this guide:

  • Ubuntu Server 26.04 LTS, 64-bit
  • Apache 2.4
  • PHP 8.5 with PHP-FPM
  • MariaDB 11.8
  • Redis
  • An accessible NFSv4 export
  • A DNS record for the Nextcloud domain
  • TCP ports 80 and 443 must be reachable

For a small installation, the following resources can be used as an example:

  • 4 vCPUs
  • 4 GiB RAM
  • At least 20 GiB of local storage for the operating system, Nextcloud application, database and logs
  • Separate storage for the Nextcloud data directory

The actual resource requirements depend on factors such as the number of users, installed apps, number of files and concurrent access.

Important: NFS storage does not replace a backup. A complete backup must include at least the Nextcloud data directory, the MariaDB database and the Nextcloud configuration.

Preparing the system

The following commands are executed as the root user.

First update the operating system:

apt update
apt full-upgrade -y

If a new kernel was installed, restart the system:

reboot

Then verify the installed Ubuntu version:

cat /etc/os-release

The output should contain the following information, among other values:

VERSION_ID="26.04"
VERSION_CODENAME=resolute

Installing the required packages

Install Apache, MariaDB, PHP 8.5, Redis and the required PHP extensions:

apt install -y \
    apache2 \
    mariadb-server \
    php8.5-fpm \
    php8.5-cli \
    php8.5-common \
    php8.5-curl \
    php8.5-gd \
    php8.5-gmp \
    php8.5-imagick \
    php8.5-intl \
    php8.5-mbstring \
    php8.5-mysql \
    php8.5-xml \
    php8.5-zip \
    php8.5-bcmath \
    php8.5-bz2 \
    php8.5-apcu \
    php8.5-redis \
    redis-server \
    nfs-common \
    cron \
    bzip2 \
    wget

Enable and start the required services:

systemctl enable --now \
    apache2 \
    mariadb \
    php8.5-fpm \
    redis-server \
    cron

Verify the installed PHP version:

php8.5 --version

The output should begin with PHP 8.5.

The loaded PHP modules can be checked with the following command:

php8.5 -m

The following modules should be present, among others:

apcu
curl
dom
fileinfo
gd
gmp
imagick
intl
mbstring
mysqli
openssl
pdo_mysql
redis
SimpleXML
xml
xmlreader
xmlwriter
zip

Configuring PHP 8.5

Nextcloud requires suitable PHP settings for both PHP-FPM and command-line PHP calls.

Configuring PHP-FPM

Create a dedicated PHP configuration file for Nextcloud:

nano /etc/php/8.5/fpm/conf.d/99-nextcloud.ini

Add the following configuration:

memory_limit = 512M
upload_max_filesize = 10G
post_max_size = 10G
max_execution_time = 3600
max_input_time = 3600
output_buffering = 0

The values for upload_max_filesize and post_max_size determine the maximum file size that can be uploaded through the web interface. Adjust these values to suit your environment if required.

Configuring PHP CLI

The PHP command-line interface is used for cron jobs, maintenance tasks and the Nextcloud updater.

Create the following configuration file:

nano /etc/php/8.5/cli/conf.d/99-nextcloud.ini

Add the following content:

memory_limit = 512M
apc.enable_cli = 1

Verify the configuration:

php8.5 --ini
php8.5 -i | grep -E 'memory_limit|apc.enable_cli'

Restart PHP-FPM:

systemctl restart php8.5-fpm

Check the service status:

systemctl status php8.5-fpm

Setting up the NFS data directory

Creating the mount point

Create the local mount point:

mkdir -p /srv/nextcloud-data

Configuring the NFS mount

Add the following line to /etc/fstab:

nfs.example.com:/nextcloud /srv/nextcloud-data nfs4 rw,hard,_netdev,x-systemd.automount 0 0

Adjust the NFS server and export path to match your environment.

Reload the systemd configuration:

systemctl daemon-reload

Access the mount point to trigger the automatic mount:

ls -la /srv/nextcloud-data

Alternatively, the mount can be triggered manually:

mount /srv/nextcloud-data

Verify that the NFS file system has been mounted:

findmnt /srv/nextcloud-data

Example:

TARGET                  SOURCE                         FSTYPE OPTIONS
/srv/nextcloud-data     nfs.example.com:/nextcloud    nfs4   rw,relatime,...

Only continue with the installation if /srv/nextcloud-data is actually mounted as an NFS file system.

Setting permissions

Apache and PHP-FPM run as the www-data user by default on Ubuntu.

Check its UID and GID:

id www-data

By default, Ubuntu uses UID and GID 33 for www-data.

The NFS directory must allow the www-data user to write to it. If NFS root_squash is enabled, ownership usually cannot be changed from the Nextcloud server. In this case, set the permissions directly on the NFS server.

Example on the NFS server:

chown -R 33:33 /path/to/export/nextcloud
chmod 0750 /path/to/export/nextcloud

Then perform a write test on the Nextcloud server as the www-data user:

sudo -u www-data touch /srv/nextcloud-data/.write-test
sudo -u www-data rm /srv/nextcloud-data/.write-test

If this test fails, correct the NFS export settings, UID/GID mapping or file system permissions before continuing.

Note: The data directory should be used exclusively by Nextcloud. Files should not be modified directly on the NFS share in parallel.

Making Apache and PHP-FPM depend on the NFS mount

To prevent the relevant services from starting without the data directory being available, systemd dependencies can be configured.

First create a dependency for Apache:

systemctl edit apache2

Add the following configuration:

[Unit]
RequiresMountsFor=/srv/nextcloud-data
Wants=network-online.target
After=network-online.target

Then create the corresponding dependency for PHP-FPM:

systemctl edit php8.5-fpm

Add the following configuration there as well:

[Unit]
RequiresMountsFor=/srv/nextcloud-data
Wants=network-online.target
After=network-online.target

Reload the systemd configuration:

systemctl daemon-reload

Check the configured dependencies:

systemctl cat apache2
systemctl cat php8.5-fpm

Configuring MariaDB

Setting the transaction isolation level

Nextcloud requires the READ-COMMITTED transaction isolation level for MySQL or MariaDB.

Create the following configuration file:

nano /etc/mysql/mariadb.conf.d/99-nextcloud.cnf

Add the following content:

[mysqld]
transaction-isolation = READ-COMMITTED

If MariaDB binary logging is enabled, the ROW format must also be used:

[mysqld]
transaction-isolation = READ-COMMITTED
binlog_format = ROW

Restart MariaDB:

systemctl restart mariadb

Verify the configured transaction isolation level:

mariadb -e "SHOW VARIABLES LIKE 'transaction_isolation';"

The output should contain the following value:

READ-COMMITTED

Creating the database and user

Open the MariaDB console:

mariadb

Create the database and a database user that can only connect locally:

CREATE DATABASE nextcloud
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_general_ci;

CREATE USER 'nextcloud'@'localhost'
    IDENTIFIED BY 'SECURE-DATABASE-PASSWORD';

GRANT ALL PRIVILEGES
    ON nextcloud.*
    TO 'nextcloud'@'localhost';

FLUSH PRIVILEGES;
EXIT;

Replace SECURE-DATABASE-PASSWORD with a long, random password used exclusively for this database.

Because MariaDB and Nextcloud are installed on the same server, the user is deliberately restricted to localhost.

Test the login:

mariadb -u nextcloud -p -h localhost nextcloud

Exit the MariaDB console afterwards:

EXIT;

Installing Nextcloud

At the time this article was created, Nextcloud 34.0.1 was the current stable version.

Before performing a later installation, check whether a newer version is available within the supported Nextcloud release branch.

Download the Nextcloud archive and the corresponding SHA-256 checksum:

cd /tmp

NEXTCLOUD_VERSION="34.0.1"

wget https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2
wget https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.sha256

Verify the integrity of the archive:

sha256sum -c nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.sha256

The output must contain OK:

nextcloud-34.0.1.tar.bz2: OK

Extract Nextcloud:

tar -xjf nextcloud-${NEXTCLOUD_VERSION}.tar.bz2
mv nextcloud /var/www/nextcloud

Set the owner:

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

Check the permissions:

ls -ld /var/www/nextcloud

After a successful installation, the downloaded archive files can optionally be removed:

rm -f /tmp/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2
rm -f /tmp/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.sha256

Configuring Apache with PHP-FPM

This guide uses a dedicated subdomain for Nextcloud:

cloud.example.com

Enable the required Apache modules:

a2enmod \
    proxy_fcgi \
    setenvif \
    rewrite \
    headers \
    env \
    dir \
    mime \
    ssl \
    http2

Enable the PHP 8.5 FPM configuration:

a2enconf php8.5-fpm

Create the Apache configuration:

nano /etc/apache2/sites-available/nextcloud.conf

Add the following configuration:

<VirtualHost *:80>
    ServerName cloud.example.com
    DocumentRoot /var/www/nextcloud

    <Directory /var/www/nextcloud/>
        Require all granted
        AllowOverride All
        Options FollowSymLinks

        <IfModule mod_dav.c>
            Dav off
        </IfModule>

        SetEnv HOME /var/www/nextcloud
        SetEnv HTTP_HOME /var/www/nextcloud
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/nextcloud-error.log
    CustomLog ${APACHE_LOG_DIR}/nextcloud-access.log combined
</VirtualHost>

Replace cloud.example.com with the actual DNS name of the Nextcloud installation.

Enable the Nextcloud site:

a2ensite nextcloud.conf

If the default Apache site is no longer required, it can be disabled:

a2dissite 000-default.conf

Check the Apache configuration:

apache2ctl configtest

If the configuration is valid, the following output is displayed:

Syntax OK

Restart Apache and PHP-FPM:

systemctl restart php8.5-fpm
systemctl restart apache2

Check both services:

systemctl status php8.5-fpm
systemctl status apache2

Configuring the firewall

This step is only required if UFW is used on the server.

Before making changes, ensure that SSH remains allowed:

ufw allow OpenSSH

Allow HTTP and HTTPS:

ufw allow 'Apache Full'

Check the rules:

ufw status

Example:

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Apache Full                ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Apache Full (v6)           ALLOW       Anywhere (v6)

Setting up HTTPS

Nextcloud should only be accessible over HTTPS on production systems.

The following requirements apply for a publicly trusted certificate:

  • The domain points to the Nextcloud server.
  • TCP port 80 is reachable for certificate validation.
  • TCP port 443 is reachable for subsequent HTTPS access.

Install Certbot and the Apache plugin:

apt install -y certbot python3-certbot-apache

Request the certificate:

certbot --apache --redirect -d cloud.example.com

Certbot configures the certificate and redirects HTTP requests to HTTPS.

Test automatic certificate renewal:

certbot renew --dry-run

Check the Certbot timer:

systemctl status certbot.timer

If a reverse proxy or load balancer is already placed in front of Nextcloud, TLS termination can alternatively take place there. In that case, the Nextcloud settings for trusted proxies and forwarded headers must also be configured correctly.

Self-signed certificates should only be used in isolated internal environments where the certificate can be added as trusted on all clients.

Completing the installation in the browser

Open the Nextcloud domain in a browser:

https://cloud.example.com/

Enter the following information in the installation dialog.

Administrator account

Create an administrator account with a secure password used exclusively for Nextcloud.

Data directory

Use the following path as the data directory:

/srv/nextcloud-data

Database

Select MariaDB or MySQL and use the following values:

  • Database user: nextcloud
  • Database password: the password defined previously
  • Database name: nextcloud
  • Database host: localhost

Then start the installation.

Configuring background jobs

Nextcloud requires background jobs to be executed regularly. Cron should be used for server installations.

Create the following cron file:

nano /etc/cron.d/nextcloud

Add the following content:

*/5 * * * * www-data /usr/bin/php8.5 -f /var/www/nextcloud/cron.php

Set the correct file permissions:

chmod 0644 /etc/cron.d/nextcloud

Enable cron mode in Nextcloud:

sudo -u www-data php8.5 /var/www/nextcloud/occ background:cron

Restart the cron service:

systemctl restart cron

Check the entry:

cat /etc/cron.d/nextcloud

Test the cron job manually once:

sudo -u www-data php8.5 -f /var/www/nextcloud/cron.php

The status of the background jobs can later be checked in Nextcloud under “Administration settings” → “Basic settings”.

Configuring APCu and Redis

APCu is used for the local application cache. Redis handles transactional file locking and can also be used as a distributed cache.

Open the Nextcloud configuration:

nano /var/www/nextcloud/config/config.php

Add the following entries inside the $CONFIG array:

'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',

'redis' => [
    'host' => '127.0.0.1',
    'port' => 6379,
    'timeout' => 0.0,
],

Ensure that all entries are placed inside the existing $CONFIG array and that preceding entries are separated correctly with commas.

Restart PHP-FPM and Apache:

systemctl restart php8.5-fpm
systemctl restart apache2

Check the Redis service:

systemctl status redis-server

Test the connection:

redis-cli ping

The expected response is:

PONG

Enabling pretty URLs

Pretty URLs remove the index.php component from Nextcloud URLs.

First set the complete Nextcloud URL:

sudo -u www-data php8.5 /var/www/nextcloud/occ \
    config:system:set overwrite.cli.url \
    --value="https://cloud.example.com"

Then set the rewrite base:

sudo -u www-data php8.5 /var/www/nextcloud/occ \
    config:system:set htaccess.RewriteBase \
    --value="/"

Update the Nextcloud .htaccess file:

sudo -u www-data php8.5 \
    /var/www/nextcloud/occ maintenance:update:htaccess

Reload Apache:

systemctl reload apache2

Nextcloud URLs should now be displayed without index.php.

Verifying the installation

First check the Nextcloud status:

sudo -u www-data php8.5 /var/www/nextcloud/occ status

A successful installation returns information similar to the following:

installed: true
maintenance: false
needsDbUpgrade: false
version: 34.0.1.0
versionstring: 34.0.1

Also check the relevant services:

systemctl status apache2
systemctl status php8.5-fpm
systemctl status mariadb
systemctl status redis-server
systemctl status cron

Check the NFS mount again:

findmnt /srv/nextcloud-data

Verify that Nextcloud can still write to the data directory:

sudo -u www-data touch /srv/nextcloud-data/.write-test
sudo -u www-data rm /srv/nextcloud-data/.write-test

Check the Nextcloud configuration:

sudo -u www-data php8.5 \
    /var/www/nextcloud/occ config:list system

Finally, open “Administration settings” → “Overview” in Nextcloud. Missing PHP modules, cache issues, failed background jobs and other configuration problems are displayed there.

Optional configurations

Setting the default phone region

If phone numbers without an international country code are used in Nextcloud, a default region can be configured.

For Germany, use:

sudo -u www-data php8.5 /var/www/nextcloud/occ \
    config:system:set default_phone_region \
    --value="DE"

Configuring the maintenance window

Nextcloud can run resource-intensive daily background jobs preferentially during a maintenance window.

The following example sets the start of the maintenance window to 01:00 UTC:

sudo -u www-data php8.5 /var/www/nextcloud/occ \
    config:system:set maintenance_window_start \
    --type=integer \
    --value=1

Running available repairs

After updates or configuration changes, the Nextcloud repair routines can be executed:

sudo -u www-data php8.5 \
    /var/www/nextcloud/occ maintenance:repair

Operational notes

At least the following points should be considered for ongoing operation:

  • Install security updates regularly
  • Update Nextcloud and installed apps regularly
  • Back up the MariaDB database
  • Back up the NFS data directory
  • Back up /var/www/nextcloud/config
  • Monitor NFS availability
  • Monitor local disk space
  • Monitor Apache, PHP-FPM, MariaDB and Redis
  • Check the Nextcloud administration overview regularly
  • Check background jobs regularly
  • Test restoring from existing backups

Relevant log files include:

/var/log/apache2/nextcloud-error.log
/var/log/apache2/nextcloud-access.log
/var/log/php8.5-fpm.log
/srv/nextcloud-data/nextcloud.log

The systemd logs can also be displayed with the following commands:

journalctl -u apache2
journalctl -u php8.5-fpm
journalctl -u mariadb
journalctl -u redis-server

Displaying the Nextcloud version

The currently installed Nextcloud version can be checked at any time:

sudo -u www-data php8.5 /var/www/nextcloud/occ status

Displaying the PHP version

The command-line PHP version can be checked as follows:

php8.5 --version

The PHP-FPM version used by Apache can be checked through the service:

systemctl status php8.5-fpm

Related articles

Log4shell zero-day vulnerability
Partition Alignment detailed explanation
WireGuard Basics