A manual Nextcloud LEMP deployment puts the application behind Nginx and PHP-FPM while MariaDB stores the application data on the same Ubuntu host. This layout fits operators who want package-managed services and the standard archive install instead of Nextcloud AIO, Snap, or a container stack.

The deployment depends on Nginx for HTTP requests, PHP-FPM for PHP execution, MariaDB for the database, the extracted Nextcloud archive, and the occ command that writes the initial configuration. Use the PHP-FPM package, service, and socket that match the active Ubuntu and Nextcloud release.

Assume a clean server with DNS already pointing at the chosen hostname. The bootstrap server block is HTTP-only so the installed site can be verified through Nginx before normal users log in; enable HTTPS and then review background jobs, cache, memory, and OPcache before putting the server into routine use.

Steps to deploy Nextcloud on Ubuntu LEMP:

  1. Refresh the Ubuntu package index.
    $ sudo apt update
  2. Install Nginx, MariaDB, PHP-FPM, the required PHP modules, and archive tools.
    $ sudo apt install nginx mariadb-server php8.5-fpm php8.5-cli php8.5-gd php8.5-mysql php8.5-curl php8.5-mbstring php8.5-intl php8.5-gmp php8.5-xml php-imagick php8.5-zip php8.5-apcu bzip2 curl ca-certificates
    ##### snipped #####
    Setting up nginx
    Setting up mariadb-server
    Setting up php8.5-fpm

    php-imagick follows the package name used by the Ubuntu archive. If a PHP module name is already bundled or renamed in the active Ubuntu release, confirm it with the distribution package list before adding a third-party PHP repository.

  3. Enable and start the service layer.
    $ sudo systemctl enable --now nginx mariadb php8.5-fpm
  4. Open the MariaDB shell.
    $ sudo mysql
    Welcome to the MariaDB monitor.
    ##### snipped #####
    MariaDB [(none)]>
  5. Create the Nextcloud database and local database user.
    CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
    CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'replace-with-a-long-random-password';
    GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost';
    FLUSH PRIVILEGES;
    EXIT;

    Use a unique database password and keep it out of screenshots, tickets, and shared transcripts.

  6. Download the latest Nextcloud archive.
    $ curl -LO https://download.nextcloud.com/server/releases/latest.tar.bz2
  7. Download the matching SHA256 checksum file.
    $ curl -LO https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256
  8. Verify the downloaded archive.
    $ sha256sum -c latest.tar.bz2.sha256
    latest.tar.bz2: OK

    Signature verification with the Nextcloud release key gives stronger provenance when deployment policy requires it.

  9. Extract the archive into /var/www.
    $ sudo tar -xjf latest.tar.bz2 -C /var/www

    Move or back up an existing /var/www/nextcloud directory before extracting. Extracting over an existing tree can mix releases and leave stale application files behind.

  10. Set the web-server user as the owner of the extracted tree.
    $ sudo chown -R www-data:www-data /var/www/nextcloud
  11. Install Nextcloud from the command line.
    $ sudo -E -u www-data php /var/www/nextcloud/occ maintenance:install \
      --database 'mysql' \
      --database-name 'nextcloud' \
      --database-user 'nextcloud' \
      --database-pass 'replace-with-database-password' \
      --admin-user 'admin' \
      --admin-pass 'replace-with-admin-password'
    Nextcloud was successfully installed

    The database and admin passwords appear in the shell command while this runs. Use a controlled setup shell, clear shell history if required by local policy, and do not reuse the database password for the web admin account.

  12. Add the public hostname to the trusted domains list.
    $ sudo -E -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 --value=cloud.example.com
    System config value trusted_domains => 1 set to string cloud.example.com
  13. Set the public command-line URL for generated links.
    $ sudo -E -u www-data php /var/www/nextcloud/occ config:system:set overwrite.cli.url --value=http://cloud.example.com
    System config value overwrite.cli.url set to string http://cloud.example.com

    Change this value to https://cloud.example.com after TLS is enabled.
    Related: How to configure HTTPS for Nextcloud with Nginx and Let's Encrypt

  14. Create the Nginx site file.
    $ sudoedit /etc/nginx/sites-available/cloud.example.com
  15. Save a root-install Nextcloud bootstrap server block.
    upstream php-handler {
        server unix:/run/php/php8.5-fpm.sock;
    }
     
    server {
        listen 80;
        listen [::]:80;
        server_name cloud.example.com;
     
        root /var/www/nextcloud;
        index index.php index.html /index.php$request_uri;
     
        client_max_body_size 512M;
     
        location ^~ /.well-known {
            location = /.well-known/carddav { return 301 /remote.php/dav/; }
            location = /.well-known/caldav  { return 301 /remote.php/dav/; }
            return 301 /index.php$request_uri;
        }
     
        location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) {
            return 404;
        }
     
        location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
            return 404;
        }
     
        location ~ \.php(?:$|/) {
            try_files $fastcgi_script_name =404;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param modHeadersAvailable true;
            fastcgi_param front_controller_active true;
            fastcgi_param HTTPS off;
            fastcgi_pass php-handler;
        }
     
        location / {
            try_files $uri $uri/ /index.php$request_uri;
        }
    }

    The official Nextcloud Nginx example changes over time. Keep the deny locations, .well-known redirects, PHP FastCGI parameters, asset caching rules, and PHP-FPM socket aligned with the active Nextcloud and Ubuntu release before production use.

    This HTTP block is for initial bootstrap or private validation only. Do not let real users enter credentials over plain HTTP.

  16. Enable the Nginx site.
    $ sudo ln -s /etc/nginx/sites-available/cloud.example.com /etc/nginx/sites-enabled/cloud.example.com
  17. Test the Nginx configuration.
    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  18. Reload Nginx and PHP-FPM.
    $ sudo systemctl reload nginx php8.5-fpm

    Use the PHP-FPM unit that owns the socket in the site file.
    Related: How to manage the Nginx service
    Related: How to manage a Linux service with systemctl

  19. Request the public status endpoint through Nginx.
    $ curl http://cloud.example.com/status.php
    {"installed":true,"maintenance":false,"needsDbUpgrade":false,"version":"35.0.0.0","versionstring":"35.0.0","edition":"","productname":"Nextcloud","extendedSupport":false}

    A successful response proves DNS, Nginx, PHP-FPM, the web root, and the installed Nextcloud app can complete a request path.

  20. Check the installed application state with occ.
    $ sudo -E -u www-data php /var/www/nextcloud/occ status
      - installed: true
      - version: 35.0.0.0
      - versionstring: 35.0.0
      - edition:
      - maintenance: false
      - needsDbUpgrade: false
      - productname: Nextcloud
      - extendedSupport: false

    Complete the follow-up service hardening before normal use, especially HTTPS, background jobs, memory limits, OPcache, and cache locking.
    Related: How to configure HTTPS for Nextcloud with Nginx and Let's Encrypt
    Related: How to configure Nextcloud background jobs with cron
    Related: How to set the PHP memory limit for Nextcloud
    Related: How to configure PHP OPcache for Nextcloud
    Related: How to configure Redis caching for Nextcloud