Nextcloud is the gold standard for self-hosted cloud storage. It’s like having your own Google Drive, Google Calendar, and Google Contacts — but you own all the data. In this guide, I’ll walk you through setting up Nextcloud on Docker from scratch, including the reverse proxy, SSL certificates, and crucial performance optimizations that most guides skip.
By the end, you’ll have a production-ready Nextcloud instance that’s fast, secure, and entirely under your control.
Why Self-Host Nextcloud?
Before diving in, let’s address why you’d want to run your own cloud:
- Privacy: Your files stay on your hardware, not Big Tech servers
- No storage limits: Only limited by your disk space
- No subscription fees: One-time setup, no monthly charges
- Feature-rich: Calendar, contacts, notes, tasks, video calls, and hundreds of apps
- Data portability: Easy to backup and migrate
The main trade-off? You’re responsible for maintenance and security. But with Docker, this becomes surprisingly manageable.
Prerequisites
Before starting, you’ll need:
- A server running Linux (Ubuntu 22.04/24.04, Debian 12, or similar)
- Docker and Docker Compose installed
- A domain name pointing to your server (for SSL)
- At least 2GB RAM (4GB recommended)
- 20GB+ storage for the base install
If you haven’t installed Docker yet, here’s the quick version:
| |
Project Structure
I recommend organizing your Docker projects consistently. Here’s the structure we’ll use:
/opt/docker/nextcloud/
├── docker-compose.yml
├── .env
├── data/
│ └── nextcloud/
├── db/
└── redis/
Create the directory structure:
| |
The Docker Compose File
Here’s the complete docker-compose.yml. I’ll explain each section afterward:
| |
Understanding the Configuration
Nextcloud Container:
- Uses the official Apache-based image (more straightforward than fpm variants)
- Connects to MariaDB and Redis for database and caching
- The
OVERWRITEPROTOCOL=httpsis crucial for proper HTTPS behind a reverse proxy TRUSTED_PROXIEStells Nextcloud to trust headers from your reverse proxy
MariaDB Container:
- The command flags enable binary logging for better crash recovery
- MariaDB 11 is well-tested with Nextcloud and performs excellently
Redis Container:
- Provides memory caching for drastically improved performance
- Alpine variant keeps the image small
Environment Variables
Create a .env file with your configuration:
| |
Generate strong passwords:
| |
Security note: Never commit .env files to version control. Add .env to your .gitignore.
Reverse Proxy Options
You have several options for the reverse proxy. I’ll cover Traefik (my recommendation) and Caddy.
Option 1: Traefik (Recommended)
The docker-compose above includes Traefik labels. If you don’t have Traefik running, here’s a minimal setup:
Create /opt/docker/traefik/docker-compose.yml:
| |
Create the proxy network first:
| |
Option 2: Caddy
If you prefer Caddy’s simplicity, remove the Traefik labels from the Nextcloud compose file and add:
| |
Then create a Caddyfile:
cloud.yourdomain.com {
reverse_proxy localhost:8080
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
}
redir /.well-known/carddav /remote.php/dav/ 301
redir /.well-known/caldav /remote.php/dav/ 301
}
Starting the Stack
With everything configured, start the containers:
| |
The first start takes a few minutes as Nextcloud initializes the database. You’ll see messages about creating tables and configuring the system.
Initial Setup
- Open
https://cloud.yourdomain.comin your browser - Create your admin account (use a strong password!)
- The database should auto-configure from environment variables
- Click “Install” and wait for completion
If you see database connection errors, wait a minute for MariaDB to fully initialize, then refresh.
Essential Post-Install Configuration
Configure Redis Caching
Edit the Nextcloud config file to enable Redis:
| |
Add these lines before the closing );:
| |
Exit the container and restart Nextcloud:
| |
Set Up Background Jobs
Nextcloud needs to run background tasks regularly. The most reliable method is a system cron job:
| |
Then change the background jobs setting in Nextcloud:
- Go to Settings → Administration → Basic settings
- Under “Background jobs”, select Cron
Configure Email
For password resets and notifications, configure SMTP:
- Go to Settings → Administration → Basic settings
- Under “Email server”, enter your SMTP details
If you don’t have an SMTP server, I recommend using a free tier from:
- Brevo (formerly Sendinblue): 300 emails/day free
- Mailgun: 5,000 emails/month free
Enable HTTPS Strict Mode
In your config.php, ensure these settings exist:
| |
Then regenerate the .htaccess:
| |
Performance Optimization
PHP Memory Limit
The default 512MB is usually fine, but for large file operations, increase it:
| |
Enable OPcache JIT
For PHP 8+, the JIT compiler provides significant performance gains:
| |
Database Maintenance
Run these periodically (monthly is fine):
| |
Preview Generation
File previews can be slow. Install the Preview Generator app:
- Go to Apps → Recommended apps
- Install “Preview Generator”
- Set up a cron job:
| |
Security Hardening
Fail2Ban Integration
Protect against brute force attacks by integrating with Fail2Ban. First, enable Nextcloud’s logging:
In config.php:
| |
Create /etc/fail2ban/filter.d/nextcloud.conf:
| |
Create /etc/fail2ban/jail.d/nextcloud.conf:
| |
Restart Fail2Ban:
| |
Two-Factor Authentication
Enable 2FA for all users:
- Go to Apps → Security
- Install “Two-Factor TOTP Provider”
- Each user can then enable 2FA in their personal settings
Essential Apps to Install
Navigate to Apps and consider installing:
- Calendar: Full CalDAV calendar with sharing
- Contacts: CardDAV contact management
- Notes: Markdown note-taking
- Tasks: Todo list synced via CalDAV
- Talk: Video calls and chat
- Deck: Kanban-style project management
- Memories: Photo management (excellent Google Photos alternative)
- News: RSS feed reader
- Bookmarks: Bookmark manager
Mobile and Desktop Sync
Desktop Client
Download from nextcloud.com/install for:
- Windows
- macOS
- Linux (AppImage, Flatpak, or distro packages)
Mobile Apps
- Android: Nextcloud (Play Store / F-Droid)
- iOS: Nextcloud (App Store)
For contacts and calendar sync on mobile, use:
- Android: DAVx⁵
- iOS: Built-in CalDAV/CardDAV support
Backup Strategy
Never skip backups. Here’s a simple script:
| |
Add to cron for daily backups:
| |
Troubleshooting Common Issues
“Access through untrusted domain”
Add your domain to trusted domains:
| |
“Your data directory is readable by other users”
Fix permissions:
| |
Slow file uploads
Check your PHP upload limits and reverse proxy timeout settings. In Traefik, add:
| |
Database locked errors
Usually a sign of missing Redis locking. Verify Redis is working:
| |
Updating Nextcloud
Updates are straightforward with Docker:
| |
Important: Always backup before updating, and check the Nextcloud changelog for breaking changes.
Conclusion
You now have a fully functional, production-ready Nextcloud instance running on Docker. With proper Redis caching, background jobs, and security hardening, it should perform excellently for personal or small team use.
The beauty of self-hosting Nextcloud is that it grows with your needs. Start with file sync, then add calendar and contacts, then explore the vast app ecosystem. Unlike cloud services, you’re never locked in — your data is always yours.
Next steps to consider:
- Set up Collabora or OnlyOffice for document editing
- Configure external storage (S3, SMB shares)
- Explore the federation features for sharing across instances
If you run into issues, the Nextcloud community forums are incredibly helpful. Happy self-hosting!
Have questions about this guide? Found an error? Drop a comment below or reach out on social media.