How to Deploy Nextcloud on Ubuntu 22.04 Utilizing Nginx and PHP-FPM
In this comprehensive guide, we will walk through the process of setting up Nextcloud on Ubuntu 22.04, powered by Nginx and PHP-FPM. Nextcloud is a robust, open-source self-hosted cloud storage platform designed to let you store, manage, and share your documents, media, and files securely online. While it mirrors popular commercial platforms like Google Drive or Dropbox, Nextcloud provides the distinct benefit of absolute data ownership since it operates entirely within your private infrastructure or self-managed servers.
Key Features of Nextcloud
- Completely Free & Open Source: Full transparency and customization without subscription fees.
- End-to-End Encryption (E2EE): Data is fully encrypted locally on your machine prior to server uploading, ensuring maximum privacy even if the physical server is compromised.
- Collaborative Office Integration: Seamlessly pairs with web-based office suites such as Collabora Online and OnlyOffice, enabling real-time document creation and spreadsheet editing inside the platform.
- Extensive App Ecosystem: An built-in marketplace offering hundreds of add-ons to expand functionality, including shared calendars, contact managers, markdown notes, and video conferencing tools.
- Cross-Platform Synchronization: Native client applications are available for Linux, macOS, Windows, iOS, and Android to keep your devices in sync.
System Prerequisites for Installation
To follow along with this deployment guide, you will need a Virtual Private Server (VPS) running a clean installation of Ubuntu 22.04 LTS.
For the purposes of this tutorial, we are spinning up a digital ocean cloud instance equipped with 1 vCPU Core, 1GB of RAM, and a 25GB SSD storage volume. If your instance is up and ready for deployment, let's dive right into the execution.
Related Reading: Understanding PHP-FPM: Definition, Practical Functions, and Internal Architecture.
Step 1: Web Server Installation
Before deploying any packages, it is crucial to update the local package index and upgrade existing system dependencies to their latest stable releases.
bash
sudo apt update && sudo apt upgrade -y
For high-performance environments, pairing Nextcloud with PHP-FPM and Nginx is highly recommended. Run the following command to deploy the Nginx web server:
bash
sudo apt install nginx -y
Once installed, initialize the Nginx service, verify its current operational status, and configure it to launch automatically during system initialization:
bash
sudo service nginx start
sudo service nginx status
sudo systemctl enable nginx
To confirm the installation, point your preferred web browser to the public IP address of your VPS. You should be greeted by the default Nginx welcome screen.
Step 2: Deploying the MariaDB Database Engine
We will utilize MariaDB Server to handle back-end data storage for Nextcloud. Execute the command below to install it:
bash
sudo apt install mariadb-server -y
After the installation concludes, initiate the MariaDB service, configure it to run on system boot, and check its daemon status to ensure stability:
bash
sudo service mariadb start
sudo systemctl enable mariadb
sudo service mariadb status
Verify that the MariaDB service is fully active and running as expected.
Step 3: Installing PHP and Required System Modules
Because Nextcloud is natively programmed in PHP, it requires the PHP runtime environment to parse server-side business logic, process application data, and render the user interface.
First, introduce the foundational software properties and import the Ondrej PHP PPA repository to access modern PHP releases:
bash
sudo apt update
sudo apt install -y lsb-release gnupg2 ca-certificates apt-transport-https software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
With the repository successfully linked, deploy PHP 8.2 along with the specific extensions required for Nextcloud's core functions:
bash
sudo apt install imagemagick php-imagick php8.2-common php8.2-mysql php8.2-fpm php8.2-gd php8.2-curl php8.2-zip php8.2-xml php8.2-mbstring php8.2-bz2 php8.2-intl php8.2-gmp
To align with Nextcloud's performance recommendations, elevate the PHP memory allocation limit from its default setting to 512MB:
bash
sudo sed -i 's/memory_limit = 128M/memory_limit = 512M/g' /etc/php/8.2/fpm/php.ini
Conclude this step by reloading the web server and initializing the PHP-FPM process manager:
bash
sudo systemctl reload nginx
sudo service php8.2-fpm restart
sudo systemctl enable php8.2-fpm
sudo service php8.2-fpm status
Step 4: Fetching the Nextcloud Archive File
The official Nextcloud distribution packages can always be verified at nextcloud.com/install. We will pull down the latest stable release package directly via the terminal:
bash
cd ~
wget https://download.nextcloud.com/server/releases/latest.zip
Unpack the downloaded zip archive using the unzip utility:
bash
sudo apt install unzip
sudo unzip latest.zip -d /var/www/
Assign the appropriate directory permissions by giving ownership of the application path to the web server user (www-data):
bash
sudo chown www-data:www-data /var/www/nextcloud/ -R
Step 5: Provisioning the Database and User Access
Access the MariaDB database command-line interface. Modern MariaDB deployments utilize the unix_socket authentication mechanism for local root access, meaning a root password is not necessary if you execute the connection statement with administrative privileges:
bash
sudo mysql
Execute the following structural queries to create a dedicated database, provision an isolated user, and grant all necessary administrative rights to that user. Remember to replace 'your-password' with a secure custom passphrase:
sql
CREATE DATABASE nextcloud_db;
CREATE USER nextclouduser@localhost identified by 'your-password';
grant all privileges on nextcloud_db.* to nextclouduser@localhost identified by 'your-password';
Apply the configuration changes immediately and close the database connection console:
sql
flush privileges;
exit;
The sequence should closely mirror the database provisioning workflow shown below.
Step 6: Engineering the Nginx Configuration Server Block
The Nginx virtual host configuration maps your custom domain name or subdomain to your internal Nextcloud paths, handles static caching, and acts as the bridge for SSL configurations.
Generate a new virtual host configuration file inside your Nginx configuration directory using your preferred text editor:
bash
sudo nano /etc/nginx/conf.d/nextcloud.conf
Inject the following blocks into the file, ensuring you swap out nextcloud.skyssh.net with your actual target domain name. Make sure you have previously configured a DNS A record pointing this domain to your server's public IP address:
nginx
server {
listen 80;
listen [::]:80;
server_name nextcloud.skyssh.net;
# Add headers to serve security related headers
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header Referrer-Policy no-referrer;
#I found this header is needed on Ubuntu, but not on Arch Linux.
add_header X-Frame-Options "SAMEORIGIN";
# Path to the root of your installation
root /var/www/nextcloud/;
access_log /var/log/nginx/nextcloud.access;
error_log /var/log/nginx/nextcloud.error;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location ~ /.well-known/acme-challenge {
allow all;
}
# set max upload size
client_max_body_size 1024M;
fastcgi_buffers 64 4K;
# Disable gzip to avoid the removal of the ETag header
gzip off;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
location / {
rewrite ^ /index.php;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
deny all;
}
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|core/templates/40[34])\.php(?:$|/) {
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
try_files $fastcgi_script_name =404;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
#Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^/(?:updater|ocs-provider)(?:$|/) {
try_files $uri/ =404;
index index.php;
}
# Adding the cache control header for js and css files
# Make sure it is BELOW the PHP block
location ~* \.(?:css|js)$ {
try_files $uri /index.php$uri$is_args$args;
add_header Cache-Control "public, max-age=7200";
# Add headers to serve security related headers (It is intended to
# have those duplicated to the ones above)
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header Referrer-Policy no-referrer;
# Optional: Don't log access to assets
access_log off;
}
location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
try_files $uri /index.php$uri$is_args$args;
# Optional: Don't log access to other assets
access_log off;
}
}Verify your file configuration rules for any syntax issues, then reload the Nginx engine to pull in the parameters:
bash
sudo nginx -t
sudo systemctl reload nginx
Step 7: Activating TLS/HTTPS Security
To secure transit communications, we will obtain a free Let's Encrypt SSL certificate managed automatically through the Certbot automation agent. First, install Certbot along with its dedicated Nginx integration helper:
bash
sudo apt install certbot python3-certbot-nginx -y
Now, initiate the certificate generation process. Ensure you update the email contact parameter and domain details to match your system configurations:
bash
sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email you@example.com -d nextcloud.example.com
Upon successful structural execution, your terminal should log a confirmation message.
Your application portal is now running securely over HTTPS. Let's Encrypt certificates are valid for 90 days, but Certbot sets up an automated background timer task to handle renewals smoothly before they expire.
Step 8: Running the Graphic Nextcloud Web Installer
With your back-end dependencies and server blocks running smoothly, the final setup layer happens in your browser interface.
Open your browser and navigate to your assigned Nextcloud domain to load the graphical wizard initialization script.
Set your primary administrative username and password credentials. Next, under the database storage selection, choose MySQL/MariaDB and fill out the precise database names, user credentials, and passwords created during Step 5. Click Install to finish the process.
Once finalized, the application will redirect you directly to the primary user control panel workspace dashboard.
Step 9: Integrating Redis for Memory Object Caching
To significantly minimize page rendering times and server overhead, we will configure Redis to act as an in-memory transactional cache layer. This prevents database log-jams and streamlines data delivery.
Begin by downloading and installing the Redis caching server engine:
bash
sudo apt install redis-server -y
Boot the service daemon and confirm it is running smoothly across server boot cycles:
bash
sudo systemctl start redis-server
sudo systemctl enable redis-server
sudo systemctl status redis
Ensure the status tracker confirms that Redis is active. Next, install the PHP-Redis connector driver to let Nextcloud send cache logs to the Redis server backend:
bash
sudo apt install php8.2-redis
Verify the active state of the connector extension with the following command:
Open the primary internal Nextcloud configuration block using a text editor to bind the Redis caching driver:
bash
sudo nano /var/www/nextcloud/config/config.php
Directly above the terminating ); string array boundary (ideally directly underneath the 'installed' => true, line item), append the following system parameters:
php
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.local' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array(
'host' => 'localhost',
'port' => 6379,
),
Review your edits against the configuration example shown below.
To complete the setup, restart the PHP processor and Nginx web server instances to apply the configuration layers:
bash
sudo systemctl restart nginx php8.2-fpm
Post-Installation Tips & Advanced Optimization
Here are a few useful maintenance tips to help you handle common edge cases, fix configuration errors, and manage users directly from the command line interface.
A. Resetting User Passwords via the Command Line Interface (OCC)
If you ever find yourself locked out of your admin dashboard, you can trigger a password override directly within the host console. Make sure to replace nextcloud_username with your target administrative account name:
bash
sudo -u www-data php /var/www/nextcloud/occ user:resetpassword nextcloud_username
B. Increasing Maximum Permitted Upload Limits
To prevent web server timeout drops when uploading larger multi-gigabyte structures, increase the default upload cap limit (e.g., from 2MB to 1GB) using this fast stream modifier tool:
bash
sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 1024M/g' /etc/php/8.2/fpm/php.ini
sudo systemctl restart php8.2-fpm
C. Transitioning System Background Tasks to System Cron
By default, Nextcloud processes periodic maintenance workflows using the standard AJAX routing system, executing tasks every time a web page loads. To optimize host operations, shift background tracking routines directly to a dedicated system automation task.
Navigate to your web control panel: Administration Settings -> Basic Settings, and switch the background execution engine checkbox selection over to Cron.
Open the crontab editor file assigned explicitly to your web application service runner (www-data):
bash
sudo -u www-data crontab -e
Insert the following automation entry line to run Nextcloud's script engine every 5 minutes:
cron
*/5 * * * * php8.2 -f /var/www/nextcloud/cron.php
Save your updates and exit the terminal file. Your Nextcloud cloud platform is now optimized and running completely under your own private infrastructure control.