NextCloud Logo

Installing NextCloud on Debian 11 LEMP

NextCloud Logo

NextCloud is a fantastic solution to manage documents, however the added app features, including integration with Collabora CODE server makes it an invaluable method to store your files and access them remotely.

In this tutorial we will assume that you know the basics of deploying your server with DNS and IP Routing and that routes to your chosen Debian 11 server and that you are working as root, if not, you can use a user with sudo privileges, however you will need to append sudo to the appropriate commands listed here.

  1. Update Debian:
    As always, we want to start on an up-to-date Debian server.

    apt update && apt upgrade -y
  2. Install Prerequisites:

    apt install nginx unzip php php-{gd,curl,zip,dom,xml,simplexml,mbstring,intl,fpm,json,ctype,posix,xmlreader,xmlwriter,fileinfo,bz2} mariadb-server mariadb-client certbot -y
  3. Configure MariaDB database:
    You will need to create a database and user for using NextCloud:


    And run the following SQL Commands:

    CREATE DATABASE nextcloud_db;
    CREATE USER 'nextcloud_user'@localhost IDENTIFIED BY 'Strong_Password';
    GRANT ALL ON nextcloud_db.* TO 'nextcloud_user'@localhost;
  4. Download the latest version of NextCloud (24.0.3 at the time of writing):

  5. Now unzip the package and move it to your webserver folder:

    mv nextcloud /var/www/html/nextcloud
  6. You will need to adjust give the WebServer permissions to access the folder:

    chown -R www-data:www-data /var/www/html/nextcloud
  7. Set Up NextCloud Data Folder:

    mkdir /var/www/html/nextcloud/data
    chown -R www-data:www-data /var/www/html/nextcloud/data
    chown -R 755 /var/www/html/nextcloud/data
  8. Generate an SSL Certificate with CertBot:

    certbot certonly --webroot --webroot-path /var/www/html/nextcloud -d --agree-tos --email
  9. Create a VirtualHost for NginX:
    Create the virtualhost file:

    nano /var/nginx/conf.d/nextcloud.conf

    And paste the following (Changing the server_name to your own configuration):

    upstream php-handler {
        server unix:/run/php/php7.4-fpm.sock;
    map $arg_v $asset_immutable {
        "" "";
        default "immutable";
    server {
        listen 80;
        listen [::]:80;
        server_tokens off;
        error_log /var/log/nginxnextcloud_error.log;
        access_log /var/log/nginx/nextcloud_access.log;
        return 301 https://$server_name$request_uri;
    server {
        listen 443 ssl; # managed by Certbot
        listen [::]:443 ssl; # managed by Certbot
        root /var/www/html/nextcloud;
        server_tokens off;
        error_log /var/log/nginxnextcloud_error.log;
        access_log /var/log/nginx/nextcloud_access.log;
        ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
        add_header Strict-Transport-Security "max-age=31536000" always; # managed by Certbot
        ssl_trusted_certificate /etc/letsencrypt/live/; # managed by Certbot
        ssl_stapling on; # managed by Certbot
        ssl_stapling_verify on; # managed by Certbot
        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 application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/ 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-Download-Options                   "noopen"        always;
        add_header X-Frame-Options                      "SAMEORIGIN"    always;
        add_header X-Permitted-Cross-Domain-Policies    "none"          always;
        add_header X-Robots-Tag                         "none"          always;
        add_header X-XSS-Protection                     "1; mode=block" always;
        fastcgi_hide_header X-Powered-By;
        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\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/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|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
            try_files $uri /index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463, $asset_immutable";
            access_log off;
            location ~ \.wasm$ {
                default_type application/wasm;
        location ~ \.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;
  10. Deploye NextCloud:
    You can now use your browser to browse to and complete the setup process with the username and database you configured in step 3.
  11. Manual Installation of Collabora CODE Server (Optional – Might fail in web-interface due to the size):
    Due to the size of the installation, this might often fail to update or install from the web-interface, the solution is to use the occ command from within the root of your NextCloud installation folder to manually install this, so first enter that folder:

    cd /var/www/html/nextcloud

    And run the following command:

    sudo -u www-data php -d memory_limit=512M ./occ app:install richdocumentscode

    Occasionally, you might need to run updates and for the same reason the Collabora CORE Server might fail to update, you can use the occ update command instead:

    sudo -u www-data php -d memory_limit=512M ./occ app:update --all


That is it, you have now successfully deployed NextCloud in your Debian Server using a LEMP stack.


Leave a Reply

Your email address will not be published. Required fields are marked *