Raspberry Pi OwnCloud: Your Own Personal Cloud Storage

In this project, we’re going to make a Raspberry Pi Owncloud server this can act as your very own personal cloud storage.

Raspberry Pi Owncloud

As the protection of your privacy becomes harder and harder, you may be thinking of moving your files to a private cloud storage. If this is the case, then this tutorial is perfect for you.

It is important to remember that since your data will be stored on your local network, you will end up with using more bandwidth if uploading and downloading files from outside your network.

This tutorial will take you through everything you need to know to get Owncloud setup and accessible.

If you’re curious and want to learn more about the Owncloud software, then be sure to check out their website over at Owncloud.org.


I made use of the following equipment for this personal cloud storage setup.


Raspberry Pi

SD Card (8GB+ Recommended) or Micro SD Card if you’re using a Raspberry Pi 2 or B+

Ethernet Cord or Wifi dongle

External Hard drive or USB Drive


Raspberry Pi Case

USB Keyboard

USB Mouse

Note: It is highly likely that the USB ports on the Raspberry Pi will be unable to power an external hard drive so you may need to invest in a powered USB hub.


If you’re a visual person and would like to see our video on how to put this tutorial together, then check out the video below.

It will take you through everything you need to know get your Raspberry Pi Owncloud server up and running.

Setting up The Raspberry Pi Owncloud Server

Firstly, you will need to have a Raspberry Pi with Raspbian installed. If you haven’t installed Raspbian, then check out our guide on how to install Raspbian via NOOBS (New Out of the Box Software).

There are quite a few ways you’re able to install Owncloud onto your Raspberry Pi. In this particular tutorial, we’re going to be downloading a web server (Nginx) and Owncloud.

1. Firstly, in either The Pi’s command line or via SSH we will need to update the Raspberry Pi and its packages, do this by entering:

sudo apt-get update
sudo apt-get upgrade

2. Now we need to open up the Raspi Config Tool to change a few settings.

sudo raspi-config

3. In here we will need to change a few settings.

  • Change Locale to en_US.UTF8 in internationalization options -> change local.
  • Change memory split to 16m in Advanced options -> Memory split.
  • Change overclock to medium.

4. Add the www-data user to the www-data group.

sudo usermod -a -G www-data www-data

These instructions have been updated to work with Raspbian Buster, if you’re on an earlier version then I highly recommend you upgrade to Raspbian Buster before continuing.

You can follow our guide on upgrading from Raspbian Stretch to Buster.

5. Once you are running Raspbian Buster, you can safely continue with this tutorial.

In this step, we will be installing all the packages that we require to run Owncloud. This includes php7.2 and its numerous modules that OwnCloud relies upon.

Run the following command to install everything we need.

sudo apt-get install nginx openssl ssl-cert php7.2-cli php7.2-sqlite3 php7.2-gd php7.2-common php7.2-cgi sqlite3 php-pear curl libapr1 libtool curl libcurl4-openssl-dev php7.2-xml php7.2 php7.2-dev php7.2-curl php7.2-gd php7.2-fpm memcached php-memcache php7.2-zip php7.2-intl php7.2-mbstring varnish

6. Now we need to create an SSL certificate you can do this by running the following command:

sudo openssl req $@ -new -x509 -days 730 -nodes -out /etc/nginx/cert.pem -keyout /etc/nginx/cert.key

Just enter the relevant data for each of the questions it asks you.

7. In addition to the SSL certificate we also need to generate ourselves a custom dhparam file. This file helps ensure that our SSL connections are kept secure, by default this would use a default one that isn’t nearly as secure.

To generate a 4096 byte long DH Param run the following command on your Raspberry Pi. This process will take quite a long time, up to 16 hours. Adding the -dsaparam flag to the command will help speed up the process, but arguably is less secure.

sudo openssl dhparam -out /etc/nginx/dh4096.pem 4096

8. Now we need to chmod the three cert files we just generated.

sudo chmod 600 /etc/nginx/cert.pem
sudo chmod 600 /etc/nginx/cert.key
sudo chmod 600 /etc/nginx/dh4096.pem

9. Let’s clear the server config file since we will be copying and pasting our own version in it.

sudo sh -c "echo '' > /etc/nginx/sites-available/default"

10. Now let’s configure the web server configuration so that it runs Owncloud correctly.

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

11. Now simply copy and paste the following code into the file.

  upstream php-handler {
      server unix:/var/run/php/php7.2-fpm.sock;

  server {
      listen 80;
      server_name _;

      #Allow letsencrypt through
      location /.well-known/acme-challenge/ {
          root /var/www/owncloud;

      # enforce https
      location / {
          return 301 https://$host$request_uri;
  server {
      listen 443 ssl http2;
      server_name _;
      ssl_certificate /etc/nginx/cert.pem;
      ssl_certificate_key /etc/nginx/cert.key;

      ssl_session_timeout 5m;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:AES256+EDH';
      ssl_dhparam /etc/nginx/dh4096.pem;
      ssl_prefer_server_ciphers on;
      keepalive_timeout    70;
      ssl_stapling on;
      ssl_stapling_verify on;
      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;
      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;
      # set max upload size
      client_max_body_size 512M;
      fastcgi_buffers 8 4K;
      fastcgi_ignore_headers X-Accel-Buffering;
      gzip 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 SCRIPT_NAME $fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
          fastcgi_param HTTPS on;
          fastcgi_param modHeadersAvailable true;
          fastcgi_param front_controller_active true;
          fastcgi_read_timeout 180;
          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;
      location ~ \.(?:css|js)$ {
          try_files $uri /index.php$uri$is_args$args;
          add_header Cache-Control "max-age=15778463";
          # 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;
          access_log off;
      location ~ \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg|map)$ {
          add_header Cache-Control "public, max-age=7200";
          try_files $uri /index.php$uri$is_args$args;
          access_log off;

12. Now simply save and exit.

13. Now that is done there is a few more configurations we will need to update, first open up the PHP config file by entering.

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

14. In this file, we want to find and update the following lines. (Ctrl + w allows you to search)

upload_max_filesize = 2000M
post_max_size = 2000M

15. Once done, save and then exit. Now we also need to edit the dphys-swapfile. To do this open up the file by entering:

sudo nano /etc/dphys-swapfile

16. Now update the conf_swapsize line to the following:


17. Restart the Pi by entering:

sudo reboot

18. Once the Pi has restarted, you will need to install Owncloud onto the Raspberry Pi. Do this by entering the following commands:

sudo mkdir -p /var/www/owncloud
cd /var/www/
curl https://download.owncloud.org/community/owncloud-10.2.1.tar.bz2 | sudo tar -jxv
sudo chown -R www-data:www-data /var/www

19. Now we need to open up the .user.ini file to enforce some of the changes we made earlier in the tutorial

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

20. In here update the following values so they are 2000M:




21. Now that is done we should be able to connect to Owncloud at your PI’s IP address.

Before you set up the admin account, you might want to mount an external drive, so you have lots of disk space for your Raspberry Pi Owncloud Server. Just follow the instructions in the next section.

Mounting & Setting up a drive

Setting up an external drive while should be relatively straightforward but sometimes things don’t work as correctly as they should.

These instructions are for mounting and allowing Owncloud to store files onto an external hard drive.

1. Firstly if you have an NTFS drive we will need to install an NTFS package by entering the following:

sudo apt-get install ntfs-3g

2. Now let’s make a directory we can mount.

sudo mkdir /media/ownclouddrive

3. Now we need to get the GID, UID, and the UUID as we will need to use these soon. Enter the following command for the GID:

id -g www-data

4. Now for the UID enter the following command:

id -u www-data

5. Also if we get the UUID of the hard drive, the Pi will remember this drive even if you plug it into a different USB port.

ls -l /dev/disk/by-uuid

UUID Hard Drive

Copy the light blue letters and numbers of the last entry (Should have something like -> ../../sda1 at the end of it).

6. Now let’s add your drive into the fstab file so that it will boot with the correct permissions.

sudo nano /etc/fstab

7. Now add the following line to the bottom of the file, updating UID, GUID and the UUID with the values we got above. (The following should all be on a single line)

UUID=DC72-0315 /media/ownclouddrive auto nofail,uid=33,gid=33,umask=0027,dmask=0027,noatime 0 0

8. Reboot the Raspberry Pi, and the drives should automatically be mounted. If they are mounted, we’re all good to go.

Note: If you get an error stating the Pi is in emergency mode at boot up then this likely means a problem with the fstab entry. Just edit the fstab file (sudo nano /etc/fstab) and remove the added line or look for a mistake and fix it.

Basic First Setup

I will briefly go through the basics of setting up Owncloud Raspberry Pi here. If you want more information I highly recommend checkout out the manuals on their website, you can find them at the Owncloud manual site here.

1. In your browser enter your Pi’s IP address in my case it is

2. Once you go to the IP you’re like to get a certificate error, simply add this to your exception list as it will be safe to proceed.

3. When you first open up ownCloud you should be presented with a simple setup screen and no errors.

4. Enter your desired username and password.

5. Click on storage & database and enter your external drive /media/ownclouddrive (Skip this step if you didn’t setup an external drive).

6. Click finish setup.

Owncloud Signup

If you ever need to update and you find the internal updater is not working this likely means, you will need to do it manually. You can find a detailed process on how to update over at owncloud’s update manual page.

Port Forwarding & External Access

If you want to have access to your cloud drive outside your local network, then you will need to setup port forwarding and make a few changes to our config files.

Firstly, we need to go back to the default file and change the server_name values (There is 2 of them). Update these to your external IP address. You can get your IP at what is my IP.

If you have a dynamic IP you may want to set up a dynamic DNS and use that as your address. You can find information on this in my guide to port forwarding.

Enter the following to bring up our default server file:

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

Once you have updated the IP’s in the server file, you will need to add the external IP to your trusted IP list and make sure Owncloud doesn’t overwrite it. To do this open up the Owncloud config file and enter:

sudo nano /var/www/owncloud/config/config.php

In here add a new item to the trusted domains array (This will be your external IP address). Your new entry should look something like this (x are just placeholders).

1 => 'xxx.xxx.xxx.xxx',

Finally update the URL of the overwrite.cli.url line to your IP Address. It should look something like this.

'overwrite.cli.url' => 'https://xxx.xxx.xxx.xxx',

Below is an example of the completed config.txt file.

External IP Change Example

Once done, restart the Nginx service by entering the following:

sudo service nginx restart

Be sure to check out my guide on port forwarding and use the following port 443 for internal, and I recommended a random port for the external port. Make sure when setting up the external port that it isn’t already reserved for a specific program.

When connecting to the Owncloud server externally, you will need to make sure you use https otherwise you will get an invalid request in your browser.

Setting up port forwarding is super easy to do and allows you to have access to your personal cloud on the go. Also after you have done this, you can still connect via your local IP as well.

I hope this tutorial has helped you make your very own Raspberry Pi OwnCloud. If you have any troubles, want to leave feedback or if I have missed anything feel free to drop us a comment below.


  1. John B on

    World backup day, so I am giving this a go. 🙂

    Will it really take 16 HOURS to get the openpssl key to generate? 🙁 Guess I am waiting till tomorrow now. lol

    1. Emmet on

      Hi John,

      Typically generating the keys is a lot faster then that.


  2. Ivo Lourenco on


    I’m trying to set up a Pi 2 with owncloud and I do need external access to it. At minute 4:58 the IP added and the 9000 port is a standard ip or should we add the PI ip instead? Also these step is not on the list only on the movie any specific reason?



    1. Emmet on

      Hi Ivo,

      The video is a little out of date and needs redoing.

      Please try following the written guide.


  3. kony on

    hi there – is this owncloud setup valid also for iOS / Mac users? reason to ask is cause i read about NTFS format …

    1. Emmet on

      Hi Kony,

      This should work fine for people using iOS and Mac. The mention of NTFS is just for those mounting external drives that are formatted in that format.


  4. Ronald Basil on

    Will this work on Raspberry pi 3?

    1. Gus on

      Yes, it will work on almost every Raspberry Pi. Do make sure you’re running the latest Raspbian (Buster).

    2. Eberhard Stephan on

      I did everything as described without SSL
      When finish and enter my IP – nothing happens, no owncloud mask appear

    3. Gus on

      You must set up SSL; otherwise, it won’t work.

      The NGINX file is set up to enforce HTTPS.

Leave a Reply

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