How to Deploy NextCloud - An Opensource File Manager and Alternative to Google Drive

Updated on 04 September, 2025
Deploy Nextcloud on Rocky Linux 9 with Docker, Nginx, and HTTPS. Set up MariaDB, Redis, and secure your private cloud storage.
How to Deploy NextCloud - An Opensource File Manager and Alternative to Google Drive header image

Nextcloud is a free and open-source platform for hosting and managing file storage services. It offers similar functionality to Google Drive, such as file sharing and collaboration, but runs entirely on infrastructure you control. Its source code is publicly available on GitHub for review and contributions.

In this article, you will deploy Nextcloud on Rocky Linux 9 using either a manual installation with Nginx, PHP, and MariaDB, or a containerized installation with Docker and Docker Compose. Both methods include secure web server configuration, database setup, and optional HTTPS support for encrypted access.

Prerequisites

Before you being, ensure you:

Install Nextcloud

This section sets up the system to install Nextcloud. You'll update your packages, install required tools, and prepare the environment for web, database, and PHP services.

  1. Update the system packages.

    console
    $ sudo dnf update
    

    When prompted, press <kbd class="key">Y</kbd> to confirm and install available updates.

  2. Install system utilities and dependencies.

    console
    $ sudo dnf install epel-release unzip curl wget policycoreutils-python-utils dnf-plugins-core -y
    

    These packages provide essential tools for web application setup and SELinux management.

Download the Nextcloud Web Application Files

  1. Download the latest Nextcloud release.

    console
    $ wget https://download.nextcloud.com/server/releases/latest.zip
    

    This command downloads the latest stable version of Nextcloud to your current working directory.

  2. Extract the archive.

    console
    $ unzip latest.zip
    

    This creates a nextcloud/ directory containing the web application files.

  3. Ensure the target web root directory exists.

    console
    $ sudo mkdir -p /var/www/
    
  4. Move the extracted files to /var/www.

    console
    $ sudo mv nextcloud/ /var/www/
    

    The Nextcloud files are now ready to be served from /var/www/nextcloud.

Install MariaDB Database Server

Nextcloud stores its configuration and user data in a relational database. While it supports MySQL, PostgreSQL, SQLite, and Oracle, SQLite is only suitable for testing or very small deployments. In this section, install and configure MariaDB as the production database backend.

  1. Create a custom repository file for MariaDB.

    console
    $ sudo tee /etc/yum.repos.d/MariaDB.repo > /dev/null <<EOF
    [mariadb]
    name = MariaDB
    baseurl = https://rpm.mariadb.org/11.4/rhel/\$releasever/\$basearch
    gpgkey = https://rpm.mariadb.org/RPM-GPG-KEY-MariaDB
    gpgcheck = 1
    EOF
    
  2. Install the MariaDB server and client.

    console
    $ sudo dnf install MariaDB-server MariaDB-client
    
  3. Start and enable MariaDB at boot.

    console
    $ sudo systemctl enable --now mariadb
    
  4. Secure your MariaDB installation.

    console
    $ sudo mariadb-secure-installation
    

    The script guides you through setting the root password and adjusting basic security options. When prompted, enter a strong root password, then answer Y to the remaining prompts to apply the recommended defaults.

Configure the MariaDB Database for Nextcloud

  1. Log in to the MariaDB root account.

    console
    $ mariadb -u root -p
    

    Enter the root password you set during mariadb-secure-installation.

  2. Create the Nextcloud database.

    sql
    MariaDB [(none)]> CREATE DATABASE nextcloud;
    
  3. Create a dedicated database user for Nextcloud.

    sql
    MariaDB [(none)]> CREATE USER 'nextcloud'@'127.0.0.1' IDENTIFIED BY 'StrongPass';
    

    Replace StrongPass with an alphanumeric, secure password.

  4. Grant the user full privileges on the Nextcloud database.

    sql
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'127.0.0.1';
    
  5. Reload the privileges.

    sql
    MariaDB [(none)]> FLUSH PRIVILEGES;
    
  6. Exit the MariaDB console.

    sql
    MariaDB [(none)]> exit
    
  7. Test the new database user login.

    console
    $ mariadb -u nextcloud -p -h 127.0.0.1
    

    Enter the password you set earlier.

  8. Verify that the nextcloud database exists.

    sql
    MariaDB [(none)]> SHOW DATABASES;
    

    Output:

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | nextcloud          |
    +--------------------+

    Exit the session by typing exit.

Tune MariaDB for Nextcloud

Nextcloud requires certain MariaDB settings to ensure optimal compatibility and performance. Modify the MariaDB configuration to meet these requirements.

  1. Edit the MariaDB configuration file.

    console
    $ sudo nano /etc/my.cnf.d/server.cnf
    
  2. Under the [mysqld] section, add the following lines:

    ini
    bind-address = 127.0.0.1
    character_set_server = utf8mb4
    collation_server = utf8mb4_general_ci
    transaction_isolation = READ-COMMITTED
    binlog_format = ROW
    innodb_large_prefix = 1
    innodb_file_format = barracuda
    innodb_file_per_table = 1
    
    • bind-address = 127.0.0.1: Restricts connections to localhost.
    • character_set_server and collation_server: Configure utf8mb4 for full Unicode support.
    • transaction_isolation = READ-COMMITTED: Prevents uncommitted read inconsistencies.
    • binlog_format = ROW: Improves replication accuracy and recovery.
    • InnoDB options: Enable larger index prefixes, Barracuda file format, and per-table tablespaces.
  3. Still in the same file, add the following under the [server] section:

    ini
    skip_name_resolve = 1
    innodb_buffer_pool_size = 128M
    innodb_buffer_pool_instances = 1
    innodb_flush_log_at_trx_commit = 2
    innodb_log_buffer_size = 32M
    innodb_max_dirty_pages_pct = 90
    query_cache_type = 1
    query_cache_limit = 2M
    query_cache_min_res_unit = 2K
    query_cache_size = 64M
    tmp_table_size = 64M
    max_heap_table_size = 64M
    slow_query_log = 1
    slow_query_log_file = /var/log/mysql/slow.log
    long_query_time = 1
    
    • skip_name_resolve: Disables DNS lookups to improve connection speed.
    • innodb_* parameters: Configure buffer pools, flushing, and log buffers for balanced performance.
    • query_cache_* parameters: Manage the query cache (note: deprecated in MariaDB 11.4 and may be ignored).
    • tmp_table_size and max_heap_table_size: Define limits for temporary and in-memory tables.
    • slow_query_log options: Enable and configure slow query logging for performance analysis.
  4. Restart MariaDB to apply the changes.

    console
    $ sudo systemctl restart mariadb
    
  5. Verify that MariaDB is running.

    console
    $ sudo systemctl status mariadb
    

Install PHP 8 for Nextcloud

Nextcloud requires PHP to run. Version 8.3 or higher is recommended for better performance, memory management, and compatibility. In this section, install PHP 8.3, enable necessary modules, and configure PHP-FPM to work with Nginx.

  1. Check available PHP streams.

    console
    $ sudo dnf module list php
    

    PHP 8.3 is available by default in Rocky Linux 9, but some packages may not be included. To ensure all required modules are accessible, you need to add and enable the Remi repository for PHP 8.3.

  2. Add the Remi repository.

    console
    $ sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm
    

    The Remi repository is a trusted third-party repo that maintains up-to-date PHP builds for Enterprise Linux distributions.

  3. Enable the Remi repository and PHP 8.3 module.

    console
    $ sudo dnf config-manager --set-enabled remi
    $ sudo dnf module enable php:remi-8.3
    
  4. Install PHP 8.3, PHP-FPM, and required extensions.

    console
    $ sudo dnf install php php-fpm php-intl php-sodium php-ctype \
     php-curl php-dom php-gd php-mbstring php-posix php-session \
     php-xml php-zip php-zlib php83-php-pecl-redis php-mysqlnd -y
    
  5. Edit the PHP-FPM configuration to use the nginx user.

    console
    $ sudo nano /etc/php-fpm.d/www.conf
    

    Change the following lines:

    ini
    user = nginx
    group = nginx
    
  6. Increase the PHP memory limit.

    console
    $ sudo nano /etc/php.ini
    

    Change the following line:

    ini
    memory_limit = 512M
    
  7. Enable and start PHP-FPM.

    console
    $ sudo systemctl enable --now php-fpm
    
  8. Allow PHP-FPM to access the MariaDB socket (SELinux).

    console
    $ sudo semanage fcontext -a -t mysqld_var_run_t "/var/lib/mysql/mysql.sock"
    
  9. Restart all services to apply the changes.

    console
    $ sudo systemctl restart php-fpm nginx mariadb
    

Install and Configure Nginx Web Server

Nextcloud requires a web server to serve its frontend and handle PHP requests. Nginx is a lightweight and high-performance web server well-suited for this task. Follow these steps to install and configure it.

  1. Install Nginx.

    console
    $ sudo dnf install nginx -y
    

    DNF automatically accepts the GPG key and installs the stable version from the configured repository.

  2. Enable and start the Nginx service.

    console
    $ sudo systemctl enable --now nginx
    
  3. Verify that Nginx is active.

    console
    $ sudo systemctl status nginx
    

    The output should indicate that the service is active (running).

  4. Allow HTTP and HTTPS traffic through the firewall.

    console
    $ sudo firewall-cmd --zone=public --permanent --add-port=80/tcp
    $ sudo firewall-cmd --zone=public --permanent --add-port=443/tcp
    
  5. Reload the firewall to apply the changes.

    console
    $ sudo firewall-cmd --reload
    
  6. Open your server’s IP address in a browser. If Nginx installed correctly, you'll see the default welcome page:

    Nginx default page

  7. Change file ownership for the Nextcloud directory to allow Nginx to read and execute the files.

    console
    $ sudo chown -R nginx:nginx  /var/www/nextcloud
    
  8. Change the permissions to give the user read, write, and execute permissions.

    console
    $ sudo chmod -R 750 /var/www/nextcloud
    
  9. Create a new configuration file for Nextcloud.

    console
    $ sudo nano /etc/nginx/conf.d/nextcloud.conf
    
  10. Add the following content. Replace nextcloud.example.com with your actual domain.

    ini
    # PHP-FPM socket
    upstream php-handler {
        server unix:/run/php-fpm/www.sock;
    }
    
    # Cache control for assets
    map $arg_v $asset_immutable {
        "" "";
        default ", immutable";
    }
    
    server {
        listen 80;
        listen [::]:80;
        server_name nextcloud.example.com;
    
        root /var/www/nextcloud;
        server_tokens off;
    
        client_max_body_size 512M;
        client_body_timeout 300s;
        fastcgi_buffers 64 4K;
    
        gzip on;
        gzip_vary on;
        gzip_comp_level 4;
        gzip_min_length 256;
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
    
        client_body_buffer_size 512k;
    
        add_header Referrer-Policy "no-referrer" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Permitted-Cross-Domain-Policies "none" always;
        add_header X-Robots-Tag "noindex, nofollow" always;
        add_header X-XSS-Protection "1; mode=block" always;
    
        fastcgi_hide_header X-Powered-By;
    
        include mime.types;
        types {
            text/javascript mjs;
        }
    
        index index.php index.html /index.php$request_uri;
    
        location = / {
            if ($http_user_agent ~ ^DavClnt) {
                return 302 /remote.php/webdav/$is_args$args;
            }
        }
    
        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }
    
        location ^~ /.well-known {
            location = /.well-known/carddav { return 301 /remote.php/dav/; }
            location = /.well-known/caldav  { return 301 /remote.php/dav/; }
            location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
            location /.well-known/pki-validation    { try_files $uri $uri/ =404; }
            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(?:$|/) {
            rewrite ^/(?!index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|.+/richdocumentscode(_arm64)?/proxy) /index.php$request_uri;
    
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            set $path_info $fastcgi_path_info;
    
            try_files $fastcgi_script_name =404;
    
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $path_info;
            fastcgi_param HTTPS on;
            fastcgi_param modHeadersAvailable true;
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
    
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
            fastcgi_max_temp_file_size 0;
        }
    
        location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
            try_files $uri /index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463$asset_immutable";
            add_header Referrer-Policy "no-referrer" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-Permitted-Cross-Domain-Policies "none" always;
            add_header X-Robots-Tag "noindex, nofollow" always;
            add_header X-XSS-Protection "1; mode=block" always;
            access_log off;
        }
    
        location ~ \.(?:otf|woff2?)$ {
            try_files $uri /index.php$request_uri;
            expires 7d;
            access_log off;
        }
    
        location /remote {
            return 301 /remote.php$request_uri;
        }
    
        location / {
            try_files $uri $uri/ /index.php$request_uri;
        }
    }
    
  11. Test the Nginx configuration.

    console
    $ sudo nginx -t
    

    Output:

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  12. Allow Nginx access to Nextcloud files using SELinux.

    console
    $ sudo chcon -R -t httpd_sys_content_t /var/www/nextcloud
    
  13. Restart Nginx web server.

    console
    $ sudo systemctl restart nginx
    
  14. Verify that the Nginx web server is running and active.

    console
    $ sudo systemctl status nginx
    

    Ensure the output shows active (running) to confirm Nginx is operational

Secure Nextcloud with HTTPS

Use Certbot to automatically request and install a TLS certificate from Let’s Encrypt. Certbot integrates with Nginx to configure HTTPS and redirect HTTP traffic securely.

  1. Install Certbot and the Nginx plugin.

    console
    $ sudo dnf install certbot python3-certbot-nginx -y
    
  2. Generate and install the TLS certificate.

    console
    $ sudo certbot --nginx -d nextcloud.example.com
    
    • --nginx: Uses the Nginx plugin to automatically configure HTTPS.
    • -d nextcloud.example.com: Replace with your actual domain name.

    When prompted:

    • Enter your email address for renewal notifications.
    • Accept the terms of service.
    • Choose the option to redirect all HTTP traffic to HTTPS.

    Ensure that port 80 (HTTP) and 443 (HTTPS) are open in the firewall before running Certbot.

Access and Set Up Nextcloud

Once the setup is complete and the containers are running, access your instance by visiting:

https://nextcloud.example.com

From the setup wizard:

  • Create an admin username and secure password
  • Set the data folder path (leave default unless changed)
  • Choose MySQL/MariaDB as the database type
  • Enter:
    • Database user: nextcloud
    • Password: the one you configured
    • Database name: nextcloud
    • Host: db (if using Docker) or 127.0.0.1 (if using local MariaDB)

After completing the setup, you can extend Nextcloud with additional apps, organize and share files, and sync data across devices using the web interface or mobile and desktop clients. This gives you a centralized platform to manage your private cloud storage through an intuitive dashboard.

Conclusion

In this article, you deployed Nextcloud on Rocky Linux 9 using either a manual installation or a Docker-based setup. You secured the deployment with Nginx and HTTPS, configured the database and Redis, and ensured that user data persists on the host system for easier backups.

Running Nextcloud in containers provides isolation, efficient resource use, and flexibility, while the manual method gives you more granular control over the environment. For advanced features such as external storage and groupware tools, see the Nextcloud documentation.

Comments

No comments yet.