Why Nextcloud?
Google Drive is convenient. It is cheap. It works everywhere. But you pay with something other than money: Google scans your files, your photos and your calendar. They use that to show you ads and to understand your habits.
iCloud is better on the privacy front, but you pay for storage every month. And you are still dependent on Apple's infrastructure.
Nextcloud costs nothing to run once you have the hardware. Your photos are yours. Not Google's. The family holiday photos from 2019 are not sitting on a server in Oregon.
It works offline too. When you are home on your LAN, you can access all your files even if the internet is down.
What you need
- Raspberry Pi 4 with at least 2 GB RAM. 4 GB is recommended, especially if the family uses it actively.
- SSD connected via USB 3. Do not use an SD card for data storage. SD cards wear out from constant small writes, and you will lose your files. A 500 GB or 1 TB SSD is a good starting point.
- Docker and Docker Compose installed on the Pi. See our guide to Docker on Pi if you do not have it yet.
- A static IP for your Pi on the LAN. Set this up in your router using a DHCP reservation for the Pi's MAC address.
Prepare the SSD
Find out what your SSD is called on the system:
lsblk
It will typically be named sda or sdb. Create a filesystem on it (only needed the first time):
sudo mkfs.ext4 /dev/sda1
Create a mount point and mount the SSD:
sudo mkdir -p /data
sudo mount /dev/sda1 /data
To mount it automatically on reboot, add a line to /etc/fstab:
# Find the UUID of the SSD
sudo blkid /dev/sda1
# Add to /etc/fstab (replace UUID with yours)
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults 0 2
Create the directories Nextcloud needs and set permissions:
sudo mkdir -p /data/nextcloud
sudo chown -R 33:33 /data/nextcloud
www-data, which has UID 33. That is why we set ownership to 33:33.
Docker Compose setup
Create a directory for your Nextcloud installation:
mkdir -p ~/nextcloud
cd ~/nextcloud
Create the file docker-compose.yml:
services:
db:
image: mariadb:10.11
restart: unless-stopped
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: change-this-to-a-strong-password
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: change-this-to-another-strong-password
nextcloud:
image: nextcloud:latest
restart: unless-stopped
ports:
- "8080:80"
volumes:
- /data/nextcloud:/var/www/html/data
- nextcloud_html:/var/www/html
environment:
MYSQL_HOST: db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: change-this-to-another-strong-password
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: change-this-to-admin-password
NEXTCLOUD_TRUSTED_DOMAINS: "192.168.1.100 nextcloud.yourdomain.com"
depends_on:
- db
volumes:
db_data:
nextcloud_html:
NEXTCLOUD_TRUSTED_DOMAINS use your Pi's actual IP address. Find it with hostname -I.
Start Nextcloud
Start the whole stack:
docker compose up -d
The first time this takes a while. Docker pulls the images and Nextcloud sets up the database. Watch what is happening:
docker compose logs -f nextcloud
When you see lines indicating Nextcloud is ready, open a browser and go to:
http://[your-pi-ip]:8080
You should see the Nextcloud welcome screen.
First setup
Log in with the admin user you set in docker-compose.yml. Nextcloud will ask if you want to install recommended apps. Say yes. This typically includes:
- Calendar: a calendar that syncs with iPhone and Android
- Contacts: contacts with CardDAV support
- Photos: a photo gallery with albums and automatic organisation
- Notes: a simple notes app, perfect for shared shopping lists
You can always install more apps later under Settings → Apps.
Add family members
Go to the top right corner, click your avatar, and choose Users. Create an account for each family member.
Set a quota for each user. This prevents one family member from accidentally filling the entire SSD with video. 50-100 GB per person is a reasonable starting point.
To share a folder: right-click the folder in the file browser, choose Share, and type the username. You can grant read-only or full write access.
Secure your Pi before going further
Before exposing Nextcloud to the internet, it is worth hardening the Pi itself. Two things matter most:
- SSH hardening: switch to key-based login, disable password authentication and set up fail2ban. See our SSH hardening guide.
- UFW firewall: block all incoming traffic except what you explicitly allow. Port 8080 should only be reachable from your LAN. See our UFW firewall guide.
Remote access with Cloudflare Tunnel
By default, Nextcloud can only be reached from your LAN. If the family wants to use it from their phones while out, you need to expose it.
The safe way is via Cloudflare Tunnel. You open no ports in your router. Cloudflare handles HTTPS. See our guide to Cloudflare Tunnel on Raspberry Pi for the full setup.
If you prefer a VPN over a Cloudflare dependency, WireGuard is a solid alternative. See our WireGuard guide.
Once you have set up the tunnel, you need to add your domain to Nextcloud's trusted domains. Edit config/config.php inside the container:
docker exec -it nextcloud-nextcloud-1 bash
nano /var/www/html/config/config.php
Find trusted_domains and add your domain:
'trusted_domains' =>
array (
0 => '192.168.1.100:8080',
1 => 'nextcloud.yourdomain.com',
),
Mobile app
The Nextcloud app is available for both iOS and Android and is free.
- Automatic photo upload: The app can upload new photos from the camera roll automatically. Go to Settings → Auto upload in the app. The family's photos land directly in Nextcloud.
- Calendar on iPhone: Go to iPhone Settings → Calendar → Accounts → Add Account → Other → CalDAV account. Server address is your Nextcloud URL, with username and password as set in Nextcloud.
- Calendar on Android: Use the DAVx5 app (free on F-Droid, small payment on Google Play). It syncs calendar and contacts from Nextcloud into Android's native apps.
Backup
A Pi can fail. An SSD can die. Backup is not optional.
The simple approach: stop Nextcloud, copy the data, start again.
# Stop the containers
cd ~/nextcloud
docker compose stop
# Create a database dump
docker exec nextcloud-db-1 sh -c \
'mysqldump --all-databases -u root -p"your-root-password"' \
> backup-db-$(date +%Y%m%d).sql
# Copy Nextcloud data to an external disk (adjust the path)
rsync -av /data/nextcloud/ /mnt/backup/nextcloud-data/
# Start the containers again
docker compose start
Automate it with cron. Run crontab -e and add:
# Run backup every Sunday at 02:00
0 2 * * 0 cd ~/nextcloud && docker compose stop && rsync -aq /data/nextcloud/ /mnt/backup/nextcloud/ && docker compose start
Performance tips
Nextcloud on a Pi 4 is perfectly usable for a family, but a few things make it noticeably faster.
Redis for memory cache
Add Redis to your docker-compose.yml:
redis:
image: redis:alpine
restart: unless-stopped
Then add these environment variables to the nextcloud service:
REDIS_HOST: redis
And add redis to depends_on in the nextcloud service. Redis keeps Nextcloud's session data and lock information in memory, which takes pressure off the database. The difference in response times is noticeable.
PHP memory and upload limits
Add these environment variables to the nextcloud service:
PHP_MEMORY_LIMIT: 512M
PHP_UPLOAD_LIMIT: 512M
Cron job for background tasks
Nextcloud has background tasks that need to run regularly (indexing, thumbnails, etc.). Add a cron job on the Pi:
# Run Nextcloud cron every 5 minutes
*/5 * * * * docker exec -u www-data nextcloud-nextcloud-1 php -f /var/www/html/cron.php
Switch to Cron (not AJAX) in Nextcloud under Settings → Basic settings.
What Nextcloud is not
Nextcloud is not a cloud backup. It is local storage with a web interface. If the house burns or the Pi is stolen, the data is gone unless you have an external backup.
A Raspberry Pi 4 is not built to handle 100 concurrent users. For a family of 4-6 people it works well. If you want to run it for a whole office, you need more powerful hardware.
It is not Google Photos either. Nextcloud Photos is good, but it does not recognise faces or locations automatically the way Google's AI does. That is the price of privacy.
Sources
- Nextcloud Administration Manual: official documentation for setup, apps and configuration
- Nextcloud – Docker Hub: official Docker image with environment variable documentation
- Raspberry Pi Foundation – Official Documentation: hardware, OS and setup guides