Nextcloud 11 on Debian Jessie with Nginx / PHP / MySQL

1. Introduction

Nextcloud is an open source, self-hosted file sync and share and communication app platform. Access & sync your files, contacts, calendars and more.

Installation on a OVH server (Kimsufi) for testing purpose.

2. Installation and configuration

First,a quick system update :

apt-get update
apt-get upgrade

Install the Nginx web server :

apt-get install nginx

Install MySql database server:

apt-get install mysql-server

Run the MySql secure installation :

mysql_secure_installation

Create a “nextcloud” database and a “nextcloud” user. Change the “PasswordToBeChanged” by a strong password !

mysql -u root -p
mysql> create database nextcloud;
mysql> CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'PasswordToBeChanged';
mysql> GRANT ALL ON nextcloud.* TO 'nextcloud'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> quit

Install PHP5 and everything required by NextCloud :

apt-get install php5-fpm php5-mysql php5-gd php5-json php5-mysql php5-curl php5-intl php5-mcrypt php5-imagick

Edit the php.ini file :

sudo vi /etc/php5/fpm/php.ini

And change the cgi.fix_pathinfo to 0 as below :

; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec.  A setting
; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; http://php.net/cgi.fix-pathinfo
;cgi.fix_pathinfo=1
cgi.fix_pathinfo=0

Restart the php-fpm daemon :

sudo systemctl restart php5-fpm

Edit a new virtual host for Nextcloud :

sudo vi /etc/nginx/sites-available/nextcloud

With the following content.
Replace the following :
– cloud.mydomain.fr : The domain you use for Nextcloud
– /etc/letsencrypt/…/fullchain.pem : Your Let’s Encrypt files
– /etc/letsencrypt/…/privkey.pem : Your Let’s Encrypt files

upstream php-handler {
    #server 127.0.0.1:9000;
    server unix:/var/run/php5-fpm.sock;
}

server {
    listen 80;
    server_name cloud.mydomain.fr;
    # enforce https
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name cloud.mydomain.fr;

    ssl_certificate /etc/letsencrypt/live/domain.fr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.fr/privkey.pem;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security "max-age=15768000;
    # includeSubDomains; preload;";
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    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;

    # Path to the root of your installation
    root /var/www/nextcloud/;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
    # last;

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Disable gzip to avoid the removal of the ETag header
    gzip off;

    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;

    error_page 403 /core/templates/403.php;
    error_page 404 /core/templates/404.php;

    location / {
        rewrite ^ /index.php$uri;
    }

    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)(/.*)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        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|woff|svg|gif)$ {
        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)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security "max-age=15768000;
        #  includeSubDomains; preload;";
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options "SAMEORIGIN";
        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;
        # Optional: Don't log access to assets
        access_log off;
    }

    location ~* \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don't log access to other assets
        access_log off;
    }
}

Check your Nginx configuration:

sudo nginx -t

You should obtain something like :

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If it’s ok, you can restart Nginx :

sudo systemctl reload nginx

Go in the www directory :

cd /var/www/

Download Nextcloud :

wget --no-check-certificate https://download.nextcloud.com/server/releases/nextcloud-11.0.1.zip

And check the integrity :

wget --no-check-certificate https://download.nextcloud.com/server/releases/nextcloud-11.0.1.zip.sha256
sha256sum -c nextcloud-11.0.1.zip.sha256 < nextcloud-11.0.1.zip

Everything should be ok :

nextcloud-11.0.1.zip: OK

Install unzip if you don't have it on your system :

sudo apt-get install unzip

Then we can unzip the downloaded file :

unzip nextcloud-11.0.1.zip

Once it's done, open a browser and you're done. You can then follow this procedure

3. Issues

On the admin page, you might have a few errors to be fixed.

3.1 getenv("PATH") only returns an empty response

php does not seem to be setup properly to query system environment variables. The test with getenv("PATH") only returns an empty response.
Please check the installation documentation ↗ for php configuration notes and the php configuration of your server, especially when using php-fpm.

Edit the following file :

sudo vi /etc/php5/fpm/pool.d/www.conf

And uncomment the "env[PATH]" line as below :

; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

Then restart the php-fpm daemon :

sudo systemctl restart php5-fpm

3.2 The "Strict-Transport-Security" HTTP header is not configured to at least "15552000" seconds.

The "Strict-Transport-Security" HTTP header is not configured to at least "15552000" seconds. For enhanced security we recommend enabling HSTS as described in our security tips.

Edit your Nextcloud virtual host configuration file:

sudo vi /etc/nginx/sites-available/nextcloud

Uncomment the following lines :

    add_header Strict-Transport-Security "max-age=15768000;
    includeSubDomains; preload;";

Check your Nginx configuration:

sudo nginx -t

You should obtain something like :

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If it's ok, you can restart Nginx :

sudo systemctl reload nginx

4 thoughts on “Nextcloud 11 on Debian Jessie with Nginx / PHP / MySQL”

  1. Thanks.
    I always used Debian in the past and then I set up centos also. Everything was fine and dandy until I went for nextcloud. I did get it running in centos but it took some heavy work and a week of my time (2 hours/day), then I upgraded to nextcloud 11 and got so many issues. Finally I gave up centos even though I like it a lot and went back to my stable Debian and read through your things. My Debian server is quite heavily modified but I got nextcloud running in less then an 1 hour and as I want. Thank you for the tips and tricks. It helped a lot.

  2. Thanks for this guide,

    one small correction, I had to enable the nginx conf using :

    sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/nextcloud

    1. Thanks Clément. I was creating a configuration file from scratch, but it’s good to know !

Leave a Reply to Ronan Cancel reply

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