Owncloud on FreeNAS 9.2

In which I set-up a cloud file store on FreeNAS...

So firstly there is an easy way to do this. You can install the owncloud plugin provided through the FreeNAS GUI. There are a few reasons not to do this:

  • It only supports SQLite
  • The plugin, as usual, is not the most up-to-date version of the software*

MySQL/MariaDB should be faster than SQLite and also allows multiple concurrent connections.

*The FreeNAS devs do a good job of keeping up-to-date but if you want to be on the latest software you normally need to update your plugins manually.

Set-Up the Jail

Follow the users guide to set up a new jail. You can either set-up a portjail (which already includes and extracted version of ports) or use a standard jail (since you would likely need to update ports anyway).

The use the GUI to run a shell as the jail before continuing to issue these commands.

Extract ports:

portsnap fetch extract

Update pkg:

pkg update -f

Install Packages

First you're going to need to install all the packages for the webserver (nginx), php and MySQL:

pkg install nginx mariadb55-server php55-extensions php55-curl\
php55-exif php55-fileinfo php55-gd php55-mbstring php55-pdo_mysql\
php55-openssl php55-zip php55-zlib
make install clean -C /usr/ports/devel/pecl-APCu

During the install of pecl-APCu accept all prompts with the standard settings.

Then enable everything in /etc/rc.conf:

nginx_enable="YES" php_fpm_enable="YES" mysql_enable="YES"

Setup Webserver

Go to /usr/local/etc/nginx/nginx.conf and edit it to look like this:

### Change the number of workers to the same number of cores 
### your server has 
worker_processes 4;

events { 
    worker_connections 1024; 
}

http { 
    include mime.types; 
    default_type application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    access_log logs/access.log main; 
    sendfile off; 
    keepalive_timeout 65; 
    gzip off;

    #SSL 
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_ciphers ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM; 
    ssl_prefer_server_ciphers on; 
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;

    # Redirects HTTP to HTTPS 
    server {
        listen 80; 
        ### Change the following two lines to match your website name
        server_name www.example.com 192.168.; 
        return 301 https://example.com$request_uri;

        # Prevent Clickjacking 
        add_header X-Frame-Options "SAMEORIGIN";
        }
     server { 
         listen 443 ssl;
        ### Change the following line to match your website name
        server_name www.example.com 192.168.0.X; 
        root /usr/local/www;

        # Prevent Clickjacking 
        add_header X-Frame-Options "SAMEORIGIN";
        # SSL Settings 
        ### If you are using different names for your SSL certificate and key, change them below: 
        ssl_certificate /usr/local/etc/nginx/ssl-bundle.crt;
        ssl_certificate_key /usr/local/etc/nginx/server.key; 
        add_header Strict-Transport-Security "max-age=16070400;
        includeSubdomains";
        location = /robots.txt { allow all; access_log off; log_not_found off; }
        location = /favicon.ico { access_log off; log_not_found off; }
        location ^~ /owncloud { 
            index index.php;
            try_files $uri $uri/ /index.php?$args;
            client_max_body_size 5120M; 
            location ~ ^/owncloud/(?:\.|data|config|db_structure\.xml|README) { 
                deny all;
            } 
            location ~ \.php(?:$|/) { 
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info; 
                include fastcgi_params;
                fastcgi_param MOD_X_ACCEL_REDIRECT_ENABLED on;
            } 
            location ~* \.(?:jpg|gif|ico|png|css|js|svg)$ {
                expires max; add_header Cache-Control public;
            }
            location ^~ /owncloud/data { 
                internal;
                ### Change this to the directory you wish to use for files
                alias /mnt/files;
            }
        }
    }
}
}

If you have an SSL certificate install it. If you want to use a self-signed certificate use these commands and follow the on screen prompts:

cd /usr/local/etc/nginx 
openssl genrsa -des3 -out server.key 2048 
openssl req -new -key server.key -out server.csr 
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out ssl-bundle.crt 
cp server.key server.key.orig 
openssl rsa -in server.key.orig -out server.key

Configure PHP

Copy the default php.ini file:

cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini

Then edit the following lines of the /usr/local/etc/php.ini file:

date.timezone =Europe/London
cgi.fix_pathinfo=0 
upload_max_filesize = 5120M 
post_max_size = 5120M

Make sure to set date.timezone to your own timezone.

Edit the following lines of /usr/local/etc/php-fpm.conf:

listen = /var/run/php-fpm.sock 
listen.owner = www 
listen.group = www 
env[PATH] = /usr/local/bin:/usr/bin:/bin

Setup MySQL

Create the MySQL configuration file at /var/db/mysql/my.cnf:

[server] socket = /tmp/mysql.sock 
skip-networking 
skip-name-resolve 
default-storage-engine = innodb 
innodb_flush_method = O_DIRECT 
skip-innodb_doublewrite 
innodb_flush_log_at_trx_commit = 2 
innodb_file_per_table 
expire_logs_days = 1

Then start the web server and initilaise the MySQL database:

service nginx start
service php-fpm start
service mysql-server
start mysql_secure_installation
mysql -u root -p
CREATE DATABASE owncloud; 
GRANT ALL PRIVILEGES ON owncloud.* TO 'ocuser'@'localhost' IDENTIFIED BY 'ocpass'; 
FLUSH PRIVILEGES; 
quit;

Make sure to change <ocpass> to a password of your choice.

Install OwnCloud

Install the owncloud source files:

fetch "http://download.owncloud.org/community/owncloud-7.0.1.tar.bz2" 
tar jxf owncloud-*.tar.bz2 -C /usr/local/www 
rm owncloud-*.tar.bz2

Make sure to change the source file to the latest file available from http://owncloud.org/install/.

Then ensure the user 'www' can access the mount point for your files and:

chown -R www:www /usr/local/www/owncloud /mnt/files

Setup cron:

crontab -u www -e

Then append† the following:

*/15 * * * * /usr/local/bin/php -f /usr/local/www/owncloud/cron.php

†The vi command is :a. Then use :wq to write and quit.

Setup OwnCloud

Now point your web browser to https://<jail ip>/owncloud and you'll get this setup screen:

And make sure to change the details to match your mount point and MySQL database.‡

Once you've logged in go to the Admin settings on the top-right and make sure to tick 'Enforce HTTPS'. This will force anyone connecting to your server to use a secure connection.

If you already have a lot of data on your server and want to make it available to your OwnCloud then you can make mount points through the FreeNas GUI:

Jail storage in FreeNAS
Jail storage in FreeNAS

Currently there is a problem where the FreeNAS GUI can't create a mount point. You'll need to make them using the jail shell. Then the GUI will be able to mount the folder correctly.

‡Set localhost to be localhost:/tmp/mysql.sock

Allow Access Across the Internet

The error message when accessing owncloud from outside your LAN.
The error message when accessing owncloud from outside your LAN.

If you wish to use a dynamic DNS service to allow access to your storage from anywhere you will need to add one line to config.php. The file in question is /usr/local/www/owncloud/config/config.php:

'trusted_domains' => array('foo.example.com'),

Tom Out!

References

This post is an amalgamation of sources that got me most of the way to a working environment. I have chosen the relevant parts from each reference to make this guide:

[1] [How-To] ownCloud using NGINX, PHP-FPM, and MySQL by Joshua Parker Ruehlig

[2] Pydio: Installing on FreeBSD (nginx and PHP-FPM) by Abstrium SAS

[3] FreeNAS 9.2.1 User's Guide  by iXsystems, Inc

[4] PHP: List of Supported Timezones by The PHP Group

[5] Untrusted Domain by RandolphCarter