How to Install Nextcloud with Docker (Your Own Private Cloud)

Nextcloud: your own private cloud — Dropbox, Google Photos and calendar — in the cupboard.

Nextcloud is Dropbox, Google Photos, a calendar and contacts, all on your own server. Phone photos upload automatically, files sync to every computer, and nobody is mining it for advertising. With Docker Compose it's one file and one command, plus a reverse proxy if you want to reach it from outside.

Quick reference

TaskWhat
Folder~/docker/nextcloud/compose.yaml
Startdocker compose up -d
First visithttp://server-ip:8080
AppsNextcloud on iOS/Android; desktop client for Windows/Mac/Linux
Run a Nextcloud commanddocker compose exec -u www-data app php occ ...
Updatedocker compose pull && docker compose up -d

1. The compose file

mkdir -p ~/docker/nextcloud && cd ~/docker/nextcloud
nano compose.yaml

services:
db:
image: mariadb:11
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
environment:
MARIADB_ROOT_PASSWORD: change-this-root-password
MARIADB_DATABASE: nextcloud
MARIADB_USER: nextcloud
MARIADB_PASSWORD: change-this-password
volumes:
- ./db:/var/lib/mysql
restart: unless-stopped

redis:
image: redis:alpine
restart: unless-stopped

app:
image: nextcloud:30
ports:
- "127.0.0.1:8080:80"
environment:
MYSQL_HOST: db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: change-this-password
REDIS_HOST: redis
NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com 192.168.1.50
OVERWRITEPROTOCOL: https
PHP_UPLOAD_LIMIT: 10G
volumes:
- ./html:/var/www/html
- /mnt/data/nextcloud:/var/www/html/data
depends_on:
- db
- redis
restart: unless-stopped

Change both passwords, the trusted domains, and the data path (put it on your biggest drive). If you'll only use it inside your network and not through Nginx, change the ports line to "8080:80" and remove OVERWRITEPROTOCOL.

docker compose up -d

2. First run

Open http://192.168.1.50:8080. Create the admin account. The database is already filled in from the environment variables, so just click Install. Skip the recommended apps for now — they can be added later.

3. Reach it from outside

Add a server block in Nginx (tutorial 28) for cloud.example.com pointing at 127.0.0.1:8080, with client_max_body_size 10G; and the WebSocket lines, then certbot --nginx -d cloud.example.com.

4. The apps

5. Background jobs

In Administration settings → Basic settings, set background jobs to Cron, then on the server:

sudo crontab -e

*/5 * * * * docker compose -f /home/john/docker/nextcloud/compose.yaml exec -u www-data app php cron.php

Updating

docker compose pull && docker compose up -d

Nextcloud only upgrades one major version at a time — change nextcloud:30 to 31, update, then 32, and so on. Back up ./db and ./html first.

Troubleshooting

"Access through untrusted domain". Add the name or IP you're using to NEXTCLOUD_TRUSTED_DOMAINS and docker compose up -d.

Warnings on the admin overview page. Most are about headers or the proxy. Run docker compose exec -u www-data app php occ db:add-missing-indices for the database ones; the rest are fixed by the Nginx headers from tutorial 28.

Uploads fail at around 1 MB or 100 MB. client_max_body_size in Nginx, and PHP_UPLOAD_LIMIT in the compose file.

Slow with lots of files. Make sure redis is running (docker compose ps) and background jobs are on cron.

Phone app says the server is on http. OVERWRITEPROTOCOL: https is missing or you're hitting the raw port instead of going through Nginx.

Wrapping up

One compose file with a database, Redis and Nextcloud; data on your big drive; Nginx and Certbot in front. Install the apps, turn on auto-upload, and you've replaced a cloud subscription with a box in the cupboard.

Call us