Published

Nextcloud

File sync and sharing with calendar and contacts (CalDAV/CardDAV), desktop and mobile sync clients and an app store for more. Fits a family, a team or a small company that wants its files on its own server. The stack is the community Docker image (Apache with PHP, background jobs every 5 minutes), PostgreSQL and Redis.

Resources by load level

What the app itself needs at each level, next to what we recommend for a server that runs only this app.

LevelWhat it meansApp requirementsRecommended
LightEstimateUp to 5 users (a family or a small office), ~20 GiB of files, sync clients on a few devices, calendars and contacts; about 4 requests at once.2.1 vCPU · 2.5 GiB RAM · 36 GiB disk2.64 vCPU · 4.5 GiB RAM · 50.945 GiB disk
MediumEstimateUp to 25 users, ~125 GiB of files (about 5 GiB each), sync clients on every device, shared folders, calendars and contacts; about 10 requests at once.3.25 vCPU · 3.25 GiB RAM · 172.5 GiB disk4.02 vCPU · 5.4 GiB RAM · 207.92 GiB disk
HeavyEstimateUp to 100 users, ~500 GiB of files, ~30 PHP requests at peak; no Office, Talk or other extra servers. Beyond this, plan separate servers per Nextcloud's enterprise guidance.6.25 vCPU · 7.5 GiB RAM · 705.25 GiB disk7.62 vCPU · 10.5 GiB RAM · 820.583 GiB disk

Recommended = app requirements + system baseline + safety headroom, under sizing policy 2026.10.0. Options stay at their defaults. “Estimate” means the sources give no number for that case, so it is worked out from them by the method stated under Components. How the numbers are built

Size it in the Stack Sizer

Ready-to-run files

Support level Supported

Compose template from the official sources; not yet verified by a run.

Create docker-compose

Components

What each component needs at each load level, before baseline and headroom.

vCPU / GiB RAM / GiB disk
ComponentLightMediumHeavySources
Nextcloud (Apache, PHP and cron) (app)1 / 1.25 / 292 / 2 / 165.54 / 3 / 653[4][15][16][29][35][36]
PostgreSQL (database)1 / 1 / 6.51 / 1 / 6.52 / 4 / 51.5[16][18][29][43][44][45][46][47][48][49]
Redis (file locking, distributed cache, sessions) (cache)0.1 / 0.25 / 0.50.25 / 0.25 / 0.50.25 / 0.5 / 0.75[7][17][18][40]
How the estimates are worked out
  • Nextcloud (Apache, PHP and cron) · Light: RAM: 4 concurrent PHP requests × 100 MB (top of the documented typical worker) + OPcache 128 MiB + APCu 32 MiB + one cron.php run at the image's 512M memory_limit = 1.05 GiB, rounded up to 1.25. vCPU: one core for a handful of mostly I/O-bound requests (ANAROQ estimate). Disk: image 1.89 GiB (measured, compressed + unpacked, both kept by containerd) + 1 GiB html volume (0.761 GiB code copy, apps, config, log) + 20 GiB of files × 1.3 for trash bin, versions and previews = 28.89 GiB, rounded up.
  • Nextcloud (Apache, PHP and cron) · Medium: RAM: 10 concurrent PHP requests × 100 MB + OPcache and APCu 160 MiB + one 512M cron.php run = 1.66 GiB, rounded up to 2. vCPU: two cores, so preview generation or a background job does not stall interactive requests (ANAROQ estimate). Disk: image 1.89 GiB (measured, compressed + unpacked, both kept by containerd) + 1 GiB html volume (0.761 GiB code copy, apps, config, log) + 125 GiB of files × 1.3 for trash bin, versions and previews = 165.39 GiB, rounded up.
  • Nextcloud (Apache, PHP and cron) · Heavy: RAM: the tuning guide's example gives PHP 2 GB for 30 workers; + OPcache and APCu 160 MiB + one 512M cron.php run = 2.66 GiB, rounded up to 3. vCPU: four cores for ~30 concurrent requests with previews and background jobs (ANAROQ estimate). Disk: image 1.89 GiB (measured, compressed + unpacked, both kept by containerd) + 1 GiB html volume (0.761 GiB code copy, apps, config, log) + 500 GiB of files × 1.3 for trash bin, versions and previews = 652.89 GiB, rounded up.
  • PostgreSQL · Light: Embedded metadata DB with the image's default config: equals the PostgreSQL profile's light preset (≤ 5 GB data, ≤ 20 concurrent connections) at every load level. Light preset method: shared_buffers 25% of RAM, worst-case work_mem/maintenance_work_mem budget, 0.5 GiB image + 5 GiB data + 1 GiB WAL.
  • PostgreSQL · Medium: About 10 PHP requests, each with its own connection (dbpersistent off), fit the sidecar's 20-connection envelope, and with Redis taking the file locks the database holds the file cache and activity (365 days) for ~125 GiB of files, well under 5 GB. Light preset method: shared_buffers 25% of RAM, worst-case work_mem budget, 0.5 GiB image + 5 GiB data + 1 GiB WAL.
  • PostgreSQL · Heavy: Up to ~30 PHP processes each hold a connection (dbpersistent off), beyond the sidecar's 20-connection envelope, so the PostgreSQL profile's medium preset (≤ 100 connections, ≤ 50 GB). Its method: shared_buffers 1 GiB = 25%, worst-case work_mem budget for 100 connections, 0.5 GiB image + 50 GiB data + 1 GiB WAL.
  • Redis (file locking, distributed cache, sessions) · Light: Redis holds file locks, the distributed cache and PHP sessions of a few users: well under 0.25 GiB (ANAROQ estimate; Nextcloud gives no figure). Disk: image 0.19 GiB (55,569,153 B compressed + 148,460,032 B unpacked) + an RDB snapshot up to the dataset in the container layer, rounded up to 0.5 GiB.
  • Redis (file locking, distributed cache, sessions) · Medium: Locks, cache and sessions of 25 users still fit 0.25 GiB; 0.25 vCPU for the lock traffic of every file operation (ANAROQ estimate). Disk as light: 0.19 GiB image + RDB snapshot, rounded up to 0.5 GiB.
  • Redis (file locking, distributed cache, sessions) · Heavy: Locks, distributed cache and sessions of 100 users: 0.5 GiB, with no eviction policy since locks must not be evicted (ANAROQ estimate). Disk: 0.19 GiB image + an RDB snapshot up to the 0.5 GiB dataset, rounded up to 0.75 GiB.

Ports

Public ports are meant to be reached from outside the stack, usually through a reverse proxy; internal ones stay on the stack's own network.

ComponentPortExposurePurposeSources
Nextcloud (Apache, PHP and cron)80/tcpPublic, through a proxyWeb UI, WebDAV/CalDAV/CardDAV and sync clients (HTTP; serve only behind TLS)[3][4]
PostgreSQL5432/tcpInternal onlyPostgreSQL connections from Nextcloud[2][48]
Redis (file locking, distributed cache, sessions)6379/tcpInternal onlyRedis for file locking, distributed cache and PHP sessions[7][38]

Every port in the catalog, with conflicts between apps

User and permissions (UID/GID)

The user each container's process runs as, and the paths it writes to. A bind mount for one of these paths must be writable by that UID:GID.

ComponentUID:GIDUserStarts as rootWrites toSources
Nextcloud (Apache, PHP and cron)33:33www-dataYes, prepares its directories, then drops to this user/var/www/html/var/www/data[2][4][5][37]
PostgreSQL999:999postgresYes, prepares its directories, then drops to this user/var/lib/postgresql/var/run/postgresql[41][42][48]
Redis (file locking, distributed cache, sessions)999:999redisYes, prepares its directories, then drops to this user/data[38][39]
  • Nextcloud (Apache, PHP and cron): The container starts as root: the entrypoint copies the code into /var/www/html as www-data and runs occ as www-data, Apache serves requests as www-data (UID 33 on the Debian image; 82 on Alpine), and root's busybox crond runs cron.php as www-data. /var/www/data is created owned by www-data and Nextcloud sets it to 0770.
  • Redis (file locking, distributed cache, sessions): The Dockerfile creates redis with fixed uid and gid 999; started as root, the entrypoint fixes ownership and drops to redis with setpriv. /data is the working directory for snapshots; the template gives it no volume, since locks, cache and sessions can be lost on recreate.

Storage growth

How much each component's data grows per month at each load level, on top of the disk in the profile. A value marked Assumption is ANAROQ's stated assumption, not a figure from the sources; the notes say what it rests on.

GiB per month
ComponentLightMediumHeavySources
Nextcloud (Apache, PHP and cron)Assumption1520[29]
PostgreSQLAssumption0.020.10.5[29]
What the growth figures rest on
  • Nextcloud (Apache, PHP and cron): New files of the users (~0.2 GiB per user per month), plus their trash bin (kept at least 30 days, then trimmed when space is needed) and versions (expired by the default rules). Nextcloud gives no growth figure; this is an ANAROQ assumption. Set user quotas to bound it.
  • PostgreSQL: The file cache grows with the number of files, and activity entries are kept 365 days (activity_expire_days) before they level off. Nextcloud gives no growth figure; this is an ANAROQ assumption.

Upgrade and rollback

How to move to a new version safely, and how to go back if it fails.

Back up first

Turn on maintenance mode (occ maintenance:mode --on), dump the database with pg_dump, copy both volumes (/var/www/html with config, custom_apps and themes; /var/www/data), then turn it off. [23][25]

Upgrade steps

  1. Read the critical changes of the target major. Move to the latest point release of your current major first; majors cannot be skipped (33 → 34 → 35). [2][5][25]
  2. Set the new nextcloud image tag, then docker compose pull and docker compose up -d. The entrypoint runs occ upgrade itself; it refuses to start if the tag skips a major or is older than the data. [2][5]
  3. After a major upgrade, let cron run 2–3 times before the next major (background migrations), and run the long migrations: docker compose exec -u www-data nextcloud php occ db:add-missing-indices. [2][25]

Roll back

Downgrading is not supported, and the image refuses to start on data newer than itself. Roll back by restoring the backup: recreate the database from the dump, put back both volumes, and start the old tag. [5][24][25]

Known breaking changes

  • In 35.0.0: PHP 8.2 is no longer supported, and the database minimums rose to MariaDB 10.11 and MySQL 8.4. The image ships PHP 8.5 and this stack uses PostgreSQL 18, so it only matters for an external database. [26]
  • In 33.0.0: PostgreSQL 13 is no longer supported; MP3 cover previews are off by default; Snowflake IDs arrive, with a server ID to set in config.php or the environment. [27]

Limits

  • Web uploads are capped at 512 MB per request (PHP_UPLOAD_LIMIT) and 1 GiB per request body (APACHE_BODY_LIMIT). The web UI and the sync clients upload in chunks, so this only limits WebDAV clients that send a file in one request. [2][28]
  • Background jobs run from cron.php every 5 minutes inside the app container. If crond stops, nothing restarts it until the container restarts: check the last run under Administration settings → Basic settings. [4][6][19]
  • CalDAV and CardDAV discovery (/.well-known) does not work behind a reverse proxy unless the proxy redirects it; the generated Caddyfile does not. Give calendar and contact apps the full URL https://<domain>/remote.php/dav/, or add the redirects from the docs. [20]
  • The stack has no office editor, Talk high-performance backend, antivirus or preview service; each is a separate server to add. Major versions upgrade one at a time and cannot be downgraded. [14][16][25]

Security

  • Expose Nextcloud only over HTTPS through the reverse proxy; local mode is loopback-only for evaluation. Behind the proxy the template sets OVERWRITEPROTOCOL=https, OVERWRITEHOST and OVERWRITECLIURL to the domain, and writes the domain to trusted_domains at install; a later domain change needs occ config:system:set trusted_domains. Add HSTS at the proxy. [2][11][20][22]
  • The first administrator is created from NEXTCLOUD_ADMIN_USER and the NEXTCLOUD_ADMIN_PASSWORD secret on the first start, so the web installer is never open. The variable is read only then: change the password in the UI later, not in .env. [2][5]
  • Brute-force protection is on by default and throttles per client IP, so the proxy setup matters: the template turns off Apache's X-Real-IP rewrite and trusts the private ranges (TRUSTED_PROXIES) so Nextcloud reads X-Forwarded-For. If every user is throttled together, fix trusted_proxies; never disable auth.bruteforce.protection.enabled. [4][20][21]
  • config/config.php holds the instance secret, the password salt and a database login that Nextcloud creates for itself (oc_admin, with a generated password), so treat the /var/www/html volume as secret. Redis has no password and stays on the internal network. [3][18][30]

Backup

  • Back up three things together, in maintenance mode: the database (pg_dump of nextcloud), the config folder (with custom_apps and themes, in the /var/www/html volume) and the data volume (/var/www/data). A restore needs all three. Command: docker compose exec -u www-data nextcloud php occ maintenance:mode --on, then --off when done. [2][23][24]
  • To restore: drop and recreate the nextcloud database, load the dump, put back both volumes and start the same image tag. If the backup is older than what the sync clients hold, run occ maintenance:data-fingerprint so clients send back the newer files instead of deleting them. [24]

Latest release

Newest upstream release
Nextcloud 35.0.1 [33][34]
This profile was checked against

Nextcloud 35.0.1

This profile was checked against the newest release.

Checked on
14 Oct 2026
State
Checked within the last 90 days
Where releases are published
Docker Hub tags

Latest releases of every app

Version

Profile status
Published
Checked against release
Nextcloud 35.0.1
Profile version
1.0.0
Figures verified
14 Oct 2026
Catalog release
2026.10.10
Sizing policy
2026.10.0
Compose file
Unverified
Official site
nextcloud.com

Sources

  1. Docker Docs: Control startup order in Compose (pg_isready healthcheck, service_healthy) (Official docs · read 11 Oct 2026)
  2. nextcloud/docker README: volumes, auto configuration (POSTGRES_*, NEXTCLOUD_ADMIN_*, NEXTCLOUD_DATA_DIR, NEXTCLOUD_TRUSTED_DOMAINS, NEXTCLOUD_UPDATE), Redis, proxy, upgrades (Official docs · read 14 Oct 2026)
  3. nextcloud/docker .examples insecure/postgres/apache compose.yaml (postgres, redis, nextcloud:apache on 127.0.0.1:8080:80, cron service running /cron.sh on the same html volume) (Official Compose · read 14 Oct 2026)
  4. nextcloud/docker 35/apache Dockerfile (php:8.5-apache-trixie, 35.0.1, crontab */5 cron.php, remoteip X-Real-IP from private ranges, /var/www/data, VOLUME /var/www/html, no HEALTHCHECK) (Official repository · read 14 Oct 2026)
  5. nextcloud/docker 35/apache entrypoint.sh (install/upgrade only for apache/php-fpm or NEXTCLOUD_UPDATE=1; one major at a time; no downgrade; APACHE_DISABLE_REWRITE_IP only for apache commands) (Official repository · read 14 Oct 2026)
  6. nextcloud/docker 35/apache cron.sh (exec busybox crond -f -L /dev/stdout) (Official repository · read 14 Oct 2026)
  7. nextcloud/docker 35/apache config/redis.config.php (REDIS_HOST sets memcache.distributed and memcache.locking to Redis) (Official repository · read 14 Oct 2026)
  8. nextcloud/docker 35/apache config/reverse-proxy.config.php (OVERWRITEHOST, OVERWRITEPROTOCOL, OVERWRITECLIURL, TRUSTED_PROXIES read at runtime) (Official repository · read 14 Oct 2026)
  9. nextcloud/docker .examples README: the cron example runs cron inside the app container (no extra container); it must run as root (Official docs · read 14 Oct 2026)
  10. nextcloud/docker .examples/dockerfiles/cron/apache supervisord.conf (apache2-foreground and /cron.sh in one container) (Official repository · read 14 Oct 2026)
  11. nextcloud/server v35.0.1 lib/OC.php (untrusted Host: 400, also on status.php; CLI exempt) (Official repository · read 14 Oct 2026)
  12. nextcloud/server v35.0.1 lib/private/Setup.php (first trusted domain = the install request host; localhost for occ) (Official repository · read 14 Oct 2026)
  13. nextcloud/server v35.0.1 Request.php (client IP from X-Forwarded-For only behind trusted_proxies; overwritehost for trusted proxies) (Official repository · read 14 Oct 2026)
  14. nextcloud/all-in-one readme (mastercontainer mounts /var/run/docker.sock to manage the other containers) (Official docs · read 14 Oct 2026)
  15. Nextcloud 35 Admin Manual: System requirements (PostgreSQL 14–18, 18 recommended; PHP 8.5 recommended; min 128 MB, recommended 512 MB RAM per process) (Official docs · read 14 Oct 2026)
  16. Nextcloud 35 Admin Manual: Server tuning (typical PHP worker 50–100 MB; 2 GB for PHP ≈ 30 workers; clients poll every 30 s; Redis file locking relieves the DB) (Official docs · read 14 Oct 2026)
  17. Nextcloud 35 Admin Manual: Memory caching (APCu local, Redis 4.0+ distributed and locking) (Official docs · read 14 Oct 2026)
  18. Nextcloud 35 Admin Manual: Transactional file locking (database by default, significant DB load; Redis recommended; Memcached unsuitable) (Official docs · read 14 Oct 2026)
  19. Nextcloud 35 Admin Manual: Background jobs (AJAX default and least reliable; Webcron 1 job per call; cron every 5 minutes recommended and switches the mode itself) (Official docs · read 14 Oct 2026)
  20. Nextcloud 35 Admin Manual: Reverse proxy (trusted_proxies, X-Forwarded-For, overwrite parameters, CalDAV/CardDAV .well-known redirects in the proxy, Caddy example) (Official docs · read 14 Oct 2026)
  21. Nextcloud 35 Admin Manual: Brute force protection (on by default, per client IP, depends on trusted_proxies behind a proxy) (Official docs · read 14 Oct 2026)
  22. Nextcloud 35 Admin Manual: Hardening and security guidance (data directory outside the web root, HTTPS only, HSTS) (Official docs · read 14 Oct 2026)
  23. Nextcloud 35 Admin Manual: Backup (maintenance mode; config, custom apps, data and theme folders; pg_dump) (Official docs · read 14 Oct 2026)
  24. Nextcloud 35 Admin Manual: Restoring backup (config, data and database all required; drop and recreate the DB; maintenance:data-fingerprint) (Official docs · read 14 Oct 2026)
  25. Nextcloud 35 Admin Manual: How to upgrade (latest point release first, no skipped majors, run cron 2–3 times between majors, no downgrade, db:add-missing-indices) (Official docs · read 14 Oct 2026)
  26. Nextcloud 35 Admin Manual: Upgrade to Nextcloud 35 (PHP 8.2 dropped; MariaDB 10.11 and MySQL 8.4 minimum) (Release notes · read 14 Oct 2026)
  27. Nextcloud 35 Admin Manual: Upgrade to Nextcloud 33 (PostgreSQL 13 dropped; MP3 cover previews off; Snowflake IDs) (Release notes · read 14 Oct 2026)
  28. Nextcloud 35 Admin Manual: Uploading big files > 512MB (sync clients upload in chunks; Apache LimitRequestBody 1 GiB caps non-chunking clients) (Official docs · read 14 Oct 2026)
  29. Nextcloud 35 Admin Manual: Configuration parameters (trash bin and versions retention auto, activity_expire_days 365, log_rotate_size 100 MiB, dbpersistent off) (Official docs · read 14 Oct 2026)
  30. nextcloud/server v35.0.1 Setup/PostgreSQL.php (a role-creating DB user makes Nextcloud create oc_admin with a generated password stored in config.php) (Official repository · read 14 Oct 2026)
  31. nextcloud/server v35.0.1 CronService.php (skips while in maintenance mode; a CLI run sets backgroundjobs_mode to cron; web calls run one job) (Official repository · read 14 Oct 2026)
  32. nextcloud/server v35.0.1 OC_Util.php (data directory permissions set to 0770 by Nextcloud itself) (Official repository · read 14 Oct 2026)
  33. Nextcloud changelog (35.0.1 of September 24, 2026 is the latest Nextcloud 35 release; 34.0.4 and 33.0.9 maintained) (Release notes · read 14 Oct 2026)
  34. Docker Hub: library/nextcloud tags (35.0.1-apache = 35.0.1 = latest on 2026-10-14; stable/production = 34.0.4) (Official repository · read 14 Oct 2026)
  35. Docker Hub tag nextcloud:35.0.1-apache (linux/amd64): 515,605,043 B compressed; 22 layers decompressed and counted: 1,513,370,624 B (code layer 816,867,328 B) (Measurement · read 14 Oct 2026)
  36. Docker: containerd image store is the default on fresh Engine 29+ installs and keeps images compressed and uncompressed (Official docs · read 14 Oct 2026)
  37. docker-library/php: 8.5 trixie apache Dockerfile (curl installed, www-data, mpm_prefork, STOPSIGNAL SIGWINCH, EXPOSE 80) (Official repository · read 14 Oct 2026)
  38. redis/docker-library-redis v8.10.2: debian Dockerfile (redis uid/gid 999, WORKDIR /data, EXPOSE 6379, no VOLUME) (Official repository · read 14 Oct 2026)
  39. redis/docker-library-redis v8.10.2: debian docker-entrypoint.sh (fixes ownership, then setpriv to redis) (Official repository · read 14 Oct 2026)
  40. Docker Hub tag redis:8.10.2 (linux/amd64): 55,569,153 B compressed; 7 layers decompressed and counted: 148,460,032 B (Measurement · read 14 Oct 2026)
  41. docker-library/postgres: 18/trixie Dockerfile (postgres uid/gid 999, VOLUME /var/lib/postgresql) (Official repository · read 14 Oct 2026)
  42. docker-library/postgres: 18/trixie docker-entrypoint.sh (chown PGDATA, then gosu postgres) (Official repository · read 14 Oct 2026)
  43. PostgreSQL 18 documentation: 19.4 Resource Consumption (Official docs · read 10 Oct 2026)
  44. PostgreSQL 18 documentation: 19.3 Connections and Authentication (Official docs · read 10 Oct 2026)
  45. PostgreSQL 18 documentation: 19.10 Vacuuming (autovacuum settings) (Official docs · read 10 Oct 2026)
  46. PostgreSQL 18 documentation: 19.5 Write Ahead Log (max_wal_size) (Official docs · read 10 Oct 2026)
  47. PostgreSQL 18 documentation: 51.2 How Connections Are Established (Official docs · read 10 Oct 2026)
  48. Docker Official Image postgres: documentation (docker-library/docs) (Official docs · read 10 Oct 2026)
  49. Docker Hub: library/postgres tag 18.6 (compressed image sizes) (Official repository · read 10 Oct 2026)

All self-hosted apps