How to configure OwnCloud on a LNMP (Linux + Niginx + MySQL + PHP-FPM) stack?

Recently, I have got tired with the little space that Dropbox has and decided to explore my own options, a few potential candidates came up, SparkleShare was the first one to consider, except somehow I got the impression that the product is still pretty much in a beta stage and is relatively new and unstable. Hence I decided to take a look at OwnCloud, which seems to be a more mature product with a relatively larger user base.

Initially I was using an LAMP (Linux + Apache + MySQL + PHP) since it was given by my VPS provider by default, and seems rather easy to install. However, the performance was not good. Sometimes it took the server a minute for the web page to load up once after I signed in and to me that is definitely not the kind of speed I would like to see, so I have decided to explore an LNMP option, to use Linux + Nginx + MySQL + PHP-FPM to set up my OwnCloud.

Note that I have used Debian Squeeze as the OS to set up Owncloud, however as I have complied all the packages myself from the source code, these methods and tricks will essentially work on any Linux distributions.

As OwnCloud requires a few PHP libraries, I have decided to compile my own PHP installation and after some Googling online, here is one configuration that worked for me, note that because I planned to use MySQL as the backend, so I added some configuration options to include the relevant MySQL drivers. Also, I suspect some of the packages may not be necessary here, such as SOAP, but this is at least something that worked well for me. I used the latest PHP 5.4.8 package to compile but I suspect it should work on the earlier packages as well:

image

For those who are too lazy to type it out, here is the configuration options that you can use:

./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-magic-quotes --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-mbstring --with-mcrypt --enable-ftp --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --without-pear --with-gettext --disable-fileinfo

For everything else, I just installed as per the default configurations (you can take a look at the installation instructions here), note that I used www-data:www-data for PHP-fpm and if you decide to do the same, make sure Nginx is running as www-data:www-data as well.

Once this is done, download the installation package to your document root and decompress the package:

wget http://mirrors.owncloud.org/releases/owncloud-4.5.0.tar.bz2
tar -jxf owncloud-4.5.0.tar.bz2

Note that I used the OwnCloud 4.5 instead of the 4.0 version. Next you will need to change the owner of the package to www-data:www-data.

chown -R www-data:www-data owncloud

Next, I have added in a few configuration blocks indicated on the official webserver notes page to adapt to some customized configuration that OwnCloud would need to run WebDav and stuff, in particular, here is what I added:

  # deny direct access
  location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
    deny all;
  }

  # default try order
  location / {
    try_files $uri $uri/ @webdav;
  }

  # owncloud WebDAV
  location @webdav {
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    unix:/tmp/php-cgi.sock;
    #fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #fastcgi_params HTTPS on;
    include fcgi.conf;
  }

Note that I have turned off fastcgi_params HTTPS on because I am not using HTTPS connection and SCRIPT_FILENAME is commented as well since it showed up in my fcgi.conf, which is a customized version of the fastcgi_params file, if you did not have a customized version of it, you will need to add the SCRIPT_FILENAME parameter.

Restarted php-fpm and log into the server, set up a user name and password and clicked on the Advance Options and select MySQL as the database, entered the MySQL credentials that I have created earlier.

I thought I was done, turned out not to be the case. In fact, this is what I am seeing once after I logged in:

image

So I started to look around to try to figure out why, and the first error I saw in my Nginx error log is this:

PHP message: PHP Warning:  Invalid argument supplied for foreach() in DOC_DIR/owncloud/lib/l10n.php on line 322
PHP message: PHP Warning:  scandir() has been disabled for security reasons in DOC_DIR/owncloud/lib/l10n.php on line 321

Where DOC_DIR is the document directory I upload my Owncloud installations to. The fix for this one is relatively easy, go to php.ini file (in my case it is at /usr/local/php/etc/php.ini but yours could be different depending on the PHP configuration options), edit the DISABLED_FUNCTION line to make sure scandir is removed, and restart your php process.

I then tried to refresh the page and hope for the best, but again to my great disappointment, the page looked almost the same. So I tried to dig into the error log again and this is what I found:

2012/10/21 21:45:08 [error] 28179#0: *7 open() "DOC_DIR/owncloud/remote.php/core.css" failed (20: Not a directory)
2012/10/21 21:45:09 [error] 28179#0: *9 open() "DOC_DIR/owncloud/remote.php/core.js" failed (20: Not a directory)

This appears to be a path problem which means the rewrite regex has to be fixed, and after some Googling, this post came to rescue:

Basically, you will need to add the following Nginx configuration to the server block:

                location ~ ^/owncloud/remote.php(/.*)$ {
                        fastcgi_split_path_info ^(.+\.php)(/.*)$;
                        fastcgi_pass unix:/tmp/php5-cgi.sock;
                        #include fastcgi_params;
			include fcgi.conf;
                        #fastcgi_param HTTPS on;
                }

Again I made some edits to make sure it matches with the kind of set up that I have:

So here is how everything looks like in the end:

server
        {
                listen       80;
                server_name MyOwnCloudURL;
                index index.php;
                root  DOC_DIR/owncloud;
		client_max_body_size 1000M; # set maximum upload size

                location ~ ^/remote.php(/.*)$ {
                        fastcgi_split_path_info ^(.+\.php)(/.*)$;
                        fastcgi_pass unix:/tmp/php-cgi.sock;
                        include fcgi.conf;
                }

                  # deny direct access
                  location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
                    deny all;
                  }

                  # default try order
                  location / {
                    try_files $uri $uri/ @webdav;
                  }

                  # owncloud WebDAV
                  location @webdav {
                    fastcgi_split_path_info ^(.+\.php)(/.*)$;
                    fastcgi_pass unix:/tmp/php-cgi.sock;
                    include fastcgi_params;
                  }

                location ~ .*\.(php|php5)?$
                        {
                                try_files $uri =404;
                                fastcgi_pass  unix:/tmp/php-cgi.sock;
                                fastcgi_index index.php;
                                include fcgi.conf;
                        }
		}

And this time, I hit refresh button on my browser again and everything worked!:

image

The calendar page appeared to work too!:

image

In conclusion, a few things you have to fix for a LNMP stack to work with Owncloud:

  • Compile PHP with all the required libraries
  • Enable scandir() function
  • Change the rewrite for remote.php
  • UPDATE: As per comment below, here is another potential fix: set cgi.fix_pathinfo=1 on /etc/php5/fpm/php.ini, thanks Mbembi for the comments and Christos for the confirmation!

Of course, the usual stuff such as change the ownership remains, hopefully this little guide will help you to get through the pain to get OwnCloud working and have your own storage on the cloud!