How to Build a Raspberry Pi Personal Cloud Server with NextCloudThis guide will show you how to create a Raspberry Pi Personal Cloud Server covering flashing Raspbian and securing your Pi server with SSL.

Now that you have your new Raspberry Pi, you may be wondering how to use it. This guide will show you how to flash Raspbian, boot into your Raspberry Pi, and configure and build a personal Raspberry Pi personal cloud server secured with SSL from Let's Encrypt.
Why a Personal Cloud Server?
Cloud servers such as Google Drive, Apple iCloud, Microsoft OneDrive, and Dropbox are good. Still, their free space isn't very much these days (~5GB), and additional storage can be very expensive.
Most of the top cloud storage providers have had some form of security breach [1], [2] or problems with their platform resulting in data loss [1].

I also wanted a small public-facing home web server for a few small personal applications, so I thought, "Why don't I put this Raspberry Pi to good use?" The Raspberry Pi 3 Model B has impressive specs for a tiny computer; it should be more than enough to run a cloud storage server and a few web applications for a single user. As the Raspberry Pi has a very low energy footprint, using it as an always-on web server makes it an ideal choice.
In this guide I'll cover installing Raspbian on the Raspberry Pi, setting up and configuring a web server, network security, nextCloud server and using Let's Encrypt X509 certificates for SSL and HTTPS.
You Will Need
- Raspberry Pi (I'm using a Pi 3 Model B, other models may work)
- Ascociated peripherals (monitor, keyboard, cables, etc)
- Micro SD card 8GB+
- 32GB USB Thumb Drive / Flash Drive (for storing files)
Downloading and Flashing Raspbian
Raspbian is the official OS for the Raspberry Pi. You can install it with NOOBS or download the image and flash it to an SD card yourself. Since the Raspberry Pi has fixed hardware, you can flash OS images to the SD card like you flash a ROM to an Android smartphone.
For Raspberry Pi, the flashing tool of choice is Etcher. This graphical SD card writing tool works on Mac OS, Linux and Windows and is the easiest option for most users. Download the Raspbian image from the link above, Etcher from here, install and run Etcher. It allows you to select the image to flash, the destination SD card and a button to start the process. Simples.

Once complete, insert the micro SD card into the Raspberry Pi and turn the power on. The Pi will then boot up into Raspbian.
Getting Started in Raspbian
Raspbian is based on Debian, so if you've used Ubuntu or Linux Mint, then the system should be very familiar. If you've not used Linux before, I recommend that you read my tutorial series on to get started with Linux.
The default username and password for Raspbian are:
- Username: pi
- Password: raspberry
Once you are logged in, the first things to do are to change the default username and password and run system updates.
To change a password in Linux, use the passwd
command. Raspbian, you can also use sudo raspi-config
to enter the configuration screens. Selecting the password option will allow you to change your password.
If you wish to rename the default pi
username, the process is simple but involves a few steps.
Firstly, we need to create a new user.
sudo adduser username
Follow the prompts to set the new user's information. It is fine to accept the default to leave all of this information blank.
Use the usermod command to add the user to the sudo group.
sudo usermod -aG sudo username
Now log out of the Pi user and log in with the new username.
Now, enter these commands into the terminal. The first command renames the user; the second sets the user's home directory. You may need to copy any files from the old home directory to the new if any were created.
sudo usermod -l techman pi sudo usermod -d /home/techman -m techman
You can delete the new user now, as we won't need it again.
sudo userdel username
Running System Updates in Linux
Running system updates is performed by issuing the following command in the terminal.
sudo apt-get update && sudo apt-get upgrade
The next thing to do is set up SSH so I can access the Pi from my desktop. This is easy enough to do as SSH is installed on the Raspberry Pi; it's just turned off by default. To enable SSH on the Raspberry Pi, enter the raspi-config
tool, select Interfacing Options and select SSH.
The default hostname for a Raspberry Pi is raspberrypi
. Very imaginative. If you would like to change it, you can also do that from the raspi-config
screen. In the remainder of this tutorial, replace Raspberry with whatever you choose.
Setting a Fixed IP Address
It is often handy to have servers with a fixed IP address; that way, it is easier to remote into them and to set up firewall rules. In my case, later on, I will need to forward the HTTP and HTTPS ports to the Pi, and my router requires a static IP address for this.
Edit the DHCP daemon config.
sudo pico /etc/dhcpcd.conf
And at the bottom, add eth0 (Ethernet) or wlan0 (Wireless adaptor) to these lines. You should change the IP addresses as provided by your network setup or system administrators.
interface eth0
static ip_address=192.168.1.10/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1
Reboot for the changes to take effect.
Installing Apache and PHP
For your Raspberry Pi to work as a web server, we need to install the Apache web server, PHP for server-side scripting and MySql for databases.
To install Apache and PHP, you must run these commands to start the installation. With the release of Stretch, Debian has removed the obsolete PHP5 package, so we must use the newer PHP 7.
sudo apt-get install apache2 php7.0 php7.0-gd libapache2-mod-php7.0 php7.0-curl
When the installation is complete, you can start Apache with this command.
sudo service apache2 restart
Now, you should be able to access the default web page in a browser on another computer by entering http://raspberrypi.local in your browser's address bar.
For setting up websites in Apache, please refer to the article Apache Administration on Linux
Installing MySQL, MariaDB and Creating Root User
Now, to install MySql. This is also simple: type in these commands.
sudo apt-get install mysql-server python-mysqldb php-mysql
Now for the not-so-simple part. MySQL 5.7 changed the secure model, so MySQL root login now requires sudo-level execution. This means root can no longer be used for web logins via PHP. The simplest and safest solution will be to create a new user and grant the required privileges.
sudo mysql --user=root mysql
Run the following commands, replacing some_pass with the desired password.
CREATE USER 'lonewolf'@'localhost' IDENTIFIED BY 'some_pass';
GRANT ALL PRIVILEGES ON *.* TO 'lonewolf'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
You should be able to log in with this user later in this tutorial.
Linux Network Security
Linux server security isn't complicated. A few applications to install and configure will block 99% of attacks an internet-facing web server can be exposed to. Follow these steps step by step, and you should be fine, but as with everything, there are no guarantees. Please let me know in the comments below if you have any suggestions for adding to this list.
Install Fail2ban
Fail2ban is a daemon that monitors login attempts to a server and blocks suspicious activity as it occurs. It's well-configured out of the box.
sudo apt-get install fail2ban
Install a Firewall
No secure server is complete without a firewall. Linux provides a good firewall called ufw
, which makes firewall management easy. Install it with this command:
sudo apt-get install ufw
We now need to configure it like this.
sudo ufw allow from {your-ip} to any port 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
This will allow all traffic from your IP address (e.g. a desktop used to SSH into the Raspberry Pi) and from any other address; only ports 80 (HTTP) and 443 (HTTP) will be accessible.
That's security on the server sorted. I said it was easy!
When I'm ready to put this Raspberry Pi server live, I'll forward ports 80 and 443 to the Pi IP address on the router. By forwarding these two ports, any attempts to access the Pi on any other port from the internet will be blocked by my router first.
Now is a good time to reboot the Pi so all the new changes can occur.
sudo shutdown -r -t 0
Installing NextCloud
NextCloud is a suite of client-server software for creating and using file hosting services. It is functionally similar to Dropbox, although NextCloud is free and open-source, allowing anyone to install and operate it on a private server.
Installing NextCloud to the Raspberry Pi is quite simple, although it involves more than previous installations.
I'm using the default Apache www directory for this; if you have changed the location, adjust the commands accordingly. Also, note that this is the current version as of writing. You should check the NextCloud website download page for the latest file version.
First, change the directory to the HTML root.
cd /var/www/html
We need to download the NextCloud archive and extract it from this folder. This file was the latest as of the time of writing; please refer to the NextCloud website for the most up-to-date version.
sudo wget https://download.nextcloud.com/server/releases/nextcloud-12.0.3.zip
sudo unzip nextcloud-12.0.3.zip
This will extract all the required files and send them to a new nextcloud directory.
Optional - Store Data Files on External Drive
This part is optional. For me, I'm using an 8GB micro SD card, which doesn't offer much for cloud storage, so to add more space and reduce stress on the micro SD card, I've added a 32GB USB thumb drive to my Pi, which I will use exclusively for storing my files. I've created a data directory in /media, which will be used to mount the drive.
sudo mkdir /media/data
I will then add the USB mount to the automatic fstab file to mount automatically at boot. I've formatted mine as FAT32 since I will be sharing this USB stick with a Windows laptop, and FAT32 is natively supported by both Windows and Linux. I could have used exFat, but eh. Old skool. You can use whatever filesystem you choose here. If you are not connecting the external storage to Windows, EXT4 may be a better option.
First, you must know the uid of your system's www-data
user. This is as easy as typing in:
id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Next, we need to know the block device associated with the USB drive:
sudo fdisk -l
Disk /dev/sda: 29.7 GiB, 31914983424 bytes, 62333952 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0006c0e4
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 62333951 62331904 29.7G c W95 FAT32 (LBA)
Now that we know the block device, we need to know the unique ID to mount the drive. We can find out the UUID by using this command.
sudo blkid /dev/sda1
Change sda1 with the device ID in the previous step. Now that we know these pieces of information, we can proceed to edit the automount entries.
sudo pico /etc/fstab
Now, to mount the drive on boot, add the following line:
UUID="90A9-AEEF" /media/data vfat auto,rw,uid=33,gid=33,umask=0027 0 0
This mounts sda1 to /media/data as a FAT32 partition, automounted, read and write enabled with user and group owner of www-data
and the permissions of 0755. For more information on the fstab permission masks, see this post fstab Permission Masks Explained, and this post for linux file permissions in general.
Now, to mount the drive, run this command. If all is well, you can cd into the data directory and view any files already there, such as a test.txt file written in Windows.
sudo mount -a
Create NextCloud Data Structure
If you choose to store your data externally, as in the previous step, you can skip this; otherwise, if you use the default storage location, you need to run these commands to create the directory and set the permissions.
sudo mkdir -p /var/www/html/nextcloud/data
sudo chown www-data:www-data /var/www/html/nextcloud/data
sudo chmod 750 /var/www/html/nextcloud/data
Setting Permissions for NextCloud and Apache Modules
Now that the data storage is configured, we must set the Linux permissions on the config and app folders so NextCloud can write settings and download apps. We also need to install a few Apache modules if they have not already been installed.
cd /var/www/html/nextcloud/
sudo chown www-data:www-data config apps
NextCloud requires a few Apache modules to be installed. They can be added using this command.
sudo apt-get install php7.0-xml php7.0-zip php7.0-mbstring php-xml
Increasing PHP maximum upload size
The default file upload size is very small by today's standards; it won't even let you upload a photo from the iPhone camera. We need to modify the php.ini file and increase the limit to change this.
sudo pico /etc/php/7.0/apache2/php.ini
Now, we need to find and replace the following two lines.
post_max_size = 8M
upload_max_filesize = 2M
To
post_max_size = 1024M
upload_max_filesize = 1024M
This will allow files of 1GB to be uploaded. Please change that number to whatever you think is the maximum size file you will upload to your NextCloud.
For all these changes to take effect, we need to restart Apache.
sudo service apache2 restart
Setting up Let's Encrypt SSL
For any web server running on the open internet, we must use some form of encryption when communicating. For this, we use an X509 certificate and the HTTPS protocol. Because I will be hosting this on my business connection, I have a static IP address and domain name to use. These are required when using the Let's Encrypt service. You can also use a self-signed certificate but may get security warnings. The data is still encrypted; it's just that your browser cannot verify the server identity with a trusted third party.
Obtaining a certificate from Let's Encrypt
The first thing to do is install the certbot
tool. This will do most of the work for us.
sudo apt-get install python-certbot-apache
Next, we must configure Apache since certbot
will read this file to obtain domain-specific information.
sudo pico /etc/apache2/sites-available/000-default.conf
Add or uncomment the ServerName directive within the Virtual Host block and set it to your domain name. Save and close the file and test the config using this command.
sudo apache2ctl configtest
You should see Syntax OK
if you did the change correctly. Restart Apache, and then we can proceed to obtain the certificate.
sudo certbot --apache
Certbot will read in the Apache config and present a list of domains where we can install the certificate. Hopefully, yours is now on the list, so select it from the menu.
Which names would you like to activate HTTPS for?
-------------------------------------------------------------------------------
1: test.example.com
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and spaces, or leave input blank to select all options shown (Enter 'c' to cancel):
You must provide a valid email address to receive confirmation and security messages. Typically, these are just notices regarding renewing the certificate.
Finally, accept the terms and conditions, and certbot
goes away and does its thing. If you get errors about "Failed authorization procedure." or "The server could not connect to the client to verify the domain", check that your 443 port is forwarded correctly on your router and that the rules are allowed on the firewall (ufw status
).
During the process, there is the option to have all requests redirected to the secure site. I recommend doing this so that everything is sent encrypted. All this does is add an entry to the config, redirecting all non-https traffic to the https equivalent. You can also manually add this to the .htaccess
for the same result.
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteCond %{SERVER_NAME} =test.example.com [NC]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
The final step is to add the domain name to NextClouds trusted domain list, or you will get a message stating that access from an untrusted domain is denied.
sudo pico /var/www/html/nextcloud/config/config.php
Locate the trusted domains and add a new line.
'trusted_domains' =>
array (
0 => '192.168.0.2',
1 => 'test.example.com',
),
Installing NextCloud
Now we have everything all set up and ready to go. You should be able to use your internet browser to navigate to the domain name specified in the Apache config and access the NextCloud welcome screen.

Enter in details for an admin user to create, change the storage location if you are using external storage, or leave the default if not, and specify the details for the database connection.
It will likely take a little while when the process is complete. You should see the screen below.

Fin!
With some luck, you should now have a secure Raspberry Pi web server with NextCloud personal cloud storage configured!