July 10, 2017

Hosting Nextcloud on a nginx Web Server

A good while ago I ditched my so-far preferred file-synchronization solution Syncthing for Nextcloud. The reason for this step was that Syncthing behaved in odd ways quite often: sometimes it didn't find content that should be synced, at other days the sync process got stuck and wouldn't complete. I really got annoyed fixing my Syncthing cluster manually almost weekly and started to play with Nextcloud.

I decided not to have just one Nextcloud instance, but two: one instance on a public vServer (Debian Jessie; mostly to sync calendars and contacts between Mac OS and iOS devices, and sharing files with others), the other instance (Ubuntu 16.04 TLS; mostly for my personal file sync needs) on an old Cubitruck (think “beefed-up Raspberry Pi”) sitting in my private home network reachable only via VPN.

One new problem I stumbled upon is that both machines are a little weak on the chest. Albeit both Nextcloud instances worked flawless, a “snappy user experience” was something totally different. Interestingly, the sluggish performance didn't affect file sync too much. But when you interacted a lot with Nextcloud via the browser, for instance when using Calendar and Contacts, things were really slow. By this reason I ditched another good old friend and said goodbye to Apache, and installed nginx, which is said to be more performant. However, I had no idea of nginx and didn't use it before, so I had to play a little before I started with the Nextcloud migration…

First of all, you get nginx by typing apt install nginx. To my surprise, nginx configuration is much easier than Apache configuration. I started with a configuration for a vHost for my blog by modifying the default config: /etc/nginx/sites-enabled/default. After throwing out some things and adapting others I ended with something like that:

(File: /etc/nginx/sites-available/blog.conf)
server {
    listen 80;
    root /var/www/html/blog/;
    server_name blog.tld www.blog.tld;
    index index.html index.htm;
    location / {
            try_files $uri $uri/ =404;
    }
}

Now symlink that file into /etc/nginx/sites-enabled and reload nginx: systemctl reload nginx.service. The blog vHost works via HTTP.

But how to enable an HTTPS-only configuration as I had before when using Apache? Well, Certbot to the rescue: you just have to execute ./certbot-auto --nginx --force-renew -d blog.tld -d www.blog.tld, wait a while and then select option 2 so that Certbot rewrites your configuration in a way that HTTPS is always enforced. So you end up with something like that:

(File: /etc/nginx/sites-available/blog.conf)
server {
    listen 80;
    root /var/www/html/blog/;
    server_name blog.tld www.blog.tld;
    index index.html index.htm;
    location / {
            try_files $uri $uri/ =404;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/blog.tld/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/blog.tld/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    } # managed by Certbot
}

Again systemctl reload nginx.service. The blog vHost now uses HTTPS only. Neat. Enough playing and back to Nextcloud:

As Nextcloud is a PHP application, I first had a look into the (German) Ubuntu docu on how to enable PHP for nginx. I found out that nginx differs from Apache in a way that it needs pre-spawned PHP processes waiting to process PHP scripts upon request of nginx. The named docu's default way to pre-spawn such processes is using php-cgi. However, I cannot recommend this approach as after some hours all PHP processes seemed to have died and no new ones were created automatically. Result: Nextcloud didn't work anymore.

More investigation: I found out that you want to have something called php-fpm - “pm” stands for “proess manager”. This works much better and more reliably as php-fpm automatically takes care that always enough pre-spawned PHP processes exist. Now install that with apt install php-fpm.

I first tried to write my own nginx configuration for my Nextcloud vHost but failed. Luckily, there is a (pretty impressive) nginx configuration on the Nextcloud help pages. This (more or less) worked out of the box after adapting some paths and the domain name. When you are using php-fpm as I suggested earlier take care that the config starts like that:

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

However, I found two not critical warnings in the Nextcloud admin menu. One about missing environment variables, the other configuration suggestions to improve cache performance:

warning

The first “problem” can be solved by editing following file /etc/php5/fpm/pool.d/www.conf. Hint: if you are using PHP 7, the file is located in /etc/php/7.0/fpm/pool.d/www.conf. You just have to enable (remove ;) following lines:

env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

Then type systemctl reload php5-fpm.service. Done.

Now edit /etc/php5/fpm/php.ini (resp. /etc/php/7.0/fpm/php.ini) and apply all settings as suggested by the Nextcloud instance. Again, systemctl reload php5-fpm.service. Done.

I have no real measurements to compare the performance of a nginx-hosted Nextcloud vs. an Apache-hosted Nextcloud. But I'd say this is at least (!!) 20-30% quicker. Especially for the Calendar app the performance gain is quite dramatic.

Another thing that I tested on the Debian Jessie vServer was HTTP/2. For this purpose I had to include some additional repository provided by the nginx guys into /etc/apt/sources.list as Debian Jessie only provides a quite old nginx version. I honestly did not experience any further performance gain after activating HTTP/2 in a vHost config file. So I removed that repository and the just installed nginx version as I am not too happy with non-official repos.

Time for a conclusion: Migrating Nextcloud to nginx took a good while but I can recommend that step. Especially when you are using quite low-powered systems to host your Nextcloud instance you will experience a significant performance boost. In case your distro does not provide a nginx version supporting HTTP/2, the extra effort to get a newer nginx version is not worth the hassle in my observation.

© holger 2015 - 2020 |