Owncloud with Nginx on RPi

Background

One of the first projects I tried with the Raspberry Pi was setting it up to work as a private cloud service with a 3TB external hard drive that I had. First iterations with the RPi 1 and 2 were slow or buggy, but I am hoping to get it right this time with the RPi 3. In this post we will start with a new RPi and build the whole thing. What you will need:

  • RPi 3
  • HDMI Cable
  • Micro USB Power Adapter for RPi
  • Keyboard & Mouse
  • Micro SD Card
  • External hard drive
  • Computer
  • Card reader

RPi Setup

So lets get started with setting up the RPi for the first time. Head over to the RPi website and download a version of Raspbian Lite to your computer. You will also need a way to write the Raspbian image to the sd card. I like to use Win32 Disk Imager, which you can get from here.

Unzip the image of raspbian that you download with something like 7-zip (another tool you can easily download) and pop your Micro SD Card into your computers card reader. Open Win32 Disk Imager and under device select the drive letter that is assigned to your SD card. Then click the blue folder and navigate to where the unzipped Raspbian image is. It is then as easy as clicking Write.

win32diskimager

Next you will need to connect up the RPi to a monitor, keyboard and mouse. Insert the micro SD card and finally power on the RPi by plugging in the micro USB cable.

Text will start scrolling down the screen hopefully and you will be presented finally with a login prompt. The default login is pi and the password is raspberry. The first step I would take after this would be to change the password. Type the below commmand in and you will be asked to type a new password twice.

login


sudo passwd pi

Now lets change some of the basic settings of the RPi, ready for the Owncloud. The below command will open a blue screen. First press Enter on Expand Filesystem, this will open up you full SD card as storage. Next hit down arrow to Advanced Options and then down again to Memory Split. Enter in a value of 16, this reduces the memoy for graphics, which will not be needed in this case. Finally under Adavances Options again select SSH and enable it. When asked if you want to reboot pick yes.


sudo raspi-config

After you have logged back in again we should set up the internet. I’ll assume you will be using wifi but if not just plug in an ethernet cable into the RPi from your router and it should just work. To setup the wifi, we need to open up the config file using:


sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Then add the wifi SSID and passkey in the fields shown below. Then hit CTRL + X and Y to save the changes.

wifi

Next reboot the RPi with


sudo reboot

With SSH enabled and the wifi hopefully setup correctly, it will be helpful to SSH into the RPi from your normal computer so that you can follow this tutorial while making changes. First you will need to get the IP address of the RPi on the local network.


sudo ifconfig

ip

This should show you something similar to above. If you are connected via ethernet cable then the inet addr entry under eth0 is your IP address. Otherwise with wifi it will be under the wlan0 entry.

In windows the most popular tool for SSH is Putty. Download this, launch it and enter in your IP address. This should launch a window for you to log into like before.

putty

Now I think that is pretty much everything setup on the RPi. Now to install Owncloud and its dependent software with the correct configuration.

Dependent Software

Most of the credit here has to go to the author of this blog, which helped me figure out the process. I am adding some more detail in areas like DDNS setup, hard drive formatting and less in others.

First we need to install all the dependent packages for Owncloud by running the below line. A brief description of what all this is:

  • Nginx: A web server that will serve up owncloud to the web
  • PHP5: A server side coding language that makes owncloud work 😉
  • SQLLite: Database package that will be used to record all our files in the cloud
  • OpenSSL: This will allow us to generate SSL certs for secure internet connections
  • Parted: For creating partitions on the hard drive

sudo apt-get install nginx openssl ssl-cert php5-cli php5-sqlite php5-gd php5-common php5-cgi sqlite3 php-pear php-apc php5-curl libapr1 libtool curl libcurl4-openssl-dev php-xml-parser php5 php5-dev php5-gd php5-fpm memcached php5-memcache varnish php5-apcu parted

SSL Certs

With everything installed lets create the SSL certs that will keep our internet connections relatively secure. Here we will create default certs that shouldn’t really be used long term as they have not been approved. I will look to purchase some in the future and will write a post about how to use them correctly.Use the below command to generate the files into the directory /etc/ssl/certs/ and /etc/ssl/private/


sudo make-ssl-cert generate-default-snakeoil --force-overwrite 

DDNS Setup

With a secure connection we will need a way to access the cloud server over the internet. This requires a dynamic DDNS service which will replace your public IP address with an easy to use domain name like example.ddns.com. There are many providers that offer this free but I have stumbled across a particularly good one in the form of Dynu. I purchased the domain name www.jfinch91.co.uk from Ghandi for a fiver a year and Dynu allows you to use this free with their dynamic DDNS service or use one of their free domain names.

Head over to the webiste in the link above and setup an account. Then click on the three cogs in the top right corner of the web page and select DDNS Services. On the next page add a new domain and within minutes it will be ready to use. If you do not have a static IP address from your internet provider you will need to download Dynu’s DDNS client onto your RPi so that if your internet provider changes your IP address your DDNS record is updated.

From the DDNS menu at the top select Setup. On the right hand side select Linux. Follow the instructions on this page and use the first configuration example.

Nginx Config

Now we need to setup the web server Nginx. This is a bit of a new one to me as I previously used Apache but this seems to be much faster. Now this involves editting the default config for nginx.


sudo nano /etc/nginx/sites-available/default

The config I used very much resembles the one recommended in the Owncloud documentation. Now I don’t understand all of what is going on in this config but a few google searches on the keywords should reveal all. For a quick setup delete everything in the default file and paste this in.

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

server {
    listen 80;
    server_name cloud.example.com;  <------ CHANGE THIS TO YOUR DDNS ADDRESS
    # enforce https
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name cloud.example.com; <------ CHANGE THIS TO YOUR DDNS ADDRESS
	
    include snippets/snakeoil.conf		
    #ssl_certificate /etc/ssl/nginx/cloud.example.com.crt;
    #ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

    # 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=15552000; includeSubDomains";
    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/owncloud/;

    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;
    }

    location /.well-known/acme-challenge { }

    # set max upload size
    client_max_body_size 2000M;
    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)/ {
        return 404;
    }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
        return 404;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|core/templates/40[34])\.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        #fastcgi_request_buffering off; #Available since nginx 1.7.11
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri $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)$ {
        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=15552000; includeSubDomains";
        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 ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don't log access to other assets
        access_log off;
    }
}

After completing all the above changes restart the Nginx server. Hopefully you don’t get any errors.


sudo service nginx restart

Port Forwarding

Now that you have an easy domain to access your home network, you will need to setup port forwarding on your router to direct requests to the RPi and the Owncloud service running on it. This is slightly different for each router but if you have one from one of the main internet providers a quick google on how to port forward on that stock router should return a useful guide.

You will want to port forward 80 and 443 based on the configuration above to the IP address of your RPi that you took down earlier. This will route requests to your DDNS hostname to your RPi where owncloud is running.

Files Size Settings

Next we will tweek some settings to allow reasonable file uploads. Press CTRL + W when the below file is open to search for upload_max_filesize and set the value to 2000M. Repeat for post_max_size.


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

Next open the file below and change listen = /var/run/php5-fpm.sock to listen = 127.0.0.1:9000


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

Finally repeat for CONF_SWAPSIZE=100 to CONF_SWAPSIZE=512 in the below. Then reboot the RPI like before.


sudo nano /etc/dphys-swapfile

Format External Hard Drive

Moving onto the storage for our cloud server. I really think if you are going to attempt this, it should be with an external hard drive that has its own power supply. This means that you are not writing to the SD card which most likely won’t have as much space and you are not drawing power from the RPi with a portable drive. I wanted to start a with a fresh hard drive so I decided to format it using the RPi with the below commands. Connect the hard drive via USB and type


# list the connected drives
lsblk 

There should be a drive with a name like sda that has a size roughly matching the size of your hard drive. If you have partitions lets delete them (warning this will delete any data on the drive!)


# start parted 
sudo parted /dev/sda

# print partitions
print

# delete each partition, repeat for each number
rm 2 

# exit
q

Now lets create some partitions and format the drive.


# started parted 
sudo parted /dev/sda 

# set label
mklabel gpt

# create partition for size of hard drive
mkpart primary ext4 0% 100%

# exit 
q

# now create filesystem with a label using the -L option
sudo mkfs.ext4 -L lablename /dev/sda1

# let's update the filesystem table to mount this hard drive to the RPi
sudo nano /etc/fstab

# add this line to the bottom of the file, this will mount the drive to the directory /media 
LABEL=labelname /media ext4 defaults 0 2

# create a folder on the hard drive for storage
sudo mkdir /media/cloud

# change permission of the hard drive 
sudo chown -R www-data:www-data /media/cloud

# reboot RPi
sudo reboot

Owncloud Installation

Finally we can install Owncloud. Head over to the Owncloud install website and copy the link for the linux download of the server.


# go to the home directory
cd ~

# create a downloads folder and move into it
sudo mkdir downloads
cd downloads

# download owncloud 
sudo wget PASTE THE DOWNLOAD LINK HERE

# extract files
sudo tar xvf owncloud-x.x.x.tar.bz2

# copy files to folder
sudo cp owncloud /var/www

# change permissions of this folder 
sudo chown -R www-data:www-data /var/www

# last few changes for files sizes
sudo nano /var/www/owncloud/.htaccess 

# then set the following values to 2000M: 
Php_value upload_max_filesize 
Php_value post_max_size 
Php_value memory_limit 

# again
sudo nano /var/www/owncloud/.user.ini 

# then set the following values to 2000M: 
upload_max_filesize 
post_max_size 
memory_limit

First Run of Owncloud

Now you should be able to visit your DDNS host name in a web browser and start the first setup. You will be asked to setup a username and password. Then change the storage location to that on the hard drive /media/cloud. The first setup will take a couple minutes but then you should be logged in and taken to your Files section like the picture at the top of this post.

If you have any issues at this point head over to the Owncloud website, there is a large community that can help with solving any issues you may have. Someone will have been in the same situation. Furthermore you will want to download the desktop or mobile client to sync files to your Owncloud server.

Hopefully this setup has worked out for you. There will be some errors highlighted at the top of the web page when you login. I will try and figure out how to solve these and post back here, it is most likely in the Owncloud documentation already.

jfinch91Owncloud with Nginx on RPi