How to Install Nextcloud with Docker
Deploy a private cloud for files, calendars and contacts using Docker Compose, with MariaDB, Redis, HTTPS and a solid backup plan.
What you'll build
Nextcloud is a self-hosted replacement for Google Drive, Dropbox, Google Calendar and Google Contacts rolled into one. By the end of this tutorial you'll have a private cloud running in Docker with a proper database (MariaDB), a caching layer (Redis), automatic HTTPS, and a backup routine so your data is safe.
This guide targets a typical home server running Linux with Docker and Docker Compose already installed. Plan for about 30 minutes.
Why the "full" stack instead of the all-in-one image
You can run Nextcloud from a single container, but for anything beyond testing you want:
- MariaDB instead of the bundled SQLite — far better performance and reliability once you have real data and multiple users.
- Redis for file locking and caching — this removes the "transactional file locking" warnings and makes the UI noticeably snappier.
- A reverse proxy for TLS — so you connect over HTTPS with a clean hostname.
Step 1: Plan your storage
Decide where two kinds of data live:
- Config and database — small, but critical. Keep it on your fast SSD.
- User files — potentially large. This can live on a bigger drive or a mounted NAS share.
Create a folder structure:
mkdir -p ~/nextcloud/{db,redis,html,data}
cd ~/nextcloudStep 2: Create the Docker Compose file
Create compose.yaml:
services:
db:
image: mariadb:11
command: --transaction-isolation=READ-COMMITTED --log-bin=ROW
restart: unless-stopped
volumes:
- ./db:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD=change-me-root
- MARIADB_DATABASE=nextcloud
- MARIADB_USER=nextcloud
- MARIADB_PASSWORD=change-me-db
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- ./redis:/data
app:
image: nextcloud:29-apache
restart: unless-stopped
ports:
- "8080:80"
depends_on:
- db
- redis
volumes:
- ./html:/var/www/html
- ./data:/var/www/html/data
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=change-me-db
- REDIS_HOST=redis
- NEXTCLOUD_TRUSTED_DOMAINS=cloud.example.comReplace the passwords with strong, unique values and set NEXTCLOUD_TRUSTED_DOMAINS to the hostname you'll use.
Step 3: Start the stack
docker compose up -d
docker compose logs -f appThe first start takes a minute while Nextcloud initializes the database. When the logs settle, open http://your-server-ip:8080 and create your admin account.
Step 4: Put it behind HTTPS
Never expose Nextcloud over plain HTTP. Publish it through a reverse proxy such as Caddy or Nginx Proxy Manager, which will obtain a free Let's Encrypt certificate automatically. With Caddy it's as little as:
cloud.example.com {
reverse_proxy localhost:8080
}Step 5: Fix the common warnings
Open Administration settings → Overview. Two fixes clear most warnings:
- Missing indices / MIME types — run the maintenance commands via
occ:
docker compose exec --user www-data app php occ db:add-missing-indices
docker compose exec --user www-data app php occ maintenance:repair- Phone region / default region — set
default_phone_regioninconfig.php.
Step 6: Install the apps that matter
From the app store, enable:
- Calendar and Contacts for CalDAV/CardDAV sync with your phone.
- Notes and Tasks if you want a Google Keep / to-do replacement.
- Nextcloud Office (Collabora) for editing documents in the browser.
Connect your phone using the official Nextcloud app for file sync and the DAVx5 app (Android) for calendars and contacts.
Step 7: Back it up
Your Nextcloud is only as safe as your backups. Follow the 3-2-1 backup strategy:
- Put the instance in maintenance mode before backing up:
docker compose exec --user www-data app php occ maintenance:mode --on- Back up the
db,html, anddatafolders (or dump the database withmysqldumpand copy the files). - Turn maintenance mode off again.
Automate this with a nightly script and send the archive offsite with Restic or Duplicati.
Troubleshooting
- "Access through untrusted domain" — add the hostname to
NEXTCLOUD_TRUSTED_DOMAINSortrusted_domainsinconfig.php. - Slow uploads of large files — increase
client_max_body_sizein your reverse proxy and PHPupload_max_filesize. - 502 from the proxy — confirm the app container is healthy and the proxy targets the correct port.
Next steps
Once Nextcloud is stable, explore external storage (mount a NAS share), enable two-factor authentication for every account, and consider Immich for a dedicated photo-backup experience alongside it.
Related articles
The Complete Home Server Beginner's Guide
Go from zero to a running home server: choose hardware, pick an operating system, deploy your first apps, and keep everything secure and backed up.
Self-Hosting Starter Guide: Replace the Cloud
Discover which cloud services you can replace with self-hosted alternatives, and how to get started.
How to Set Up Jellyseerr for Media Requests
Give your household a clean way to request movies and shows that flow automatically into your Jellyfin or Plex library.