DEV Community

Cover image for How I turned my Raspberry Pi into a private cloud server
Rossano D'Angelo
Rossano D'Angelo

Posted on • Updated on • Originally published at

How I turned my Raspberry Pi into a private cloud server

I do like traveling and taking pictures, even if most of them are really pointless 😄

Once back at home, I'm used to moving all the pictures I took on my laptop and, after a selection, I upload the best pictures to the cloud. I like using Google Photos. But there's a problem.
Since I use the Free plan, I don't upload pictures with the original size. It means they lose quality.

That's why I decided to buy an HDD and to upload my pictures on it, not using Google Photos anymore.

Damn, I miss it.

I don't have access to my pictures anymore when I'm not around my HDD. Showing and/or sharing them's impossible.

That's when the idea of the private cloud started floating in my mind.

You may say buying an HDD wasn't a cost? Pay for Google Photos then! You're right but nothing is better than the satisfaction you get by something built by yourself. I like doing this kind of thing so I made my private Google Photos! It's a fully private cloud service actually - documents, video, images, emails, etc - but I use it only for my pictures.


Raspberry Pi and Micro SD

To set up my photo server I used a Raspberry Pi 4 (4 GB RAM) with 16 GB Micro SD and an external USB drive to use as storage.

Alt Text

Docker and Docker Compose 🐳

I also installed Docker on my Raspberry Pi: I didn't want to re-install everything in case something goes wrong.

Once installed, I did make sure the user pi can use it (I don't want to use sudo every time)

curl -fsSl -o
sudo sh
sudo usermod -aG docker pi
Enter fullscreen mode Exit fullscreen mode

I installed Docker Compose too - kudos to Roahn for the help

sudo apt-get install -y libffi-dev libssl-dev python3 python3-pip
sudo apt-get remove python-configparser
sudo pip3 install docker-compose
Enter fullscreen mode Exit fullscreen mode

Since the architecture of the Raspberry Pi is different than the classic Ubuntu's, I needed to install Docker Compose via pip3.

The infrastructure

To set up Nextcloud I used a yml file docker-compose.yml

version: '2'


    image: nextcloud
      - 8080:80
      - nextcloud:/var/www/html
    restart: always
Enter fullscreen mode Exit fullscreen mode

This yml file contains the infrastructure I want to build. This way to build infrastructures is called IaC, Infrastructure as Code: you declare the services you want to run and how they have to communicate with each other, and Docker Compose does the job for you.

In this case, I declared I want to use the nextcloud image to run an app on the port 8080 (host - I reach it on this port) and to redirect to the container "internal" port 80. Learn here how to expose ports. I also specified the path for the volume - where the container stores data (my photos).

Up and running

Now that the docker-compose.yml is ready, it's time to launch 🚀

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

The option -d stands for detached mode, containers run in the background.

To check if the container we declared in the yml file is up and running, run

docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
a1d31d5ee1d6        nextcloud           "/ apac…"   About an hour ago   Up About a minute>80/tcp   nextcloud_app_1
Enter fullscreen mode Exit fullscreen mode

I can do something similar with Docker Compose. Within the root folder that contains the docker-componse.yml file, run

docker-compose ps

     Name                    Command               State          Ports
nextcloud_app_1   / apache2-for ...   Up>80/tcp
Enter fullscreen mode Exit fullscreen mode

The difference between docker ps and docker-compose ps is that docker ps lists all running containers in the docker engine while docker-compose ps lists containers related to images declared in the docker-compose.yml file.

If you're on your Raspberry, go to http://localhost:8080/. If you're connected to the Raspberry Pi via SSH instead, open a browser and go to http://[HOSTNAME]:8080/.

If you don't know the IP address of your Raspberry Pi, just run

hostname -I 2a00:23c7:8e8b:1201:f35:95a7:4c14:6ed

So, in my case, my Raspberry's IP address is It shouldn't change until you disconnect the Raspberry from the Internet > or you restart the router.

Here's a good article about how to connect via SSH to your Raspberry Pi.

Ta-da! Nextcloud is up and running, ready to use! 🎉 🎉 🎉

Setup the administrator account and do not change the storage and database settings. It's not the time for that yet.

Let's take a closer look

Sweet, Nextcloud is working and is reachable only within my WiFi connection. I can upload photos from my smartphone too!

Let's take a look at the container now. Run

docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
a1d31d5ee1d6        nextcloud           "/ apac…"   2 hours ago         Up 37 minutes>80/tcp   nextcloud_app_1
Enter fullscreen mode Exit fullscreen mode

and copy the container id. Now run

docker exec -it <CONTAINER_ID> bash
Enter fullscreen mode Exit fullscreen mode

to enter the container itself, in interactive mode -it using the bash.

What you will see is something like

Enter fullscreen mode Exit fullscreen mode

You entered the container as root and it's waiting for a command. So, let's discover where the container will store my pictures. The volume path is /var/www/html. In this container you have Apache running, that's where /var/www comes from.

To list all the files run ls -l. To discover where Nextcloud stores my data, let's open the config.php file to sneak a peek.

more config/config.php

$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' =>
  array (
    0 =>
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    1 =>
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
  'instanceid' => 'ocagdfr8srkl',
  'passwordsalt' => 'Mw2SMCooFW1CAUuyzK7TV5Uh7cbGge',
  'secret' => 'KpK7QWHnzWs/NgdkQSATn4EogqLLrIFLXO0mu0cShbG6zJVQ',
  'trusted_domains' =>
  array (
    0 => '',
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'sqlite3',
  'version' => '',
  'overwrite.cli.url' => '',
  'installed' => true,
Enter fullscreen mode Exit fullscreen mode

datadirectory, got it!


cd data/<NEXTCLOUD_USERNAME>/files/
ls -l
Enter fullscreen mode Exit fullscreen mode

Here they are, files and folders! Photos are stored into Photos folder.

Alt Text

What's next

My private cloud is ready and now I can safely store my HD pictures on it! Sky is the limit!

Not yet 🚫 I do have two limits:

  1. I can't upload my photos if I'm not a home
  2. I can't upload all the photos I want because of the limited storage capacity of the Micro SD

To overcome these problems are enough a domain and an external hard disk 🔜

Top comments (15)

alxtrnr profile image
Alex Turner • Edited

Good stuff. I have something similar. Using . Booting up and running the install from a USB stick. I have found that much more reliable than an SD card. Data directory and snapshot backups are both on dedicated external drives powered by external source. Remote access via a dns address. Just got myself a pijuice power hat for an emergency UPS should it be needed. Here it is in a shoe box... Here it is in a shoe box...

rossanodan profile image
Rossano D'Angelo

This is awesome!! Do you have any hints for me about using an external hard drive as storage for Nextcloud? I tried but I had errors abour writing permissions on the external disk. I used a HDD 2 TB Toshiba.

alxtrnr profile image
Alex Turner • Edited

Cheers! In order for me to be able to use an external USB drive, the USB drive must not be formatted as NTFS/FAT as these do not support the user/permission system. For me the drives needs to be formatted to BTRFS. That may be worth checking. Big drives (bigger than 2 TB) also need to be partitioned with GPT.

gervais_b profile image
Blaise Gervais 🇧🇪

Well done. Please note that 8080:80 in the "ports" section of you docker-compose does not mean "use 80 if 8080 is busy". It means "expose 8080 and redirect to 80 on the container".

rossanodan profile image
Rossano D'Angelo

Ooooh thanks for reporting this!! I'll edit it right now. Thank you! :)

cristiannebunu profile image
Cristian N

Pretty cool. I'm sure you thought about it, but for everyone else, on an RP4 you have USB 3 and that means you can hook up an SSD or a any other kind of external drive and make it run on that, and when you are no longer limited by the sd card, imagine the possibilities :)

rossanodan profile image
Rossano D'Angelo

There you are, that's what I'm try to do ;)

brunooliveira profile image
Bruno Oliveira

Awesome awesome stuff!!! Really nice! Similar to the app related to dams I did and wrote about here, I believe these projects are the best to learn

rossanodan profile image
Rossano D'Angelo

I agree. It gave me another chance to go deeper on Docker and Docker Compose. Now, as I said, I need to overcome the limitations.. Let's see if I find good advices here ;)

etescartz profile image
etescartz • Edited

If I may suggest adding a Redis container to your setup, for Nextcloud caching instead of the default apcu. I'm also looking into adding a Photoprism container since it can import directly from Nextcloud, or so I keep reading.
Also I found Docker compose to be cumbersome so I started using Ansible since it has it's own "docker_module". That way I deploy my own cloud infra with really granular parameters and modulatity, and also avoiding docker-compose's "deploy my containers as a group" mentality.
The beauty of it all is that if one RaspberryPi's power isn't enough for this setup you can always buy another one and split containers among them as you see fit.

Thread Thread
rossanodan profile image
Rossano D'Angelo

I followed what you said but, I want to be honest, I'm not able to implement such architecture by my own. I'm only at the beginning! :)
I'll keep your comment in mind tho, it'll be useful for my next steps into docker and docker-compose. I like working with it!! :)

moeletjis profile image
Moeletji Semenya

Super creative. Great work

rossanodan profile image
Rossano D'Angelo

Thank you Moeletji! You made my day with these comments. Really glad you enjoyed it :)

musale profile image
Musale Martin • Edited

I like this. Running docker really excited me I can't wait to try it out.

jdsaraiva profile image

Thanks for sharing Rossano, I am now waiting for the second part of the article.