Skip to content

TutorialsSelf-hosted apps

How to install Nextcloud Server manually with Apache, PHP-FPM and MariaDB

Install Nextcloud Server by hand on Ubuntu or Debian with Apache, PHP-FPM, MariaDB and Redis, then add HTTPS, background jobs, backups and safe upgrades.

  • Advanced
  • 75 min read
  • Updated

Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 13

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. Step 1 — Install Apache, PHP-FPM, MariaDB and Redis
  3. Step 2 — Configure PHP
  4. Step 3 — Create the database
  5. Step 4 — Download and verify Nextcloud
  6. Step 5 — Configure Apache
  7. Step 6 — Install Nextcloud from the command line
  8. Step 7 — Turn on HTTPS and the firewall
  9. Step 8 — Enable memory caching
  10. Step 9 — Run background jobs with a systemd timer
  11. Step 10 — Clear the security and setup warnings
  12. Back up and restore
  13. Update Nextcloud
  14. Troubleshooting
  15. Access through untrusted domain
  16. occ reports that APCu is not available for the local cache
  17. Pages other than the start page return Not Found
  18. The overview says background jobs have not run for a long time
  19. The updater stops because the PHP version is not supported
  20. Next steps

Nextcloud Server is an open-source platform for file sync and sharing, calendars, contacts and collaboration that you run on your own server. This guide installs it by hand from the official archive, following the Nextcloud administration manual for the current major version, Nextcloud 35. You set up Apache with PHP-FPM, MariaDB, APCu and Redis caching, a verified download, the command-line installer, HTTPS with Certbot, background jobs through a systemd timer, and the backup, restore and upgrade procedures from the manual.

A manual install gives you full control, and also full responsibility for every component. If you prefer containers that update and back up themselves, use Nextcloud All-in-One instead.

Prerequisites

  • A server running Ubuntu 26.04 LTS (recommended by Nextcloud), Ubuntu 24.04 LTS or Debian 13. These are the Ubuntu and Debian releases the Nextcloud 35 manual lists.
  • A non-root user with sudo rights and SSH key login: see Secure a new Linux server and Set up SSH keys.
  • A domain such as cloud.example.com with an A/AAAA record pointing at the server, and nothing else listening on ports 80 and 443.

Check the versions your release ships against the manual's requirements:

ComponentNextcloud 35 supportsUbuntu 24.04Ubuntu 26.04Debian 13
PHP8.3, 8.4; 8.5 recommended8.38.58.4
MariaDB10.11, 11.4, 11.8 (recommended), 12.310.1111.811.8

The manual gives memory requirements per PHP process, not per server. The suggested values are a conservative starting point for a small team, not official numbers:

ResourceMinimum (official)Suggested starting point
RAM128 MB per PHP process; 512 MB per process recommended2 GB for a few users, more for Office or many users
CPUNot published2 vCPUs
DiskNot published20 GB SSD for the system plus space for all user files

Step 1 — Install Apache, PHP-FPM, MariaDB and Redis

The manual lists Apache 2.4 with mod_php or PHP-FPM, or Nginx with PHP-FPM. This guide uses Apache with PHP-FPM, which runs PHP in its own service and lets you tune the number of PHP processes. Install the packages from the manual's Ubuntu example plus PHP-FPM and the cache modules:

Bash
sudo apt update && sudo apt upgrade
sudo apt install apache2 mariadb-server redis-server bzip2 php-fpm php-cli php-gd php-mysql php-curl php-mbstring php-intl php-gmp php-xml php-imagick php-zip php-apcu php-redis

Check PHP and the modules:

Bash
php -v
php -m | grep -E "apcu|redis|imagick|intl"
systemctl status redis-server mariadb --no-pager

php -v should report 8.3, 8.4 or 8.5, and the module list should include all four names.

Step 2 — Configure PHP

Store your PHP version in a variable, then set the memory limit the manual asks for. Nextcloud's command-line tool occ also needs APCu enabled for the CLI, which is off by default:

Bash
PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
echo $PHP_VER
sudo tee /etc/php/$PHP_VER/fpm/conf.d/90-nextcloud.ini <<'EOF'
memory_limit = 512M
EOF
sudo tee /etc/php/$PHP_VER/cli/conf.d/90-nextcloud.ini <<'EOF'
memory_limit = 512M
apc.enable_cli = 1
EOF
sudo systemctl restart php$PHP_VER-fpm
php -i | grep -E "memory_limit|apc.enable_cli"

The last command should show 512M and On.

Step 3 — Create the database

Generate a strong password with openssl rand -hex 24, then open the MariaDB shell with sudo mariadb and run:

SQL
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'change-me';
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost';
FLUSH PRIVILEGES;
quit;

Replace change-me with your generated password. Nextcloud creates its tables during installation.

Step 4 — Download and verify Nextcloud

Download the latest release, its checksum and its signature from download.nextcloud.com, plus Nextcloud's public key:

Bash
cd /tmp
wget https://download.nextcloud.com/server/releases/latest.tar.bz2
wget https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256
wget https://download.nextcloud.com/server/releases/latest.tar.bz2.asc
wget https://nextcloud.com/nextcloud.asc
sha256sum -c --ignore-missing latest.tar.bz2.sha256
gpg --import nextcloud.asc
gpg --verify latest.tar.bz2.asc latest.tar.bz2

sha256sum must print latest.tar.bz2: OK, and gpg must report a good signature. A warning that the key is not certified with a trusted signature is normal for a key you just imported. If either check fails, delete the files and download them again.

Unpack the archive into the web root, and create a data directory outside the web root, as the hardening guide recommends:

Bash
sudo tar -xjf latest.tar.bz2 -C /var/www
sudo chown -R www-data:www-data /var/www/nextcloud
sudo mkdir -p /srv/nextcloud/data
sudo chown -R www-data:www-data /srv/nextcloud

Step 5 — Configure Apache

Create /etc/apache2/sites-available/nextcloud.conf with sudo nano and add the virtual host from the manual. The FilesMatch block passes the Authorization header to PHP-FPM, which WebDAV clients need:

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

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

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

  ProxyFCGIBackendType FPM
  <FilesMatch remote.php>
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
  </FilesMatch>
</VirtualHost>

Enable the modules the manual requires and recommends, connect Apache to PHP-FPM, and switch sites:

Bash
PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
sudo a2enmod proxy proxy_fcgi setenvif rewrite headers env dir mime
sudo a2enconf php$PHP_VER-fpm
sudo a2ensite nextcloud.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest
sudo systemctl restart apache2
apache2ctl -M | grep -E "rewrite|proxy_fcgi|mpm"

configtest should print Syntax OK, and the module list should show rewrite_module, proxy_fcgi_module and mpm_event_module.

Step 6 — Install Nextcloud from the command line

Run the installer as the web server user. It asks for the database password from Step 3 and a new admin password, so neither ends up in your shell history:

Bash
sudo -E -u www-data php /var/www/nextcloud/occ maintenance:install \
  --database mysql --database-name nextcloud \
  --database-user nextcloud \
  --admin-user admin \
  --data-dir /srv/nextcloud/data

The mysql type covers MariaDB. When it finishes, it prints that Nextcloud was successfully installed. Now add your domain to the trusted domains, set the public URL and enable URLs without index.php:

Bash
cd /var/www/nextcloud
sudo -E -u www-data php occ config:system:set trusted_domains 1 --value=cloud.example.com
sudo -E -u www-data php occ config:system:set overwrite.cli.url --value=https://cloud.example.com
sudo -E -u www-data php occ config:system:set htaccess.RewriteBase --value=/
sudo -E -u www-data php occ maintenance:update:htaccess
sudo -E -u www-data php occ config:system:get trusted_domains

The last command lists localhost and cloud.example.com. Every hostname you use to reach Nextcloud must be in this list.

Step 7 — Turn on HTTPS and the firewall

Allow only SSH and web traffic, then get a Let's Encrypt certificate with Certbot's Apache plugin. Certbot adds a TLS virtual host and, with --redirect, a redirect from HTTP to HTTPS:

Bash
sudo apt install ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d cloud.example.com --redirect
sudo certbot renew --dry-run

This uses the Certbot packages from your distribution, which include a renewal timer. The Certbot team recommends its snap instead, as shown in Nginx reverse proxy with Certbot; either works, but install only one of them.

The hardening guide recommends HTTP Strict Transport Security. Open /etc/apache2/sites-available/nextcloud-le-ssl.conf, the file Certbot created, and add this inside the VirtualHost *:443 block:

Config
<IfModule mod_headers.c>
  Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
</IfModule>

Reload Apache and check the header:

Bash
sudo apache2ctl configtest && sudo systemctl reload apache2
curl -sI https://cloud.example.com | grep -i strict-transport

If you prefer Nginx in front, the same principles apply; see Nginx reverse proxy with Certbot.

Step 8 — Enable memory caching

The manual's single-server setup uses APCu for the local cache and Redis for the distributed cache and file locking. Redis on Ubuntu and Debian listens on localhost only by default:

Bash
cd /var/www/nextcloud
sudo -E -u www-data php occ config:system:set memcache.local --value='\OC\Memcache\APCu'
sudo -E -u www-data php occ config:system:set memcache.distributed --value='\OC\Memcache\Redis'
sudo -E -u www-data php occ config:system:set memcache.locking --value='\OC\Memcache\Redis'
sudo -E -u www-data php occ config:system:set redis host --value=localhost
sudo -E -u www-data php occ config:system:set redis port --value=6379 --type=integer
sudo -E -u www-data php occ config:system:get memcache.locking

The last command prints the Redis class. Since Redis runs on the same server, the manual also describes a Unix socket connection (/run/redis/redis-server.sock with port 0) as an alternative.

Step 9 — Run background jobs with a systemd timer

Nextcloud needs regular background jobs for cleanup, notifications and previews. Create the two units from the manual. First /etc/systemd/system/nextcloudcron.service:

INI
[Unit]
Description=Nextcloud cron.php job

[Service]
User=www-data
ExecCondition=php -f /var/www/nextcloud/occ status -e
ExecStart=/usr/bin/php -f /var/www/nextcloud/cron.php
KillMode=process

Then /etc/systemd/system/nextcloudcron.timer:

INI
[Unit]
Description=Run Nextcloud cron.php every 5 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Unit=nextcloudcron.service

[Install]
WantedBy=timers.target

Enable the timer and switch Nextcloud to cron mode:

Bash
sudo systemctl daemon-reload
sudo systemctl enable --now nextcloudcron.timer
sudo -E -u www-data php /var/www/nextcloud/occ background:cron
systemctl list-timers | grep nextcloud

Step 10 — Clear the security and setup warnings

Log in at https://cloud.example.com and open Administration settings → Overview. Nextcloud checks your setup and lists warnings with links to the manual. These commands fix common ones on a new server; use your own country code for the phone region:

Bash
cd /var/www/nextcloud
sudo -E -u www-data php occ config:system:set default_phone_region --value=GB
sudo -E -u www-data php occ config:system:set maintenance_window_start --type=integer --value=1
sudo -E -u www-data php occ db:add-missing-indices
sudo -E -u www-data php occ maintenance:repair --include-expensive

maintenance_window_start is an hour in UTC; with 1, heavy background jobs run between 01:00 and 05:00 UTC. Reload the overview page until it reports that all checks passed, then turn on two-factor authentication for the admin account under Personal settings → Security.

Nextcloud emails password resets and notifications about shares and file changes; set up the mail server under Administration settings → Basic settings in the Email server section with host smtp.example.com, port 587 and the None/STARTTLS encryption option, then send a test message from the same page.

Back up and restore

The manual lists what to back up: the config folder, the data folder, the themes folder, custom apps if you installed any, and the database. Put Nextcloud into maintenance mode so files and database match, copy the folders, dump the database, and leave maintenance mode:

Bash
sudo mkdir -p /opt/backups
cd /var/www/nextcloud
sudo -E -u www-data php occ maintenance:mode --on
sudo rsync -Aax /var/www/nextcloud/ /opt/backups/nextcloud-dirbkp_$(date +%F)/
sudo rsync -Aax /srv/nextcloud/data/ /opt/backups/nextcloud-databkp_$(date +%F)/
sudo mariadb-dump --single-transaction --default-character-set=utf8mb4 -r /opt/backups/nextcloud-sqlbkp_$(date +%F).bak nextcloud
sudo -E -u www-data php occ maintenance:mode --off

Copy /opt/backups to another machine, for example with rsync -aAx over SSH, and keep several dated copies.

To restore, enable maintenance mode, copy the folders back, recreate the database and import the dump:

Bash
cd /var/www/nextcloud
sudo -E -u www-data php occ maintenance:mode --on
sudo rsync -Aax /opt/backups/nextcloud-dirbkp_2026-10-09/ /var/www/nextcloud/
sudo rsync -Aax /opt/backups/nextcloud-databkp_2026-10-09/ /srv/nextcloud/data/
sudo mariadb -e "DROP DATABASE nextcloud"
sudo mariadb -e "CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"
sudo mariadb nextcloud < /opt/backups/nextcloud-sqlbkp_2026-10-09.bak
sudo -E -u www-data php occ maintenance:mode --off

If the backup is older than what your sync clients last saw, run sudo -E -u www-data php occ maintenance:data-fingerprint so the clients detect the change instead of deleting newer local files.

Update Nextcloud

Read the release notes and make a fresh backup first; the updater does not back up your database or data. Upgrade one major version at a time (for example 35 to 36), always from the latest point release of your current version, and check that the next major version still supports your PHP version. Run the built-in updater as the web server user:

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

The updater replaces the code and asks whether to run occ upgrade for you. If you answer no, or if it stops, finish the upgrade yourself:

Bash
cd /var/www/nextcloud
sudo -E -u www-data php occ upgrade
sudo -E -u www-data php occ maintenance:mode --off
sudo -E -u www-data php occ db:add-missing-indices

Keep Apache, PHP, MariaDB and Redis updated with sudo apt update && sudo apt upgrade.

Troubleshooting

Access through untrusted domain

You opened Nextcloud under a hostname that is not in trusted_domains. Add it with occ config:system:set trusted_domains 2 --value=other.example.com (use the next free index), or always use the configured domain.

occ reports that APCu is not available for the local cache

APCu is disabled for the PHP CLI. Check that /etc/php/8.x/cli/conf.d/90-nextcloud.ini contains apc.enable_cli = 1 and that php -i | grep apc.enable_cli shows On. The background job service uses the same CLI configuration.

Pages other than the start page return Not Found

URL rewriting is not working. Check that rewrite is enabled with apache2ctl -M, that the Directory block has AllowOverride All, and run occ maintenance:update:htaccess again after changing htaccess.RewriteBase.

The overview says background jobs have not run for a long time

The timer is not running or the job fails. Check systemctl status nextcloudcron.timer and journalctl -u nextcloudcron.service -n 50. A common cause is a wrong path in the service file or missing apc.enable_cli.

The updater stops because the PHP version is not supported

The next Nextcloud major version needs a newer PHP than your release ships. Stay on your current version, which keeps receiving point releases for a while, and move to a newer OS release before upgrading Nextcloud.

Next steps

Frequently asked questions

Which PHP version does Nextcloud 35 need?

The Nextcloud 35 administration manual lists PHP 8.3 and 8.4 as supported and PHP 8.5 as recommended. Ubuntu 26.04 ships PHP 8.5, Debian 13 ships PHP 8.4 and Ubuntu 24.04 ships PHP 8.3, so all three work with their own packages.

Can I install Nextcloud 35 on Debian 12?

Not with Debian's own packages. Debian 12 ships PHP 8.2, which Nextcloud 35 no longer supports. Use Debian 13 or Ubuntu 24.04 or 26.04 instead, or run Nextcloud All-in-One, which brings its own PHP in containers.

Should I use the manual install or Nextcloud AIO?

Choose the manual install when you want full control over Apache, PHP and the database or need to fit Nextcloud into an existing server. Choose AIO when you want updates, HTTPS and backups handled for you by the official containers.

Can I skip a major version when upgrading Nextcloud?

No. Nextcloud supports upgrades one major version at a time, for example 34 to 35 and then 35 to 36, always from the latest point release of your current version. Downgrades are not supported, so back up before every upgrade.

Which HyperDC servers can run Nextcloud?

Nextcloud runs on a HyperDC Linux VPS, VDS or dedicated server with root access and Ubuntu 24.04, Ubuntu 26.04 or Debian 13. Plan RAM for PHP processes and disk space for your users’ files.

Sources

Сгенерировать пароль

Please confirm