Install Nextcloud on Ubuntu and Debian with Nginx (LEMP)

Install Nextcloud 35 on Ubuntu 24.04, 26.04 or Debian 12 and 13 with Nginx, MariaDB and PHP-FPM: create the database, set up the vhost and enable HTTPS.

In this guide, we are going to set up Nextcloud on an Ubuntu or Debian server hosted with Nginx, MariaDB and PHP (LEMP stack). The steps are the same on every release covered here; only the PHP version changes, and Debian 12 needs one extra repository.

ReleasePHP (default repos)MariaDB (default repos)Extra steps
Ubuntu 26.04 LTS8.511.8none
Ubuntu 24.04 LTS8.310.11none
Debian 13 (Trixie)8.411.8none
Debian 12 (Bookworm)8.210.11add the Sury PHP repository

Current Nextcloud (35) supports PHP 8.3, 8.4 and 8.5 (8.5 recommended) and MariaDB 10.11, 11.4, 11.8 or 12.3; see the Nextcloud system requirements. The commands below were tested on all four releases.

Older releases. This guide was first written for Ubuntu 20.04, and earlier versions of it covered Debian 11, Ubuntu 22.04 and openSUSE Leap 15.3. Ubuntu 22.04 ships PHP 8.1 and MariaDB 10.6, neither of which Nextcloud 35 supports, so upgrade it to 24.04 rather than replacing both. Debian 11, Ubuntu 20.04 and openSUSE Leap 15.3 are end-of-life: upgrade them first.

Nextcloud is an Open Source suite of client-server software for creating and using file hosting services. It is a free self-hosted cloud storage solution similar to Dropbox, Google Drive, etc. With Nextcloud, you don’t have to worry about the pricey alternatives and since you will host your own files, you don’t have to worry about privacy or someone collecting your data.

Nextcloud can be installed on a private home server or a virtual private server in the cloud. Files can then be uploaded and then synced to a local desktop, laptop or even a smartphone. This way you have full control of your data.

Features of Nextcloud

  • Nextcloud has sync clients for Linux, Mac OS, Windows, Android and IOS
  • End to end encryption - files are encrypted while being uploaded to the server
  • Nextcloud is free and Open Source
  • Can be integrated with an online office suite (Collabora, OnlyOffice) so you can create and edit your doc, ppt, xls files directly from Nextcloud.
  • The app store contains hundreds of apps to extend functionality (like calendar app, notes-taking app, video conferencing app, etc).

Related Content:

Prerequisites

To follow along this guide, ensure that you have:

  • An up to date server running Ubuntu 24.04 or 26.04 LTS, or Debian 12 or 13
  • Internet access from the server
  • Root access from the server or user with sudo access
  • A DNS record pointing at the server if you want to reach Nextcloud by hostname (and you need one for HTTPS)

Ensure that the server packages are up to date

Let us make sure that our server packages are up to date with this command:

sudo apt update
sudo apt -y upgrade

While at it, let us also install some dependencies that we will require

sudo apt install -y unzip curl vim

Installing MariaDB

MariaDB is a popular Opensource relational management system. It is available in the default repositories as mariadb-server, and every release in the table above ships a version Nextcloud supports.

Install it with this command:

sudo apt install -y mariadb-server

MariaDB will be installed and started by default. Check the status with this

sudo systemctl status mariadb

Look for Active: active (running) near the top of the output, along with Status: "Taking your SQL requests now...". You can confirm the exact version with mariadb --version.

To ensure that mariadb starts on boot, enable it with this systemd command:

sudo systemctl enable mariadb

Once the service is running, you need to secure it. MariaDB provides a commandline utility that will do that:

sudo mariadb-secure-installation

The above command will take you through prompts to secure the instance: removing anonymous users, disallowing remote root login and dropping the test database.

Older guides call this mysql_secure_installation. MariaDB has renamed its client tools to mariadb-*, so prefer the new name.

Check more info on Installing and setting up MariaDB in this guide.

Creating a database user for Nextcloud

It is always recommended to have a dedicated user for each app that connects to the DB. Check out this guide on managing mysql permissions. We will set up a database, user and password to be used by nextcloud.

Connect to the database server. The root MariaDB account authenticates over a unix socket on Ubuntu and Debian, so sudo is enough and no password is needed:

sudo mariadb

At the prompt, create the database and a dedicated user:

CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'nextcloud_user'@'localhost' IDENTIFIED BY 'S0mStrongPa$$word';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Two things worth calling out:

  • utf8mb4 is not optional. Nextcloud stores filenames and comments as 4-byte UTF-8 (emoji included). Creating the database with the older default charset leads to “MySQL 4-byte support” warnings and truncation errors later.
  • Scope the user to localhost, not '%'. The database and Nextcloud are on the same host here, so there is no reason to accept connections from anywhere on the network. Only widen this if your database genuinely lives on another machine.

Replace S0mStrongPa$$word with a strong password of your own; you will need it in the setup wizard later.

Installing PHP

On Ubuntu 24.04, Ubuntu 26.04 and Debian 13 the default repositories already give you a supported PHP, so skip straight to the install command.

Debian 12 only: add the Sury PHP repository

Debian 12 ships PHP 8.2, which Nextcloud 35 no longer supports. Add the Sury PHP repository, maintained by Debian’s PHP packager, to get a current PHP:

sudo apt install -y lsb-release ca-certificates curl
sudo curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb
echo "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list
sudo apt update

With the repository in place, the unversioned php-* packages below install Sury’s default PHP (8.4 at the time of writing) instead of Debian’s 8.2.

Install PHP and the Nextcloud modules

sudo apt install -y \
  php-fpm \
  php-cli \
  php-mysql \
  php-gd \
  php-curl \
  php-zip \
  php-xml \
  php-mbstring \
  php-intl \
  php-bcmath \
  php-gmp \
  php-apcu

A few notes on that list:

  • php-mysql is mandatory. It provides the pdo_mysql driver. Without it the setup wizard cannot talk to MariaDB and fails at the database step.
  • php-dom and php-simplexml are both provided by php-xml, so installing it covers them.
  • php-json no longer exists as a separate package; JSON has been part of PHP core since 8.0.
  • bcmath, gmp and apcu are not strictly required, but Nextcloud’s setup checks warn about them; installing them up front keeps the admin overview clean.
  • For richer preview generation you can optionally add php-imagick.

The PHP version sets the FPM service name, the config path and the socket path, so capture it once:

PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
echo $PHP_VER

Expect 8.3 on Ubuntu 24.04, 8.4 on Debian 13 and on Debian 12 with Sury, and 8.5 on Ubuntu 26.04.

Nextcloud also wants a memory_limit of at least 512M, and PHP’s default upload limits (2M per file, 8M per request) are far below the 512M the Nginx config below allows. Set all three in the FPM config:

sudo sed -i -e 's/^memory_limit = .*/memory_limit = 512M/' \
  -e 's/^upload_max_filesize = .*/upload_max_filesize = 512M/' \
  -e 's/^post_max_size = .*/post_max_size = 512M/' /etc/php/$PHP_VER/fpm/php.ini

APCu is installed above as Nextcloud’s local memory cache. The background job runs on the PHP CLI, where APCu is off by default, so enable it there too:

echo 'apc.enable_cli=1' | sudo tee /etc/php/$PHP_VER/mods-available/apcu-cli.ini
sudo phpenmod -s cli apcu-cli

For more info on setting up PHP and Nginx, check out How to Install and set up PHP and Nginx (LEMP) on Ubuntu 22.04.

Installing Nginx

Next, let us install Nginx in our system. Use this command to install nginx

sudo apt install -y nginx

Nginx will be started by default. Check the status using this command:

sudo systemctl status nginx

Active: active (running) indicates that the service is now up and running.

To enable the service on boot, use this command:

sudo systemctl enable nginx

Download and configure Nextcloud

Now that we have successfully configured the LEMP server in our system, let us download and set up Nextcloud. You can get the latest version of Nextcloud from the Nextcloud installation page. Rather than pinning a version that will go stale, use the latest.zip alias, which always resolves to the current stable release (Nextcloud 35 at the time of writing):

cd /tmp
curl -LO https://download.nextcloud.com/server/releases/latest.zip

Now let us change into a directory path to serve Nextcloud in /var/www then extract the downloaded file there:

cd /var/www
sudo unzip /tmp/latest.zip
sudo chown -R www-data:www-data /var/www/nextcloud
sudo chmod -R 750 /var/www/nextcloud

Nextcloud requires a directory to keep its data. So create a data directory and set the proper permissions on it:

sudo mkdir -p /var/nextcloud/data
sudo chown -R www-data:www-data /var/nextcloud
sudo chmod -R 750 /var/nextcloud

The files need to be owned by www-data, the user PHP-FPM runs as, or Nextcloud cannot write to its own config and data directories. Keeping the data directory at /var/nextcloud, outside the web root, is deliberate: the files are never directly reachable over HTTP.

Configure Nginx to serve Nextcloud from a virtual host

We managed to download the Nextcloud content to /var/www/nextcloud. The next bit is to set up Nginx to serve it.

Let’s create a virtual site in the directory that nginx serves content from, /etc/nginx/conf.d:

sudo vim /etc/nginx/conf.d/nextcloud.conf

Add the following content, replacing php8.3-fpm.sock with your $PHP_VER (for example php8.5-fpm.sock on Ubuntu 26.04):

server {
    listen 80;

    server_name nextcloud.citizix.com;
    root /var/www/nextcloud;
    index index.php index.html;

    # Nextcloud moves large files; the nginx default of 1m is far too small.
    client_max_body_size 512M;
    client_body_timeout 300s;
    fastcgi_buffers 64 4K;

    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "no-referrer" always;

    # Service discovery for the CalDAV/CardDAV clients.
    location = /.well-known/carddav { return 301 /remote.php/dav/; }
    location = /.well-known/caldav  { return 301 /remote.php/dav/; }

    # Never serve these over HTTP.
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location ~* \.(js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~ \.php(?:$|/) {
        # Split the script from the trailing path so remote.php/dav/... routes correctly.
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        try_files $fastcgi_script_name =404;

        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param front_controller_active true;

        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_hide_header X-Powered-By;
        fastcgi_read_timeout 300;
    }
}

A few things to note in that config:

  • fastcgi_pass must point at the socket your PHP-FPM version actually creates. A generic /run/php/php-fpm.sock is not what this config expects, and a wrong path yields a 502 Bad Gateway. Confirm yours with ls /run/php/.
  • client_max_body_size is the single most common cause of failed Nextcloud uploads. Raise it to the largest file you expect to sync, and keep PHP’s upload_max_filesize and post_max_size at least as high.
  • The return 404 blocks keep /data, /config and friends off the web. Nextcloud ships an .htaccess for this, but Nginx ignores .htaccess entirely, so it has to be expressed here.

This is a deliberately minimal config that is enough to get Nextcloud running. For a production deployment (HTTP/2, more security headers, caching rules and the rest), start from the full example in the Nextcloud admin manual instead.

Check the syntax before reloading:

sudo nginx -t

Once the above changes have been made, we need to restart the nginx server and the php-fpm server:

sudo systemctl restart php$PHP_VER-fpm nginx

Accessing Nextcloud from the web url

Then head to your set domain, http://nextcloud.citizix.com/ for me. Since the vhost root already points at /var/www/nextcloud, the app is served from the domain root; there is no /nextcloud path segment to append.

  • You will be asked to create the admin account. Enter the username and password to be using for the new user
  • Set the data folder to /var/nextcloud/data
  • Then enter the Database Details: database nextcloud, user nextcloud_user, the password you chose, and localhost as the host

After that Click Install. The installer takes a minute or two to seed the database. You will then be redirected to the dashboard, logged in as the admin user.

Secure the site with HTTPS

The virtual host above listens on port 80 only, which means your login credentials and every file you sync travel in clear text. Do not put anything real on the server until it is behind TLS. With the DNS record already pointing at the server, Certbot will obtain a Let’s Encrypt certificate and rewrite the Nginx server block for you:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d nextcloud.citizix.com

Renewal is handled automatically by the certbot.timer systemd unit that the package installs, so there is nothing further to schedule. Nextcloud’s own security check will also stop warning about the missing HSTS header once you are on HTTPS.

Finishing touches

Open Administration settings → Overview in the web UI. Nextcloud runs its own configuration checks there and will tell you about anything still missing: a missing PHP module, an absent memory cache, or a cron job that has not been set up.

Two items worth handling straight away. First, register a real background job runner instead of the default AJAX one:

sudo crontab -u www-data -e

Add this line:

*/5 * * * * php -f /var/www/nextcloud/cron.php

Then switch the mode to Cron under Administration settings → Basic settings.

Second, if you reach the server by any hostname other than the one you installed with, add it to trusted_domains or Nextcloud will refuse the request:

sudo -u www-data php /var/www/nextcloud/occ config:system:set \
  trusted_domains 1 --value=nextcloud.example.com

Third, point Nextcloud at the APCu cache installed earlier, which clears the “no memory cache” warning in the admin overview:

sudo -u www-data php /var/www/nextcloud/occ config:system:set \
  memcache.local --value='\OC\Memcache\APCu'

Conclusion

In this guide, we managed to set up LEMP on Ubuntu or Debian to serve Nextcloud: MariaDB and Nginx from the distribution repositories, and PHP from the distribution (or Sury on Debian 12).

Keep an eye on the Nextcloud system requirements when you upgrade: the supported PHP and database versions move with each major release, and PHP is the component most likely to need attention on a long-lived host.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy