Setting Up Nextcloud on a Raspberry Pi 5
DISCLAIMER: I wrote these instructions some months after I set up my Pi, from my personal notes and my memory, which can be faulty. They should be mostly complete, but it’s possible I something is left out unintentionally.
Setting up NextCloud on a Raspberry Pi 5
I recently moved to a new city, and where I now live I have symmetrical gigabit fiber to my house. 😄 This should allow me to host some of my own cloud services instead of relying on a VPS somewhere, and save a little bit of money on hosting fees. Since I’m the only person that uses my nextcloud instance, it shouldn’t require a lot of hardware to host, and I have an extra Raspberry Pi 5 to play with, so let’s try hosting nextcloud on a Pi 5! Here is my setup.
Raspberry Pi 5 Specs
- 8 GB RAM
- 4 core ARM Cortex-A76
- Active CPU cooler
- Raspberry Pi OS Lite (Debian 12 bookworm)
- 256 GB microSD card
- I got one specifically certified for high data rates, typically used for 4k video recording with drones. ProGrade, V60, UHS-II U3, C10 rating.
- Samsung 2 TB USB 3.1 external SSD
Raspberry Pi OS Setup
I used the Raspberry Pi Imager tool to write the OS image to my SD card. Before committing the image to disk, I made sure to set up a user account and password so I could get in after installing! This is a headless setup, so I needed to be able to access the pi via SSH after install.
Post-install OS setup tasks
First make sure everything is up-to-date before continuing.
sudo apt update
sudo apt upgrade
sudo shutdown -r now
Great!
Once that’s complete, format the external SSD with ext4 and mount it. I created a directory in the root filesystem called “nextcloud-data” and mounted the SSD there.
Format and mount the external SSD
Make sure you know where in the filesystem the SSD gets attached. You can unplug the SSD and plug it back in, then run dmesg to see the kernel logs. Near the bottom will be something like
[ 2.827039] sd 0:0:0:0: [sda] Optimal transfer size 33553920 bytes
[ 2.847962] sda: sda1
[ 2.850651] sd 0:0:0:0: [sda] Attached SCSI disk
For me, the SSD is attached at /dev/sda. For you, it might be somewhere else, so pay attention to make sure you use the right location when formatting and mounting the device next.
fdisk and mkfs.ext4
Remove whatever partition table is on the external SSD
sudo fdisk /dev/sda
Type ‘o’ to create a new MBR partition table. ’n’ to create a new partition. Accept the default values for start and end of the partition to take up the whole volume. Then ‘w’ to write the changes and exit
Create a new ext4 filesystem on the new partition you just created, and mount it to /nextcloud-data:
sudo mkfs.ext4 /dev/sda1
sudo mkdir /nextcloud-data
sudo mount /dev/sda1 /nextcloud-data
/etc/fstab
We want to make sure the external SSD gets mounted at every boot, so add an entry to /etc/fstab
We’ll refer to the partition by it’s PARTUUID, which is more robust than just using its device node name (e.g. /dev/sda1, or /dev/mmcblk0p2, etc). Get the PARTUUID with the lsblk command:
sudo lsblk -o +PARTUUID
There will be several entries, but we’re interested in the one associated with the partition we just made. For example, this is my output:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS PARTUUID
sda 8:0 0 1.8T 0 disk
└─sda1 8:1 0 1.8T 0 part /nextcloud-data 50679bd6-01
Now add an entry to /etc/fstab to mount it on boot. This is what my /etc/fstab looks like:
proc /proc proc defaults 0 0
PARTUUID=a678d940-01 /boot/firmware vfat defaults 0 2
PARTUUID=a678d940-02 / ext4 defaults,noatime 0 1
# External USB drive
PARTUUID=50679bd6-01 /nextcloud-data ext4 defaults,noatime 0 0
Then I more-or-less followed the instructions to set up NextCloud on Ubuntu here
Ubuntu is based off Debian, so the instructions should map pretty well to the Pi.
Install Apache2 web server, MySQL database, and some php libraries
sudo apt install apache2 mariadb-server libapache2-mod-php php-gd php-mysql php-curl php-mbstring php-intl php-gmp php-bcmath php-xml php-imagick php-zip
Set up MySQL
Really it’s MariaDB, not MySQL, but they can be treated the same for our purposes here. For the following, change ‘username’ to the username you want to use. It does not have to be your Linux username, it could be anything. Something like ’nextclouduser’ could work. Just remember what it is when you log into nextcloud for the first time and use it to connect to the database.
Also change ‘password’ to the actual database password you want to use. Make it good, and it’s probably a good idea to make it something other than your Linux username/password.
Keep ’localhost’ as ’localhost’, since we are installing the database on the pi.
sudo mysql
CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON nextcloud.* TO 'username'@'localhost';
FLUSH PRIVILEGES;
Then exit:
quit;
Download Nextcloud and Install
I grabbed latest.zip and verified the download:
wget https://download.nextcloud.com/server/releases/latest.zip
wget https://download.nextcloud.com/server/releases/latest.zip.md5
md5sum -c latest.zip.md5
Then extract and copy to the Apache document root we want. In my case here, it’s /var/www/nextcloud
. Be careful about the trailing slashes, if you do exactly as written below things’ll work out consistently with these instructions in this blog post. If not, you might have a /var/www/nextcloud/nextcloud/ directory. If that’s the case, it’s fine, but adjust the rest of the instructions accordingly:
sudo apt install unzip
unzip latest.zip
cp -r nextcloud /var/www/
chown -R www-data:www-data /var/www/nextcloud
chown -R www-data:www-data /nextcloud-data
Setup Apache
Enable modules:
a2enmod rewrite
a2enmod headers
a2enmod env
a2enmod dir
a2enmod mime
a2enmod ssl
Configure /etc/apache2/sites-available/nextcloud.conf.
Replace YOURSERVERNAME with an actual domain you own. e.g. “mycloud.mydomain.net” or something.
<VirtualHost *:80>
DocumentRoot "/var/www/nextcloud"
ServerName <YOURSERVERNAME>
ErrorLog ${APACHE_LOG_DIR}/nextcloud.error
CustomLog ${APACHE_LOG_DIR}/nextcloud.access combined
<Directory /var/www/nextcloud/>
Require all granted
Options FollowSymlinks MultiViews
AllowOverride All
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
</VirtualHost>
Enable the site
a2ensite nextcloud.conf
Configure SSL with Lets Encrypt and Certbot
Install certbot
sudo apt install certbot python3-certbot-apache
Get some certificates. replace <YOUREMAILADDRESS> and <YOURSERVERNAME> with actual real values. e.g. mycloud.mydomain.net
certbot --apache --agree-tos --redirect --staple-ocsp --email <YOUREMAILADDRESS> -d <YOURSERVERNAME>
Firewall
Enable access to port 22, 443. Block everything else.
# enable IPV6 filtering
add IPV6=yes /etc/default/ufw
# Set default policy of reject incoming
ufw default deny incoming
ufw default allow outgoing
# Allow services
ufw allow ssh
ufw allow https
# rate limit ssh
ufw limit ssh
# start
ufw enable
Restart Apache
systemctl restart apache2
Configure Nextcloud
Go to your new NextCloud instance! Open a browser to the server address (e.g. mycloud.mydomain.net in the examples above)
Here you will set the data directory to /nextcloud-data to use your SSD for file storage, and add the database credentials you used when you set up mysql above.
More configuration of config.php
After running through the graphical installer through the web browser, I configured /var/www/nextcloud/config/config.php by adding (for pretty URLs):
'htaccess.RewriteBase' => '/',
beneath overwrite.cli.url
Run occ maintenance to make that effective (from /var/www/nextcloud/ directory):
sudo -u www-data php occ maintenance:update:htaccess
Update memory limits for php: Change memory_limit from 128M to 512M in /etc/php/8.2/apache2/php.ini
Extra security and performance enhancements
Redis
apt install php-apcu redis-server php-redis php-bz2
First, open the Redis configuration file at /etc/redis/redis.conf
sudo vim /etc/redis/redis.conf
Now, find and change:
port 6379 to port 0
Then uncomment:
#unixsocket /run/redis/redis-server.sock to unixsocket /run/redis/redis-server.sock #unixsocketperm 700 changing permissions to 770 at the same time: unixsocketperm 770
Save and quit, then add the Apache user www-data to the redis group:
sudo usermod -a -G redis www-data
Finally, restart Apache with:
sudo service apache2 restart
And start Redis server with:
sudo service redis-server start
With Redis configured, we can add the caching configuration to the Nextcloud config file:
Open and edit /var/www/nextcloud/config/config.php to add
'filelocking.enabled' => 'true',
'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array (
'host' => '/run/redis/redis-server.sock',
'port' => 0,
'timeout' => 0.0,
),
You can work through the findings in “Security & setup warnings” under Administration Settings at this point to address any findings there you might want to address.
Have fun!
Reach out to me if there’s something here that didn’t work, and I’d be happy to adjust the instructions.
Have fun with your NextCloud!