NextCloud
More Raspberry Pi Projects
Project 1 — Personal Cloud with Nextcloud
What is Nextcloud?
Nextcloud is a self-hosted cloud platform — think Google Drive, Google Photos, Google Calendar, and Google Contacts, all rolled into one, running entirely on your own Raspberry Pi. Your files never leave your home network unless you explicitly share them, and there are no storage limits beyond your hard drive.
It replaces a surprising number of cloud subscriptions:
What You Will Need
Step 1 — Install Required PHP Extensions
Nextcloud requires several PHP modules beyond the basic set installed in Course 1. Install them all at once:
pi@raspberrypi:~$ sudo apt install -y \ php-gd php-json php-curl php-mbstring php-intl \ php-imagick php-xml php-zip php-bcmath php-gmp \ php-apcu php-redis php-memcached \ libapache2-mod-php php-mysql pi@raspberrypi:~$ sudo systemctl restart apache2
Verify the key modules are loaded:
pi@raspberrypi:~$ php -m | grep -E "gd|imagick|apcu|redis" apcu gd imagick redis
Step 2 — Create the Nextcloud Database
pi@raspberrypi:~$ sudo mysql -u root -p MariaDB [(none)]> CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; MariaDB [(none)]> CREATE USER 'nextclouduser'@'localhost' IDENTIFIED BY 'StrongPassword123!'; MariaDB [(none)]> GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextclouduser'@'localhost'; MariaDB [(none)]> FLUSH PRIVILEGES; MariaDB [(none)]> EXIT;
CHARACTER SET utf8mb4 is important — Nextcloud stores emoji and international characters in filenames, and the default MySQL utf8 charset doesn't support 4-byte Unicode characters. Using utf8mb4 from the start avoids a painful migration later.
Step 3 — Download and Install Nextcloud
Download the latest Nextcloud release from nextcloud.com. Always get the current version from the official site rather than apt — the apt version is often many releases out of date:
pi@raspberrypi:~$ cd /tmp pi@raspberrypi:/tmp$ wget https://download.nextcloud.com/server/releases/latest.zip pi@raspberrypi:/tmp$ unzip latest.zip pi@raspberrypi:/tmp$ sudo mv nextcloud /var/www/nextcloud pi@raspberrypi:/tmp$ sudo chown -R www-data:www-data /var/www/nextcloud pi@raspberrypi:/tmp$ sudo chmod -R 755 /var/www/nextcloud
Set up a data directory on the external drive
Store your actual files on the external SSD rather than the system SD card:
pi@raspberrypi:~$ sudo mkdir -p /media/mediadrive/nextcloud-data pi@raspberrypi:~$ sudo chown www-data:www-data /media/mediadrive/nextcloud-data pi@raspberrypi:~$ sudo chmod 750 /media/mediadrive/nextcloud-data
Step 4 — Configure Apache
Create a virtual host for Nextcloud:
pi@raspberrypi:~$ sudo nano /etc/apache2/sites-available/nextcloud.conf
<VirtualHost *:80> ServerName cloud.yourdomain.com DocumentRoot /var/www/nextcloud Redirect permanent / https://cloud.yourdomain.com/ </VirtualHost> <VirtualHost *:443> ServerName cloud.yourdomain.com DocumentRoot /var/www/nextcloud SSLEngine on SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem <Directory /var/www/nextcloud/> Require all granted AllowOverride All Options FollowSymLinks MultiViews <IfModule mod_dav.c> Dav off </IfModule> </Directory> # Security headers recommended by Nextcloud Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" Header always set X-Content-Type-Options "nosniff" Header always set X-Frame-Options "SAMEORIGIN" Header always set X-XSS-Protection "1; mode=block" Header always set Referrer-Policy "no-referrer" ErrorLog ${APACHE_LOG_DIR}/nextcloud-error.log CustomLog ${APACHE_LOG_DIR}/nextcloud-access.log combined </VirtualHost>
Enable the site and required Apache modules:
pi@raspberrypi:~$ sudo a2ensite nextcloud.conf pi@raspberrypi:~$ sudo a2enmod rewrite headers env dir mime ssl pi@raspberrypi:~$ sudo systemctl reload apache2
If you are using a subdomain (cloud.yourdomain.com), add it to your Let's Encrypt certificate:
pi@raspberrypi:~$ sudo certbot --apache -d yourdomain.com -d www.yourdomain.com -d cloud.yourdomain.com
Step 5 — Tune PHP for Nextcloud
Nextcloud's default PHP limits are too low for syncing large files. Edit the PHP configuration:
pi@raspberrypi:~$ sudo nano /etc/php/8.2/apache2/php.ini # Adjust the version number to match yours: php --version
Find and update these values:
memory_limit = 512M # was 128M upload_max_filesize = 10G # was 2M — allows large file uploads post_max_size = 10G # was 8M — must be >= upload_max_filesize max_execution_time = 3600 # was 30 — prevents timeout on large uploads max_input_time = 3600 # was 60 output_buffering = Off # required by Nextcloud opcache.enable = 1 opcache.memory_consumption = 128 opcache.interned_strings_buffer = 8 opcache.max_accelerated_files = 10000 opcache.revalidate_freq = 1 opcache.save_comments = 1
pi@raspberrypi:~$ sudo systemctl restart apache2
Step 6 — Run the Nextcloud Setup Wizard
Open https://cloud.yourdomain.com in a browser. The setup wizard will appear:
- Create an admin account — choose a username and a strong password. This is your Nextcloud administrator login.
- Data folder — change this from the default to your external SSD path:
/media/mediadrive/nextcloud-data - Database — select MySQL/MariaDB (not SQLite — SQLite is only suitable for testing). Enter:
- Database user:
nextclouduser - Database password: your password from Step 2
- Database name:
nextcloud - Database host:
localhost
- Database user:
- Install recommended apps — tick the box to install Calendar, Contacts, and Talk. You can add or remove apps later.
- Click Install and wait — first setup takes 2–5 minutes.
Step 7 — Set Up the Background Job (Cron)
Nextcloud runs maintenance tasks (sending notifications, cleaning the database, updating search indices) via a background job. The recommended method is a system cron job rather than AJAX:
pi@raspberrypi:~$ sudo crontab -u www-data -e
Add this line:
*/5 * * * * php -f /var/www/nextcloud/cron.php
Then tell Nextcloud to use cron instead of AJAX. In the Nextcloud admin panel go to Administration Settings → Basic Settings and change Background jobs to Cron.
Step 8 — Fix Security & Settings Warnings
After logging in, go to Administration Settings → Overview. Nextcloud performs a self-check and will flag any issues. The most common ones on a fresh Pi install:
Add trusted domain
If you see "You are accessing the server from an untrusted domain", edit the config file:
pi@raspberrypi:~$ sudo nano /var/www/nextcloud/config/config.php
'trusted_domains' => array ( 0 => 'cloud.yourdomain.com', 1 => '192.168.1.xx', # optional: allow local IP access ),
Set the default phone region
# In config.php, add inside the array: 'default_phone_region' => 'GB', # use your country code
Enable memory caching (APCu)
# In config.php, add: 'memcache.local' => '\OC\Memcache\APCu',
After editing config.php, reload Apache:
pi@raspberrypi:~$ sudo systemctl reload apache2
Step 9 — Install Sync Clients
https://cloud.yourdomain.com). Choose which folders to sync. The client keeps a local copy of your files in sync with the server automatically.CalDAV:
https://cloud.yourdomain.com/remote.php/dav/principals/users/YOUR_USERNAME/CardDAV:
https://cloud.yourdomain.com/remote.php/dav/principals/users/YOUR_USERNAME/On iOS: Settings → Calendar → Accounts → Add Account → Other → Add CalDAV Account.
On macOS: System Settings → Internet Accounts → Add Account → CalDAV.
Step 10 — Add External Storage
You can mount additional folders — network shares, USB drives, even Google Drive — as storage locations visible inside Nextcloud. Enable the External Storage Support app first:
Go to Apps → Your Apps → External Storage Support → Enable.
Then go to Administration Settings → External Storages and add a mount. Common options:
| Type | Use case | Notes |
|---|---|---|
| Local | Another folder on the Pi (e.g. a second drive) | Path must be readable by the www-data user |
| SMB / CIFS | A NAS or Windows share on your network | Requires sudo apt install smbclient |
| SFTP | Another SSH server | Useful for accessing a remote server's files |
| WebDAV | Another WebDAV server | Can also mount another Nextcloud instance |
Performance Tips
sudo apt install redis-server php-redis. Add to config.php: 'memcache.locking' => '\OC\Memcache\Redis' and 'redis' => ['host' => 'localhost', 'port' => 6379]. This moves file lock handling out of the database, dramatically improving performance with multiple clients.sudo apt install imagemagick. Then run sudo -u www-data php /var/www/nextcloud/occ preview:generate-all to pre-generate thumbnails for your existing files. Schedule it as a cron job for ongoing generation.sudo -u www-data php occ db:add-missing-indicessudo -u www-data php occ db:convert-filecache-bigintsudo -u www-data php occ maintenance:repairKeeping Nextcloud Updated
Nextcloud releases updates frequently. Never use apt to update it — always use the built-in updater:
Go to Administration Settings → Overview. When an update is available you will see a notification. Click Open Updater and follow the steps — it downloads the new version, backs up your old installation, and runs the upgrade automatically.
Alternatively, use the command line updater:
pi@raspberrypi:~$ sudo -u www-data php /var/www/nextcloud/updater/updater.phar
After any update, run the post-upgrade steps:
pi@raspberrypi:~$ sudo -u www-data php /var/www/nextcloud/occ upgrade pi@raspberrypi:~$ sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices pi@raspberrypi:~$ sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off
Troubleshooting Common Problems
max_execution_time = 3600 and max_input_time = 3600 are set in php.ini and that you restarted Apache after editing. Also check Apache's timeout: add Timeout 3600 to your virtual host config. For very large files (50 GB+), use the desktop client rather than the browser — it uploads in chunks and handles network interruptions gracefully.trusted_domains in config.php. Add it as shown in Step 8. If you are accessing via the local IP (192.168.1.xx) and that is not in the list, add it. Changes take effect immediately — no Apache restart needed.www-data user owns the data directory: ls -la /media/mediadrive/nextcloud-data. (3) If the error mentions "file locking", Redis may not be running: sudo systemctl status redis-server. (4) Run the filesystem scan to force Nextcloud to re-index: sudo -u www-data php /var/www/nextcloud/occ files:scan --all.'memcache.local' => '\OC\Memcache\APCu'). (3) Enable Redis for file locking. (4) Disable unused apps, especially Talk and Recognize. (5) Check htop — if PHP processes are pegged, reduce MaxRequestWorkers in Apache's mpm config to avoid memory pressure.'default_phone_region' => 'GB' (or your ISO country code) to /var/www/nextcloud/config/config.php inside the config array. Save the file — the warning disappears immediately on next page load.sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off. Check the updater log at /var/www/nextcloud/data/updater.log for the cause. Most commonly: insufficient disk space (check with df -h) or a file permissions problem (sudo chown -R www-data:www-data /var/www/nextcloud).www-data user cannot access the path. For a local folder, check ownership: sudo chown www-data:www-data /path/to/folder. For SMB shares, verify the smbclient package is installed and the credentials are correct. For network shares that may be temporarily offline, the red dot is expected — it clears when the share becomes available again.Quick Reference
| Task | Command / Location |
|---|---|
| Nextcloud config file | /var/www/nextcloud/config/config.php |
| Nextcloud data directory | /media/mediadrive/nextcloud-data/ |
| occ — admin command line tool | sudo -u www-data php /var/www/nextcloud/occ |
| Scan all files | sudo -u www-data php occ files:scan --all |
| Run DB repairs | sudo -u www-data php occ db:add-missing-indices |
| Enable maintenance mode | sudo -u www-data php occ maintenance:mode --on |
| Disable maintenance mode | sudo -u www-data php occ maintenance:mode --off |
| List installed apps | sudo -u www-data php occ app:list |
| Enable an app | sudo -u www-data php occ app:enable appname |
| Disable an app | sudo -u www-data php occ app:disable appname |
| View Nextcloud logs | Admin Settings → Logging, or tail -f /var/www/nextcloud/data/nextcloud.log |
| Restart Apache | sudo systemctl restart apache2 |
| Restart Redis | sudo systemctl restart redis-server |
| PHP config file | /etc/php/8.2/apache2/php.ini |
| CalDAV URL | https://cloud.yourdomain.com/remote.php/dav/ |
| Admin panel | https://cloud.yourdomain.com/settings/admin |