Install Nextcloud on Raspberry Pi
Running Nextcloud on a Raspberry Pi
Nextcloud runs on a Raspberry Pi, but the experience depends heavily on your hardware choices. A Pi 4 with 4 GB RAM and a USB SSD handles 1-3 users well. A Pi 5 with 8 GB and NVMe is genuinely comfortable for a small family. Running Nextcloud on an SD card or a Pi with 1-2 GB RAM leads to frustration — slow page loads, failed file syncs, and database corruption.
This guide covers the Pi-specific setup: ARM64 Docker installation, SSD boot, memory tuning for constrained hardware, and realistic expectations for what a Pi can handle.
For Nextcloud’s full feature guide and troubleshooting, see the main Nextcloud guide.
Prerequisites
- Raspberry Pi 4 (4 GB) or Pi 5 (4-8 GB). Pi 3B+ works but is marginal.
- Raspberry Pi OS Lite (64-bit / ARM64) — not the 32-bit version
- USB SSD or NVMe (strongly recommended — SD cards are too slow for database writes)
- Docker and Docker Compose installed (guide)
- 2 GB of free RAM
- 10 GB of free disk space for the application, plus storage for files
- SSH access enabled
Platform Setup
Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
Log out and back in, then verify:
docker run --rm hello-world
uname -m # Should show: aarch64
SSD Storage (Critical for Performance)
Running Nextcloud’s PostgreSQL database on an SD card causes write amplification, slow queries, and eventual card failure. Move Docker’s data root to SSD:
Option A: Boot entirely from SSD (recommended). Flash Raspberry Pi OS directly to the SSD and boot from USB/NVMe. No SD card needed on Pi 4 (with updated bootloader) or Pi 5.
Option B: Keep boot on SD, move Docker data to SSD.
# Mount SSD
sudo mkdir -p /mnt/ssd
sudo mount /dev/sda1 /mnt/ssd # adjust device as needed
echo "/dev/sda1 /mnt/ssd ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab
# Move Docker data root to SSD
sudo systemctl stop docker
sudo mkdir -p /mnt/ssd/docker
sudo rsync -aP /var/lib/docker/ /mnt/ssd/docker/
# Configure Docker to use SSD
sudo tee /etc/docker/daemon.json << 'EOF'
{
"data-root": "/mnt/ssd/docker",
"log-driver": "json-file",
"log-opts": {
"max-size": "5m",
"max-file": "2"
}
}
EOF
sudo systemctl start docker
Add Swap
Even with 4 GB RAM, swap is important for Nextcloud on a Pi. PostgreSQL, Redis, and the PHP application compete for memory:
sudo fallocate -l 2G /mnt/ssd/swapfile # Put swap on SSD, not SD card
sudo chmod 600 /mnt/ssd/swapfile
sudo mkswap /mnt/ssd/swapfile
sudo swapon /mnt/ssd/swapfile
echo '/mnt/ssd/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Docker Compose Configuration
Create the project directory:
mkdir -p ~/nextcloud && cd ~/nextcloud
Create docker-compose.yml:
services:
db:
image: postgres:17-alpine
container_name: nextcloud-db
restart: unless-stopped
volumes:
- nextcloud-db:/var/lib/postgresql/data
environment:
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
# CHANGE THIS — use a strong password
POSTGRES_PASSWORD: "change-this-db-password"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nextcloud"]
interval: 10s
timeout: 5s
retries: 5
# Pi-specific: limit PostgreSQL memory usage
deploy:
resources:
limits:
memory: 256M
redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
# Limit Redis to 64MB — enough for session and file lock caching
command: redis-server --maxmemory 64mb --maxmemory-policy allkeys-lru
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
app:
image: nextcloud:33.0.0-apache
container_name: nextcloud
restart: unless-stopped
ports:
- "8080:80"
volumes:
- nextcloud-html:/var/www/html
environment:
# Database
POSTGRES_HOST: db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: "change-this-db-password"
# Cache
REDIS_HOST: redis
# Admin account (first run only)
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: "change-this-admin-password"
# Trusted domains — replace with your Pi's IP
NEXTCLOUD_TRUSTED_DOMAINS: "localhost your-pi-ip"
# PHP tuning — conservative for Pi hardware
PHP_MEMORY_LIMIT: "384M"
PHP_UPLOAD_LIMIT: "4G"
APACHE_BODY_LIMIT: "0"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
cron:
image: nextcloud:33.0.0-apache
container_name: nextcloud-cron
restart: unless-stopped
volumes:
- nextcloud-html:/var/www/html
entrypoint: /cron.sh
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
volumes:
nextcloud-db:
nextcloud-html:
Start the stack:
docker compose up -d
First startup takes 2-4 minutes on a Pi (slower than x86 due to ARM’s lower single-thread performance).
Initial Setup
- Open
http://your-pi-ip:8080in a browser - The admin account is created from the environment variables
- Install only the apps you need — each app adds memory and CPU overhead on constrained Pi hardware
- Go to Administration > Basic settings and confirm background jobs is set to Cron
Raspberry Pi Optimization
Memory Monitoring
With Nextcloud, PostgreSQL, Redis, and the cron container all running, memory usage on a Pi 4 (4 GB) looks approximately like:
| Component | Approximate RAM |
|---|---|
| Nextcloud (Apache + PHP) | 200-400 MB |
| PostgreSQL | 100-200 MB |
| Redis | 30-64 MB |
| Cron container | 100-200 MB (shares image) |
| OS + Docker | 300-400 MB |
| Total | 730 MB - 1.3 GB |
Monitor with:
free -m
docker stats --no-stream
On a 4 GB Pi, you have ~2.7-3.3 GB free for file operations and other containers. On a 2 GB Pi, this is tight — consider skipping Collabora/OnlyOffice and limiting concurrent users to 1.
Disable Unnecessary Nextcloud Features
Reduce CPU and memory usage by disabling features you do not need:
# Disable apps that consume resources
docker compose exec -u www-data app php occ app:disable activity
docker compose exec -u www-data app php occ app:disable weather_status
docker compose exec -u www-data app php occ app:disable dashboard
Reduce Preview Generation Load
Image previews are CPU-intensive on ARM. Limit preview sizes:
docker compose exec -u www-data app php occ config:system:set preview_max_x --value="1024"
docker compose exec -u www-data app php occ config:system:set preview_max_y --value="1024"
docker compose exec -u www-data app php occ config:system:set jpeg_quality --value="60"
SD Card Wear (If Not Using SSD)
If you must run on an SD card, reduce write frequency:
# Increase cron interval to reduce database writes
docker compose exec -u www-data app php occ config:system:set maintenance_window_start --value="1" --type=integer
Use a high-endurance SD card (Samsung PRO Endurance, SanDisk MAX Endurance). Standard SD cards can fail within months under database write load.
Reverse Proxy
For HTTPS access, use Nginx Proxy Manager or Caddy on the same Pi or a separate device:
- Point your domain at the Pi’s IP
- Proxy to
http://nextcloud:80(orpi-ip:8080) - Enable SSL with Let’s Encrypt
- Configure Nextcloud trusted proxies:
docker compose exec -u www-data app php occ config:system:set overwriteprotocol --value="https"
docker compose exec -u www-data app php occ config:system:set trusted_proxies 0 --value="172.16.0.0/12"
See Reverse Proxy Setup.
Backup
# Database
docker compose exec nextcloud-db pg_dump -U nextcloud nextcloud > nextcloud-db-$(date +%Y%m%d).sql
# Application data
docker compose stop app cron
docker run --rm -v nextcloud-html:/data -v $(pwd):/backup alpine tar czf /backup/nextcloud-data-$(date +%Y%m%d).tar.gz /data
docker compose start app cron
On a Pi, back up to a USB drive or network storage — not to the same SD card or SSD that Nextcloud runs on. See Backup Strategy.
Troubleshooting
Very slow first page load after startup
The first page load on a Pi triggers PHP OPcache compilation. This can take 30-60 seconds. Subsequent loads are much faster. If every page load is slow, check that Redis is connected (Admin > Overview) and OPcache is active.
Out of memory — containers killed by OOM
Check dmesg | grep -i oom. If PostgreSQL or Nextcloud is being OOM-killed:
- Reduce
PHP_MEMORY_LIMITto256M - Add or increase swap
- Remove unnecessary containers from the Pi
- Upgrade to a Pi with more RAM
Wrong architecture image pulled
If Docker pulls an amd64 image instead of ARM64:
docker inspect nextcloud | grep Architecture
# Should show: arm64
Force the platform in Compose:
platform: linux/arm64
File sync errors with desktop/mobile clients
Nextcloud’s sync client is sensitive to server response time. On a Pi, large file scans can cause timeouts. Increase the client’s timeout setting and avoid syncing folders with thousands of files.
SD card corruption
Symptoms: random read errors, containers failing to start, database errors. The only fix is to flash a new SD card from your backup. Migrate to SSD to prevent recurrence.
Resource Requirements
- RAM: ~1 GB minimum (Nextcloud + PostgreSQL + Redis + cron). 4 GB Pi recommended.
- CPU: Medium. Page loads are noticeably slower than x86. Preview generation is CPU-bound.
- Disk: 1 GB for the application. SSD strongly recommended for database performance.
- Power: ~5-7W for Pi 4 with SSD, ~8-10W for Pi 5 with NVMe
Realistic Expectations
| Pi Model | Users | Experience |
|---|---|---|
| Pi 3B+ (1 GB) | 1 | Barely usable. Constant swapping. File sync works but UI is painful. |
| Pi 4 (2 GB) | 1 | Functional but tight. No Collabora/OnlyOffice. |
| Pi 4 (4 GB) | 1-3 | Good for file sync and basic apps. Preview generation is slow. |
| Pi 4 (8 GB) | 2-5 | Comfortable. Can run Collabora with modest usage. |
| Pi 5 (8 GB) | 3-8 | Best Pi experience. NVMe support. Handles concurrent users well. |
For more than 5 regular users, consider an Intel N100 mini PC — 3-4x the single-thread performance at similar power consumption.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments