On this page (12)
  1. Side-by-side measured table
  2. Test method
  3. Which ownCloud: Infinite Scale, not Classic
  4. Features compared (researched)
  5. When to pick Nextcloud
  6. When to pick Seafile
  7. When to pick ownCloud Infinite Scale
  8. Syncthing, if you do not need a server
  9. Migration notes
  10. Compose files
  11. What we did not test
  12. Related

Nextcloud vs ownCloud vs Seafile comes down to scope and RAM. Pick Nextcloud for files plus calendar, contacts and online office: 297 MiB idle for the file server alone. Pick Seafile if files are the whole job: 616 MiB idle, 905 MiB peak. Pick ownCloud Infinite Scale for the smallest measured footprint: one container, 151 MiB idle (range 101 to 155, noisy), with fewer features (researched, not tested). Our sizing rule gives 1 GB, 2 GB and 1 GB for a one-user test of 103 files. Treat those as floors: ownCloud’s own documents call 4 GB a good production starting point, and Seafile’s call for 2G. We tested Infinite Scale, not ownCloud Classic.

The lab ran each app as a single user on a clean install. Nextcloud’s run (35.0.2) is from Oct 18, 2026 on an AMD EPYC 7763; Seafile and Infinite Scale ran on Oct 16 in separate jobs on EPYC 9V45. RAM and image sizes carry across hosts, timing rows do not. Seafile took its native upload API, the other two WebDAV, so the upload times are not ranked. We did not test sync clients, search, previews, office editing, LDAP or SSO, more than one user, or Arm hardware.

Measured readings

Test box: Nextcloud 35.0.2

Measured in our lab on : 3 full runs, each from a fresh stack. Each figure is the median, with the range over the runs under it. The numbers come from the raw result file.

Idle RAM
297 MiBrange 295–301 · 3 runs all containers, median of 3 runs; each run is the mean over 30 s after the stack settled
Startup peak RAM
302 MiBrange 295–302 · 3 runs highest total between healthy and settled
Peak RAM
452 MiBrange 402–479 · 3 runs under load, median of the run peaks
Settled after
190 srange 187–217 · 3 runs after the first healthy response
Idle CPU
2.5 %range 1.8–2.6 · 3 runs of one core, lab host
Startup
27 ssame when rounded in all 3 runs to first healthy response
App version
35.0.2
Tested
, 3 runs (compose file verified the same day)
How the figures are made
Each run starts a fresh stack and goes through setup, settling, the idle window and the load step. We publish the median over the runs and the lowest and highest value, because the lab host and some apps vary from run to run. Runs, median and range
Lab host
AMD EPYC 7763 64-Core Processor, 2 cores, 7.8 GiB RAM, x86_64.Ubuntu 24.04.5 LTS, Docker 28.0.4.
Disk for the images
About 2.9 GB with the containerd image store, the default on fresh installs of Docker Engine 29 and later (our estimate: unpacked plus compressed size, plus 10%; not measured on a containerd host). About 1.9 GB with the older overlay2 store (the unpacked column, as measured on this lab host). Plan for the larger figure. How we size disk
How idle was measured
After the stack was healthy and set up, we sampled total RAM until it stayed within max(2% of its mean, 10 MiB) over 60 s (at least 120 s, at most 600 s), then measured idle over the next 30 s. Rule in full
Peak RAM measured
Under load. One user (the admin), over plain HTTP on the Compose network, one request at a time. A Python script generates 103 random files (100 small ones of 1 KB to 1 MB, about 50 MB together, and three of 50 MB), uploads them over WebDAV (MKCOL, then one PUT per file), lists the folder with PROPFIND, and downloads five files (three small, two large) and checks their SHA-256. About 200 MB in total. No browser, no sync client, no chunked upload, no previews, no sharing. `occ files:scan` is not part of this load (the harness cannot run commands inside the stack); it was run by hand, see the article.
Per-container figures for Nextcloud: median over 3 runs, with the range
ContainerIdle RAMPeak RAM (under load)Image, compressed (download)Image, unpacked (disk, overlay2 store)
app204 MiBrange 204–211 · 3 runs309 MiBrange 308–317 · 3 runs517 MB1.5 GB
cron34 MiBsame when rounded in all 3 runs147 MiBrange 34–167 · 3 runs517 MB (same image as app)1.5 GB (same image as app)
db46 MiBsame when rounded in all 3 runs51 MiBrange 49–51 · 3 runs120 MB304 MB
redis10 MiBrange 10–12 · 3 runs11 MiBrange 11–13 · 3 runs39 MB119 MB
Total297 MiBrange 295–301 · 3 runs452 MiBrange 402–479 · 3 runs676 MB1.9 GB
Every run (3)
Total RAM, startup and CPU model of each run of Nextcloud
RunIdle RAMPeak RAMStartup peakStartupLab host CPU
1301 MiB402 MiB302 MiB27 sAMD EPYC 7763 64-Core Processor
2295 MiB452 MiB295 MiB27 sAMD EPYC 7763 64-Core Processor
3 (closest to median idle)297 MiB479 MiB302 MiB27 sAMD EPYC 7763 64-Core Processor
Total RAM after the stack became healthy (10 s averages, run 3 of 3)
Total RAM across all containers in 10 s averages, from the moment the stack was healthy until the end of the idle window (220 s). Run 3 of 3, the one closest to the median idle. Highest 10 s average 298 MiB at 150 s, last 297 MiB at 220 s. Dashed line: the stack counted as settled at 187 s.

0 s to 220 s after healthy; the line spans 0 to 298 MiB. Dashed line: settled.

Timeline as a table
Total RAM, 10 s average ending at each time, every 30 s after healthy
Seconds after healthyTotal RAM
30260 MiB
60256 MiB
90258 MiB
120259 MiB
150298 MiB
180297 MiB
210297 MiB
220297 MiB

RAM is MiB (220 bytes); image sizes are MB (106 bytes). The unpacked column is what our lab host's Docker reported; see Disk for the images for other setups. Per-container peaks happen at different moments, so they do not add up to the total peak. Medians of separate columns need not add up either.

Lab notes (3)
  • Image: the official `nextcloud` apache variant. The `cron` service is the same image started with /cron.sh: two containers in memory, one image on disk.
  • The first install is automatic (database and admin variables in compose.yaml), so there is no web wizard and no installed apps beyond the image's defaults.
  • Periodic job: service cron runs a scheduled job every 300 s on the wall-clock grid. After the settle rule is met, the idle window starts only once the job has ticked at least once since the stack became healthy and the last tick is 60 s old (extra wait capped at 360 s), so idle reflects a stack after one run of the job. The wait is part of settle_seconds_used; runs[].periodic has the tick times (computed from the clock, not read from the job).

Measured readings

Test box: Seafile 13.0.28

Measured in our lab on : 3 full runs, each from a fresh stack. Each figure is the median, with the range over the runs under it. The numbers come from the raw result file.

Idle RAM
616 MiBrange 590–759 · 3 runs all containers, median of 3 runs; each run is the mean over 30 s after the stack settled
Startup peak RAM
620 MiBrange 590–761 · 3 runs highest total between healthy and settled
Peak RAM
905 MiBrange 876–911 · 3 runs under load, median of the run peaks
Settled after
125 srange 124–128 · 3 runs after the first healthy response
Idle CPU
1.8 %range 1.5–1.9 · 3 runs of one core, lab host
Startup
18 ssame when rounded in all 3 runs to first healthy response
App version
13.0.28
Tested
, 3 runs (compose file verified the same day)
How the figures are made
Each run starts a fresh stack and goes through setup, settling, the idle window and the load step. We publish the median over the runs and the lowest and highest value, because the lab host and some apps vary from run to run. Runs, median and range
Lab host
AMD EPYC 9V45 96-Core Processor, 2 cores, 7.8 GiB RAM, x86_64.Ubuntu 24.04.5 LTS, Docker 28.0.4.
Disk for the images
About 3.2 GB with the containerd image store, the default on fresh installs of Docker Engine 29 and later (our estimate: unpacked plus compressed size, plus 10%; not measured on a containerd host). About 2.1 GB with the older overlay2 store (the unpacked column, as measured on this lab host). Plan for the larger figure. How we size disk
How idle was measured
After the stack was healthy and set up, we sampled total RAM until it stayed within max(2% of its mean, 10 MiB) over 60 s (at least 120 s, at most 600 s), then measured idle over the next 30 s. Rule in full
Peak RAM measured
Under load. The same load as the Nextcloud and ownCloud tests, through Seafile's own Web API. One user (the admin), over plain HTTP on the Compose network, one request at a time, each on a new connection. A Python script generates the same 103 random files (100 small ones of 1 KB to 1 MB, about 50 MB together, and three of 50 MB; same seed, same names, same order), creates a folder in the library, asks for one upload address for that folder (GET upload-link) and uploads the files to it with one multipart POST each, lists the folder with one GET of the directory, and downloads five files (three small, two large; one request for the download address and one for the file each) and checks their SHA-256. About 200 MB in total. The web API is used instead of WebDAV because it is what Seafile's web interface, mobile apps and scripts use; WebDAV is a separate, optional component that is off by default in Seafile 13. No browser, no sync client (Seafile's desktop client uses its own block-based sync protocol, which is not exercised), no chunked upload, no thumbnails, no sharing.
Per-container figures for Seafile: median over 3 runs, with the range
ContainerIdle RAMPeak RAM (under load)Image, compressed (download)Image, unpacked (disk, overlay2 store)
db133 MiBrange 132–133 · 3 runs134 MiBsame when rounded in all 3 runs104 MB327 MB
redis9 MiBsame when rounded in all 3 runs9 MiBsame when rounded in all 3 runs56 MB146 MB
seafile475 MiBrange 449–617 · 3 runs762 MiBrange 734–769 · 3 runs560 MB1.6 GB
Total616 MiBrange 590–759 · 3 runs905 MiBrange 876–911 · 3 runs720 MB2.1 GB
Every run (3)
Total RAM, startup and CPU model of each run of Seafile
RunIdle RAMPeak RAMStartup peakStartupLab host CPU
1759 MiB911 MiB761 MiB18 sAMD EPYC 9V45 96-Core Processor
2 (closest to median idle)616 MiB905 MiB620 MiB18 sAMD EPYC 9V45 96-Core Processor
3590 MiB876 MiB590 MiB18 sAMD EPYC 9V45 96-Core Processor
Total RAM after the stack became healthy (10 s averages, run 2 of 3)
Total RAM across all containers in 10 s averages, from the moment the stack was healthy until the end of the idle window (160 s). Run 2 of 3, the one closest to the median idle. Highest 10 s average 617 MiB at 160 s, last 617 MiB at 160 s. Dashed line: the stack counted as settled at 125 s.

0 s to 160 s after healthy; the line spans 0 to 617 MiB. Dashed line: settled.

Timeline as a table
Total RAM, 10 s average ending at each time, every 30 s after healthy
Seconds after healthyTotal RAM
30613 MiB
60613 MiB
90614 MiB
120616 MiB
150616 MiB
160617 MiB

RAM is MiB (220 bytes); image sizes are MB (106 bytes). The unpacked column is what our lab host's Docker reported; see Disk for the images for other setups. Per-container peaks happen at different moments, so they do not add up to the total peak. Medians of separate columns need not add up either.

Lab notes (6)
  • Host: a GitHub Actions runner (ubuntu-latest, x86_64, 2 vCPU, 8 GB RAM; the CPU model varies between runners and each run records its own). Numbers are valid for that host only.
  • Image: seafileltd/seafile-mc:13.0.28, Seafile Community Edition 13.0.28 (18 Sep 2026), the newest release Seafile's own changelog (plus.seafile.com/wiki/publish/seafile-wiki/5L80/) does not label beta. 14.0.9 (14 Oct 2026) is labelled beta there and is not tested. The image's version label says 24.04 (the Ubuntu base), so the version is read from the running server (GET /api2/server-info/).
  • Companions (Seafile 13 official Docker file): MariaDB 10.11 and Redis, in their own containers. Memcached is optional since 13 and not used. Caddy (reverse proxy), SeaDoc (online documents), the notification server, the metadata server, Seafile AI, the thumbnail server and WebDAV are not run. The container count is three, against four for Nextcloud (app, cron, PostgreSQL, Redis) and one for ownCloud Infinite Scale.
  • Measured: idle RAM and CPU after the first start with the admin account and one empty library; RAM and CPU while the load of load.description runs (a few seconds); image sizes; start-up time. Not measured: the desktop or mobile sync clients, external storage or S3 backends, online editing (SeaDoc, OnlyOffice, Collabora), full-text search, previews, LDAP/SSO, many users, long-term growth.
  • Equivalence with the Nextcloud test: same 103 files (same generator and seed), same order, one request at a time, one user, plain HTTP, 5 downloads with a SHA-256 check. Differences that come from the products: Seafile needs one request for an upload address (reused for every file) and one per download address; Nextcloud's PROPFIND also returns the folder itself, Seafile's listing returns files only, so `listing_entries` is 103 for both. The Nextcloud result calls the listing `propfind_entries` and `propfind_seconds`.
  • The load script reports every request kind with the HTTP statuses it got (`requests` in the load result); any failed request fails the run.

Measured readings

Test box: ownCloud Infinite Scale 8.2.1

Measured in our lab on : 3 full runs, each from a fresh stack. Each figure is the median, with the range over the runs under it. The numbers come from the raw result file.

Idle RAM
151 MiBrange 101–155 · 3 runs all containers, median of 3 runs; each run is the mean over 30 s after the stack settled
Startup peak RAM
282 MiBrange 252–323 · 3 runs highest total between healthy and settled
Peak RAM
305 MiBrange 304–309 · 3 runs under load, median of the run peaks
Settled after
181 ssame when rounded in all 3 runs after the first healthy response
Idle CPU
0.8 %range 0.6–1.0 · 3 runs of one core, lab host
Startup
5.4 srange 5.4–5.5 · 3 runs to first healthy response

Varies between runs. The highest run was more than 1.5 times the lowest: idle RAM was 155 MiB, 151 MiB, 101 MiB in runs 1 to 3. The figures above are the median; plan for the top of the range. Each run was the same stack and version started fresh, so the spread comes from the app or the lab host.

App version
8.2.1
Tested
, 3 runs (compose file verified the same day)
How the figures are made
Each run starts a fresh stack and goes through setup, settling, the idle window and the load step. We publish the median over the runs and the lowest and highest value, because the lab host and some apps vary from run to run. Runs, median and range
Lab host
AMD EPYC 9V45 96-Core Processor, 2 cores, 7.8 GiB RAM, x86_64.Ubuntu 24.04.5 LTS, Docker 28.0.4.
Disk for the images
About 359 MB with the containerd image store, the default on fresh installs of Docker Engine 29 and later (our estimate: unpacked plus compressed size, plus 10%; not measured on a containerd host). About 238 MB with the older overlay2 store (the unpacked column, as measured on this lab host). Plan for the larger figure. How we size disk
How idle was measured
After the stack was healthy and set up, we sampled total RAM until it stayed within max(2% of its mean, 10 MiB) over 60 s (at least 120 s, at most 600 s), then measured idle over the next 30 s. Rule in full
Peak RAM measured
Under load. The same load as the Nextcloud and Seafile tests, over WebDAV. One user (the admin), over HTTPS with a self-signed certificate on the Compose network (not verified), basic authentication, one request at a time, each on a new connection. A Python script generates the same 103 random files (100 small ones of 1 KB to 1 MB, about 50 MB together, and three of 50 MB; same seed, same names, same order), uploads them to a folder in the admin's personal space (MKCOL, then one PUT per file), lists the folder with PROPFIND (Depth 1), and downloads five files (three small, two large) and checks their SHA-256. About 200 MB in total. The address is /dav/spaces/<space id>, the form the official desktop and mobile apps use (Nextcloud's test uses /remote.php/dav/files/admin). No browser, no sync client, no chunked (TUS) upload, no thumbnails, no sharing, no search.
Per-container figures for ownCloud Infinite Scale: median over 3 runs, with the range
ContainerIdle RAMPeak RAM (under load)Image, compressed (download)Image, unpacked (disk, overlay2 store)
ocis151 MiBrange 101–155 · 3 runs305 MiBrange 304–309 · 3 runs88 MB238 MB
Every run (3)
Total RAM, startup and CPU model of each run of ownCloud Infinite Scale
RunIdle RAMPeak RAMStartup peakStartupLab host CPU
1155 MiB305 MiB252 MiB5.4 sAMD EPYC 9V45 96-Core Processor
2 (closest to median idle)151 MiB309 MiB282 MiB5.5 sAMD EPYC 9V45 96-Core Processor
3101 MiB304 MiB323 MiB5.4 sAMD EPYC 9V45 96-Core Processor
Total RAM after the stack became healthy (10 s averages, run 2 of 3)
Total RAM across all containers in 10 s averages, from the moment the stack was healthy until the end of the idle window (220 s). Run 2 of 3, the one closest to the median idle. Highest 10 s average 282 MiB at 120 s, last 152 MiB at 220 s. Dashed line: the stack counted as settled at 181 s.

0 s to 220 s after healthy; the line spans 0 to 282 MiB. Dashed line: settled.

Timeline as a table
Total RAM, 10 s average ending at each time, every 30 s after healthy
Seconds after healthyTotal RAM
30271 MiB
60272 MiB
90276 MiB
120282 MiB
150151 MiB
180153 MiB
210151 MiB
220152 MiB

RAM is MiB (220 bytes); image sizes are MB (106 bytes). The unpacked column is what our lab host's Docker reported; see Disk for the images for other setups. Per-container peaks happen at different moments, so they do not add up to the total peak. Medians of separate columns need not add up either.

Lab notes (9)
  • Warning: max/min across runs is above 1.5 for idle_mem_mib: the app is bimodal or the host is noisy. The published figure is the median; read it together with the range.
  • Host: a GitHub Actions runner (ubuntu-latest, x86_64, 2 vCPU, 8 GB RAM; the CPU model varies between runners and each run records its own). Numbers are valid for that host only.
  • Which ownCloud: ownCloud Infinite Scale (oCIS), image owncloud/ocis:8.2.1 (GitHub release v8.2.1, marked Latest, 2 Oct 2026; Docker Hub tag rebuilt 12 Oct 2026). owncloud.com/download-server calls Infinite Scale 'Our Flagship Product' and 'ownCloud's modern successor to the old PHP monolith (ownCloud 10 / oC10)'. The classic PHP server (owncloud/server 10.16.x and 11.0.x) is not tested; see lab/notes/owncloud-flavour-2026-10-16.md for the evidence.
  • Infinite Scale is one container with no separate database or cache: users, metadata and the search index live in its two volumes. The container count is one, against four for Nextcloud and three for Seafile, so compare the total, not the container.
  • TLS: oCIS serves HTTPS on port 9200 with a self-signed certificate it generates (default, as in ownCloud's evaluation guide). OCIS_INSECURE=true lets its services accept that certificate, and the load scripts do not verify it. A reader behind a reverse proxy with a real certificate would not need either.
  • Basic authentication (PROXY_ENABLE_BASIC_AUTH=true) is on so a script can use WebDAV without an OpenID Connect login; ownCloud describes it as 'not recommended' and the web interface and apps do not need it. It is in the published compose too.
  • Measured: idle RAM and CPU after the first start with the admin account; RAM and CPU while the load of load.description runs (a few seconds); image size; start-up time. Not measured: the desktop or mobile sync clients, external storage or S3 backends, online editing (Collabora, ONLYOFFICE), Tika full-text search, antivirus, previews, Keycloak/LDAP, many users, background work after the script ends (search indexing), long-term growth.
  • Equivalence with the Nextcloud test: same 103 files (same generator and seed), same order, same request kinds (MKCOL, 103 PUT, PROPFIND Depth 1, 5 GET), one request at a time, one user. Differences: HTTPS instead of HTTP, the /dav/spaces/<id> address, and PROPFIND on oCIS returns 104 entries as on Nextcloud (folder plus 103 files); `listing_entries` counts the files (103). The Nextcloud result calls the listing `propfind_entries` and `propfind_seconds`.
  • The load script reports every request kind with the HTTP statuses it got (`requests` in the load result); any failed request fails the run.

Side-by-side measured table

Source for every row marked Tested: nextcloud.json (run of Oct 18, 2026), seafile.json and owncloud.json (runs of Oct 16, 2026). Each figure is the median of three runs, with the lowest to highest run in brackets. Each app had its own GitHub Actions job (2 vCPU, 7.8 GiB RAM, Ubuntu 24.04.5, Docker 28.0.4, overlay2 image store), and all three runs of an app landed on one CPU model, shown in the first row. RAM is Docker’s working set. Idle is the mean of at least 10 samples over 30 s after the stack’s total memory had settled (how we measure idle RAM).

Row Nextcloud 35.0.2 Seafile 13.0.28 ownCloud Infinite Scale 8.2.1 Source
Test date Oct 18, 2026 Oct 16, 2026 Oct 16, 2026 Tested
Lab host CPU (2 vCPU) AMD EPYC 7763 AMD EPYC 9V45 AMD EPYC 9V45 Tested
Containers 4: app, cron, PostgreSQL 18.6, Redis 8.10.2 3: Seafile, MariaDB 10.11.19, Redis 8.10.2 1 Tested
Idle RAM, whole stack, MiB 296.93 (294.95 to 301.33) 616.28 (590.22 to 758.82) 151.47 (101.46 to 155.41) Tested
Startup peak RAM, whole stack, MiB (healthy to settled) 301.63 (295.39 to 302.46) 620.10 (590.33 to 760.89) 281.80 (252.40 to 322.70) Tested
Peak RAM under the upload load, whole stack, MiB 451.78 (401.61 to 478.96) 904.61 (876.15 to 911.35) 305.30 (304.30 to 309.30) Tested
Highest run reading used for sizing, MiB 478.96 911.35 322.70 Tested
Recommended RAM by our sizing rule (one user, 103 files) 1 GB 2 GB 1 GB Tested, rule applied
RAM in the project’s own documents (details below) 512MB recommended per process 2G 4GB “a good starting point” for production Researched
Images to download, compressed, MB 676.4 720.0 87.5 Tested
Images unpacked (overlay2), MB 1,903 2,123 238 Tested
Disk for images, containerd-store estimate, MB 2,900 3,200 359 Tested, rule applied
Idle CPU, % of one core, lab host 2.52 (1.77 to 2.58) 1.81 (1.52 to 1.91) 0.85 (0.58 to 1.00) Tested
Healthy after docker compose up, s, lab host 26.8 (26.8 to 26.9) 17.5 (17.5 to 17.6) 5.4 (5.4 to 5.5) Tested

The medians and ranges in this table, and the sizing arithmetic, come from a script over the three result files. Its output for Seafile and Infinite Scale is saved in lab/notes/filesync-2026-10-16.md (its Nextcloud section is the Oct 8 run); the Nextcloud column is a script over the Oct 18 file, saved in lab/notes/nextcloud-2026-10-18.md. Notes on reading it.

  • Nextcloud’s idle is measured after cron’s first run, and its peak depends on a cron burst. This page first said 299 MiB idle and 454 MiB peak (35.0.1, run of Oct 8), then 265 and 367 (35.0.2, run of Oct 17); the run of Oct 18 gives 297 and 452. The Oct 17 idle figure was taken before the cron container’s first background run in two of its three runs, when cron held 0.6 MiB; after that run it held about 34 MiB in 6 of the 7 runs we measured after a first run (1.0 MiB in the seventh). The lab now waits for that first run before it measures idle (methodology, 2026-10-18), and memory.stat shows the 34 MiB is anonymous memory, not file cache. app, db and redis together were the same in all three batches (262.5, 264.2 and 264.7 MiB idle). The peak depends on whether a cron burst of 147 to 182 MiB lands inside the upload: two of the three runs on Oct 18 had one and peaked at 452 and 479 MiB, the third peaked at 402 MiB. We do not know what starts the bursts. Single runs across the three batches ranged from 253 to 301 MiB idle and from 362 to 497 MiB peak, so read Nextcloud’s peak as roughly 400 to 500 MiB, and do not read 35.0.2 as using less memory: we did not test that. Details are in the Nextcloud guide.
  • Infinite Scale’s idle figure is noisy: use the range. The three runs idled at 155.41, 151.47 and 101.46 MiB, a ratio of 1.53 against a flag threshold of 1.5, so the result carries a variance flag. In all three runs the stack sat between 213 and 322 MiB for about two minutes after the first healthy check and then dropped in one step, between the 120 s and 140 s marks, to those three levels. We do not know why it drops or why the level differs, because the result holds no per-process data. The lab waited for the total to flatten (about 180 s), so the idle figure is the level after the drop. Anyone sizing for the first two minutes should read the startup peak row.
  • Seafile’s idle figure spreads too, below the flag. The runs idled at 758.82, 616.28 and 590.22 MiB (ratio 1.29). The difference sits in the Seafile container (617, 475 and 449 MiB); MariaDB held 132 MiB and Redis 9 MiB in every run. We did not look for the cause.
  • Peaks rest on few samples, and unevenly. The peak is the highest sample while the upload script ran, sampled every 2 to 3 seconds. The Nextcloud load lasted about 36 s (19 to 21 samples), Infinite Scale’s about 9 s (6 to 7) and Seafile’s about 4 s (4). A spike shorter than the sample interval is missed, and a short window gives it fewer chances, so the Seafile and Infinite Scale peaks are the less certain ones.
  • By our sizing rule (the highest reading in any run, times 1.5, rounded up to 1, 2, 4, 8, 16 or 32 GB; how we size): Nextcloud 479.0 MiB (the peak under load in run 3, with a cron burst in it) gives 1 GB, Seafile 911.4 MiB gives 2 GB (1.34 GiB needed), and Infinite Scale 322.7 MiB (a startup peak in run 3) gives 1 GB. No one in the lab used a sync client, an office server or more than one user, so these are floors for a one-user setup, not for a team.
  • Disk for images uses the site’s rule: unpacked plus compressed size, plus 10%, rounded up, for a fresh Docker 29 or later install with the containerd image store (how we size disk). Your files and databases come on top.
  • Start-up times are not the same event. Each is the wall-clock time until that stack’s own health checks passed, and each includes a first-run setup (Nextcloud’s automatic install, Seafile’s database and admin creation, Infinite Scale’s ocis init). The checks themselves differ: Nextcloud’s waits for status.php to report installed, Seafile’s for the web API and the file server, Infinite Scale’s for status.php. They are lab-host figures and we do not rank on them.

What each project’s documents say about RAM

Researched, not tested by us: read from each project’s own documentation on Oct 16, 2026.

Project What the documentation says Source
Nextcloud “a minimum of 128MB RAM per process, and we recommend a minimum of 512MB RAM per process” (system requirements, version 35) Researched
Seafile Community Edition Memory 2G, 2 cores “more than 2G Hz are recommended”, 10G of disk available and more than 50G recommended; extensions the page does not cover, such as OnlyOffice, need more than those figures (system requirements) Researched
ownCloud Infinite Scale A laptop or Raspberry Pi 4 “with a minimum of 512MB of RAM” for simple testing; “at least 4GB of RAM” for “more intense testing”; for production, RAM “depends a lot on the quantity of spaces, the tasks that will run concurrently” and “Using 4GB of RAM is a good starting point” (prerequisites). The production Docker Compose guide, which adds Traefik, Collabora and ONLYOFFICE, says “at minimum 4-6GB of memory” and about 2.4 GB of disk (guide) Researched

Read our sizing tiers next to these, not instead of them. Our test was one user, one 194 MB upload of 103 files and a clean install, so its 1 GB, 2 GB and 1 GB say what that load needs, not what a working server needs. It did not cover search indexing, thumbnails and previews, an office server, sync clients, many users or many spaces, and each of those adds memory. For Infinite Scale, ownCloud’s guidance (4GB to start, 4-6GB with the production example’s other services) is four times our tier, and our 151 MiB idle and 305 MiB peak do not contradict it. We would not run Infinite Scale for real users on 1 GB on the strength of this test. Seafile’s 2G matches our tier, so we would treat it as a minimum. Nextcloud’s 512MB is per process, and the total depends on how many processes run at once, which we did not count.

Upload, list and download timing

The same 103 generated files went to each app: 100 small ones of 1 KB to 1 MB and three of 50 MB, 194,456,599 bytes in all, from one user, one request at a time. Seconds, median of three runs with the range in brackets, lab host only. Source: Tested (nextcloud.json, seafile.json, owncloud.json).

Step Nextcloud (WebDAV, EPYC 7763) Seafile (upload API, EPYC 9V45) Infinite Scale (WebDAV over HTTPS, EPYC 9V45)
Upload of 103 files, s 32.9 (31.7 to 35.4) 1.5 (1.4 to 1.9) 6.8 (6.4 to 7.7)
Listing the folder, s 0.23 (0.23 to 0.25) 0.01 (0.01 to 0.02) 0.05 (0.05 to 0.06)
Download of 5 files (101.5 MB), s 1.7 (1.6 to 1.9) 0.5 (0.5 to 1.0) 0.5 (0.5 to 0.7)
Load window sampled for RAM, s 35.7 (34.0 to 37.7) 4.0 (3.9 to 4.1) 9.4 (8.6 to 10.5)
CPU during the load window, mean, % of one core, lab host 103.98 (89.30 to 108.72) 41.49 (31.49 to 48.49) 99.55 (90.12 to 99.77)
Requests sent 110 (by script design; the result file does not count them) 116 110
Failed requests; downloads matching their SHA-256 none reported; 5 of 5 in all 3 runs 0; 5 of 5 in all 3 runs 0; 5 of 5 in all 3 runs

What the rows say, and what they do not:

  • Every upload in every run succeeded and every downloaded file matched its checksum. Seafile’s script counts 116 requests because it asks for an upload address once and a download address for each of the five files; the other two have no such step.
  • The Nextcloud result file predates the request-count fields, so it reports no failed-request count. Its 103 uploads returned 201, as our Nextcloud guide describes.
  • The Seafile and Infinite Scale rows come from the same CPU model, but still differ in API and transport. The gap between 1.5 and 6.8 s is not a pure comparison of the two servers.
  • The upload script is not a sync client. A desktop client sends changes in its own way, and we did not measure it.

Test method

Same load, three scripts. One generator (the same seed, file names and order) built the 103 files for all three apps; a test in the lab repository fails if the files differ by a byte. Each script created a folder, uploaded the files, listed the folder and downloaded five files (small-000, small-050, small-099, large-0, large-2) and checked their SHA-256. Files were generated before the memory window began. One user (the admin), no browser, no sync client, no chunked upload, no previews, no sharing.

Why Seafile used its upload API. Seafile’s WebDAV server is an optional component and is off by default: the manual says “By default, seafdav is disabled” (WebDAV extension), and the same page recommends the sync client if you want better performance. Seafile’s Web API has a documented call that returns an upload link; the desktop client uses its own protocol, and we found no documented script interface for it. So the lab used the Web API: log in for a token, create a library, request one upload address and reuse it for every file with a multipart POST. That is one request per file, the same shape as one WebDAV PUT, but it is a different code path, and we say so wherever timing appears.

Transport. Nextcloud and Seafile were reached over plain HTTP on the Compose network, with a Host header for their configured names. Infinite Scale serves HTTPS with a self-signed certificate it generates, and the script does not verify it, which adds TLS work to the Infinite Scale rows only (we did not measure how much). Infinite Scale’s WebDAV login used Basic authentication, switched on for the lab (see the Compose section).

What we made equal, and what we did not. Equal: the files, the request order, one request at a time, one admin user, a clean install, the default settle rule (wait until the stack’s total memory is flat to within max(2%, 10 MiB) over 60 s, at least 120 s after setup), three runs from fresh volumes. Not equal: the hosts (see the table), the number of containers, the database (PostgreSQL, MariaDB, none), and everything that comes with each product’s own setup. Seafile ran without Caddy, SeaDoc, its notification and metadata servers, Seafile AI and WebDAV; Infinite Scale ran without Traefik, Collabora, ONLYOFFICE, Tika, ClamAV, Keycloak and a mail server. Nextcloud had no apps beyond the image’s defaults.

Versions. Nextcloud 35.0.2 (Apache image; its changelog dates the release to Oct 15, 2026, read Oct 17), Seafile Community Edition 13.0.28, ownCloud Infinite Scale 8.2.1. Seafile 14.0.9 was out on Oct 14, 2026 but its own changelog labels it “14.0.9 beta” and lists 13.0.28 (Sep 18, 2026) as the newest release without that label, so we tested 13.0.28. Re-test when 14.0 leaves beta. For Nextcloud, the setup, update and restore steps are in the Nextcloud Docker Compose guide; we ran no such steps for the other two.

Which ownCloud: Infinite Scale, not Classic

A search for “nextcloud vs owncloud” can mean two different products. ownCloud Classic is the PHP server (versions 10 and 11) that Nextcloud descends from; Nextcloud’s repository still carries “2013-2016 ownCloud, Inc.” copyright lines. ownCloud Infinite Scale (oCIS) is a separate product, written in Go. We tested Infinite Scale, and our numbers say nothing about Classic.

Why Infinite Scale: ownCloud’s download page labels it “Our Flagship Product” and “ownCloud’s modern successor to the old PHP monolith (ownCloud 10 / oC10)”, read Oct 16, 2026. An ownCloud blog post of Apr 24, 2026 (PHP 8.3: yes for Classic) says “oCIS is the future”, calls Classic “a maintenance commitment” and says “We’re not building major new features on the Classic codebase”; it also says a migrator from Classic to oCIS is “in the pipeline, not shipped yet”. We found no sentence in which ownCloud says “use Infinite Scale for new installs”, so that is our reading of these.

Classic is still released. Docker Hub showed owncloud/server 10.16.6 and 11.0.1 pushed on Oct 15, 2026 (read Oct 16), and ownCloud’s 11.0.0 announcement (Jul 31, 2026) describes eleven security fixes and a PHP 8.3 baseline, with PHP 7.4 installs staying on 10.16.x. If you run Classic today, or follow a tutorial that installs it, you are on the maintenance line. A later lab test of owncloud/server:11.0.1 would complete this page; it has not been done.

Features compared (researched)

We did not test these. Each row is from the project’s own documentation, repository or registry page, read Oct 16, 2026.

Feature Nextcloud 35 Seafile 13 Community Edition ownCloud Infinite Scale 8.2 Source
Server license AGPL-3.0-or-later (README) Server core AGPLv3, Seahub (web interface) Apache 2.0 (manual) Code: Apache 2.0 (repository). Some ownCloud GmbH builds are also under an end-user license agreement; see “Infinite Scale license” below the table Researched
Calendar and contacts A Calendar and Contacts server (CalDAV and CardDAV); the Calendar app “comes installed with Nextcloud Hub by default, but can be disabled” (groupware, calendar) No calendar or contacts section in the manual’s contents The oCIS 8.2 documentation we read does not list CalDAV, CardDAV, a calendar or a contacts service: not on the architecture or prerequisites pages, and not in the services list. That is an absence in the pages we read, not a statement from ownCloud, and we did not check release notes or the web interface Researched
Online office Nextcloud Office (powered by Euro-Office), which “Requires a Euro-Office Document Server”, or Collabora Online, “as a self-hosted server or as a built-in app” (office docs) OnlyOffice integration with its own setup page (OnlyOffice); SeaDoc for lightweight documents (manual) Integrates Collabora Online, OnlyOffice Docs or Microsoft Office Online Server through a WOPI gateway (README) Researched
Apps and extensions An App Store with Calendar, Contacts, Talk, Deck, Notes and Nextcloud Office in its listing Integrations are listed in the manual (OnlyOffice, SeaDoc, SeaSearch); we found no app store ownCloud Web can be extended with apps, such as file editors, that are “installed in an ownCloud Infinite Scale instance” (extension system); we found no marketplace in the 8.2 documentation Researched
How files are stored Files in each user’s folder, metadata in a database (MariaDB, PostgreSQL or, for testing and minimal instances, SQLite, per the requirements) A Git-like model of libraries, commits and file blocks; files are cut into variable-length blocks of about 8 MB on average, which the manual says “makes it possible to deduplicate data between different versions” (data model) Storage “spaces” with their own roles; no relational database is listed in the prerequisites, and metadata is kept in MessagePack files on a POSIX filesystem (architecture, prerequisites) Researched
Process design PHP application (requirements); in the lab, app and cron containers plus PostgreSQL and Redis File server and web interface (Seahub) in one container, plus MariaDB and Redis (container counts from the lab’s compose file) “uses a single binary, which starts the contained Infinite Scale services with a single command”; by default all services run “in a single process” (architecture) Container counts Tested, the rest Researched
Paid editions Nextcloud Enterprise exists (linked from the README) Several features carry “(Pro)” in the manual’s contents: cluster installation, virus scan, SeaSearch, advanced user management Not checked for Infinite Scale Researched
Arm images Not checked seafile-mc supports x86 and Arm (architecture) Docker on AMD64 and ARM64 (prerequisites) Researched

Three things the table does not settle. First, “no calendar section in the manual” is an absence we saw in the contents, not a statement by Seafile that it has none. Second, the license rows are the projects’ words and are not legal advice. Third, we ran none of the sync clients, so we cannot say how any of these designs behaves when files change on a laptop.

Infinite Scale license

Researched, read Oct 16, 2026. The Infinite Scale source is Apache 2.0, and the oCIS README has a separate section that says: “Some builds of stable ownCloud Infinite Scale releases provided by ownCloud GmbH are subject to an End User License Agreement.” The agreement defines the covered software as ownCloud Infinite Scale “packaged and distributed by licensor in form of (but not limited to) zip-archives, tarballs, virtual images, software containers or the like formats”. It grants “Private Use” (an individual, family and friends, including “testing, evaluation or development purposes”) and “Productive Use” (an organization’s “productive day to day business”). It also says “You must not install and use ownCloud Infinite Scale for Commercial Use”, and defines that as corporate use for commercial advantage, “including but not limited to e.g. offering ownCloud Infinite Scale based software-as-a-service (SaaS), platform-as-a-service (PaaS) or any other types of hosted services to a third party”, and also an indirect advantage such as a “cost-free add-on” to other products. It states that Private Use and Productive Use “are explicitly NOT considered as Commercial”.

What we could not settle: whether the owncloud/ocis image on Docker Hub is one of the “some builds”. Its Docker Hub page does not mention the agreement. It carries an Apache-2.0 badge for the image’s packaging repository, owncloud-docker/ocis, and says the image is built from source. No source we read says the image is covered or that it is not. If you would run Infinite Scale as a hosted service for others, or inside a product you sell, ask ownCloud before you start. Running it for yourself or inside your own organization is what the agreement’s Private Use and Productive Use describe. This is our reading of the sources, not legal advice.

When to pick Nextcloud

  • You want more than file storage from one server. Calendar, contacts, mail and Deck boards are documented as Nextcloud’s groupware bundle, and online office is a documented add-on (researched, not tested). The lab stack did not run any of those apps, so 297 MiB idle is the file server alone.
  • You want the stack we tested furthest. Whole stack: 297 MiB idle, 452 MiB peak under a one-user upload (the Oct 8 run on 35.0.1 gave 299 and 454; the Oct 17 run, 265 and 367, was taken before cron’s first run in two of three runs; see the note under the table), 1 GB by our sizing rule for that load, the same tier as Infinite Scale and half of Seafile’s. Nextcloud’s documents recommend 512MB per process, and we did not count processes, so add room for more users. It is also the only one of the three for which we ran proxy, cron, Redis, patch and major update, backup and restore tests. They are in the verified Nextcloud compose file and guide.
  • You accept four containers and 676.4 MB of images to download. app held 204 MiB of the 297 at idle. The cron container held 34 MiB at idle in this run, after its first background run (0.6 MiB before it), and reached 147 and 167 MiB during the upload in two of three runs (on Oct 8 it reached 154 and 182 MiB in two of three runs).

When to pick Seafile

  • Files are the whole job. Seafile’s manual describes a Git-like model with content-defined blocks and deduplication between versions of a file (researched; we did not exercise the sync client, so we have no measure of what that saves you). There is no calendar or contacts section in the manual, and online office goes through its OnlyOffice or SeaDoc extensions.
  • You have 2 GB or more. Whole stack: 616 MiB idle and 905 MiB under the upload, 2 GB by our rule. The manual’s own figure for the Community Edition is 2G of memory and 2 cores, and it says extensions such as OnlyOffice need more. Of the three, it is the stack with the most RAM and the most image data (720.0 MB to download).
  • You are fine with MariaDB and Redis. The 13.0 Docker documentation says that “Since Seafile 13” Redis is the recommended cache and Memcached “will no longer be integrated into Seafile Docker by default” (Docker setup). The lab’s file follows that setup. Our compose file leaves out Caddy, which the official setup uses for TLS.
  • Check the edition. Cluster installation, virus scan and SeaSearch are marked “(Pro)” in the manual’s contents. Which Community Edition limits matter for you is for the manual to say; we tested Community Edition 13.0.28 only.

When to pick ownCloud Infinite Scale

  • You want the smallest measured footprint of the three. One container: 151 MiB idle (range 101 to 155), 305 MiB peak under our one-user upload, 87.5 MB of image to download, 1 GB by our rule for that test. By its idle median it used 51% of Nextcloud’s RAM (151 against 297 MiB) and about a quarter of Seafile’s; by its lowest run, 34% of Nextcloud’s. Its peak (305 MiB) was 68% of Nextcloud’s (452). Against the Oct 17 Nextcloud medians (265 and 367 MiB), which were taken before cron’s first run, the shares would have been 57% and 83%. For about two minutes after start it sat at 213 to 322 MiB, close to Nextcloud’s idle.
  • Do not read that as “runs on 1 GB”. ownCloud’s prerequisites page calls 4GB “a good starting point” for production and says RAM depends on the number of spaces and the tasks running at once. Our test had one user, one space, no search, previews or office server. It shows the footprint of the empty server and a small upload, not the memory a team would need.
  • You can live without calendar and contacts, or will run them elsewhere. Neither is in the 8.2 documentation we read (see the table). If you need CalDAV and CardDAV on the same server, Nextcloud documents them, and ownCloud’s edition comparison, which names ownCloud 10.13, lists optional Calendar and Contacts apps that sync over CalDAV and CardDAV; the Infinite Scale pages we read do not.
  • You like the spaces model and no PHP. Infinite Scale organizes data into spaces that have roles of their own and runs as a Go binary (researched). We tested neither the spaces features nor the web interface.
  • Read the production notes first. The lab ran it the evaluation way, with a self-signed certificate (see the Compose section). The documented production setup is a different, larger stack. Read the “Infinite Scale license” section above if you plan to host it for other people or build it into a product.

Syncthing, if you do not need a server

A search for “seafile vs syncthing” is asking a different question. Syncthing’s FAQ says it “does not upload your data to the cloud but exchanges your data across your machines as soon as they are online at the same time”. It copies folders between your own devices instead of keeping them on a server you run. If that covers your need, none of the three stacks above is required. We have since tested Syncthing 2.1.6, on Oct 16, 2026: 22 to 24 MiB idle per node, measured as two lab nodes. Those numbers, and how a peer-to-peer tool differs from a server, are on our page about a self-hosted alternative to Google Drive. This page has no feature comparison for it.

Migration notes

Not run in our lab: we did not move data between any of these apps. What we can say from the sources:

  • Classic to Infinite Scale. ownCloud’s April 2026 post says the migrator is “in the pipeline, not shipped yet”. Check ownCloud’s documentation for the state of the migrator before you plan a move; we did not look for a converter.
  • Between any two of these. All three can hold plain files, and rclone has a WebDAV backend with Nextcloud and ownCloud options and a Seafile backend, so a file-level copy through rclone is possible in principle (researched; not run in our lab). Calendars, contacts, shares, versions and comments would not come with a plain file copy.
  • Back up first. The only restore we tested is Nextcloud’s, in its guide. It showed that a database dump alone did not restore; do not assume the other two are simpler.

Compose files

Nextcloud’s verified compose file and .env are in the Nextcloud guide’s verified-file section, which also covers the trusted-domain, Redis and cron settings and the reverse proxy; they are the files the Oct 18 run used (35.0.2) and we do not repeat them here.

The Seafile and Infinite Scale files below are the ones the lab ran on Oct 16, 2026, with their ports as published (localhost only). Each .env has its password lines commented out, on purpose: both products create the first admin account with whatever they are given, so a placeholder would become a real, known password. The compose files refuse to start until you set them. The measured runs used the lab’s own values.

Seafile

Three services: seafile, db (MariaDB 10.11) and redis. Data lives in two named volumes: db and seafile-data. The file has no TLS. It follows the official Seafile 13.0 Docker setup, with one file instead of four and without Caddy and SeaDoc.

compose.yamlVerified 2026-10-16 · Seafile 13.0.28Download compose.yaml for Seafile
# Verified compose for Seafile, tested 2026-10-16 by the SelfHostBench lab (3 runs; the figures are the median).
# Lab host: AMD EPYC 9V45 96-Core Processor, 2 vCPU, 7.8 GiB RAM, x86_64, Docker 28.0.4.
# Floating image tags below were replaced by the version resolved at test time;
# the registry digest is in the comment on each image line.
# Measurements: seafile.json (schema 3).
# Companion env file: seafile.env (save it as .env next to this file).
# Secrets are not published: the lab's values are public. In seafile.env:
#   INIT_SEAFILE_ADMIN_PASSWORD is commented out. Uncomment it and set your own value (the comment above it explains how).
#   INIT_SEAFILE_MYSQL_ROOT_PASSWORD is commented out. Uncomment it and set your own value (the comment above it explains how).
#   SEAFILE_MYSQL_DB_PASSWORD is commented out. Uncomment it and set your own value (the comment above it explains how).
#   JWT_PRIVATE_KEY is commented out. Uncomment it and set your own value (the comment above it explains how).

# Seafile Community Edition 13.0 with MariaDB and Redis.
# Follows the official Docker setup, https://manual.seafile.com/13.0/setup/setup_ce_by_docker/ (seafile-server.yml and .env of
# that page, read 2026-10-16). Differences from it, all marked below: one file instead of four, no Caddy and no SeaDoc, named volumes
# instead of /opt/... bind paths, a pinned image tag, required passwords, healthchecks on every service, a stricter Seafile healthcheck.
# There is no TLS in this file. Put a reverse proxy in front before you expose it (see the article).
name: seafile

services:
  db:
    # MariaDB 10.11, the version the official file uses. Seafile needs a MySQL-compatible database (SQLite is not supported since 11.0).
    image: mariadb:10.11  # sha256:7db29378d4fdab73f8123bbc2b48905c90d1a4b00cf848b028f1e81e623257f2  (version 10.11.19, from label:org.opencontainers.image.version)
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: "${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:?set INIT_SEAFILE_MYSQL_ROOT_PASSWORD in .env}"
      MYSQL_LOG_CONSOLE: "true"
      MARIADB_AUTO_UPGRADE: "1"
    volumes:
      # The Seafile databases (ccnet_db, seafile_db, seahub_db). Back them up with mariadb-dump.
      - db:/var/lib/mysql
    healthcheck:
      test: ["CMD", "/usr/local/bin/healthcheck.sh", "--connect", "--mariadbupgrade", "--innodb_initialized"]
      interval: 10s
      start_period: 30s
      timeout: 5s
      retries: 12

  redis:
    # Since Seafile 13 Redis is the recommended cache (memcached is optional and no longer part of the official file).
    # No password and no published port: only containers on this Compose network can reach it.
    image: redis:8.10.2  # sha256:2c2dff791878316e3b083188be0d578423b24813cdda5de0e80ea4f7b3e6bfd6  (version 8.10.2, from exec)
    restart: unless-stopped
    command:
      - /bin/sh
      - -c
      - exec redis-server --requirepass "$$REDIS_PASSWORD" --save "" --appendonly no
    environment:
      REDIS_PASSWORD: "${REDIS_PASSWORD:-}"
    healthcheck:
      # Differs from the official file, which has no healthcheck here.
      test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
      interval: 5s
      timeout: 3s
      retries: 12

  seafile:
    # The Seafile server: seaf-server (file server, Go), Seahub (the web interface, Django) and the bundled nginx on port 80.
    image: seafileltd/seafile-mc:13.0.28  # sha256:b0c90832126bf432db908449f1bb450211e6bbf75a2193bab3399e2a9636eccf  (version 13.0.28, from exec)
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      # Localhost only. A reverse proxy on the host sends traffic here. The official file publishes nothing and puts Caddy in front.
      - "127.0.0.1:8080:80"
    environment:
      # Database. The first start creates the three databases and the "seafile" database user with the root password.
      SEAFILE_MYSQL_DB_HOST: db
      SEAFILE_MYSQL_DB_PORT: "3306"
      SEAFILE_MYSQL_DB_USER: seafile
      SEAFILE_MYSQL_DB_PASSWORD: "${SEAFILE_MYSQL_DB_PASSWORD:?set SEAFILE_MYSQL_DB_PASSWORD in .env}"
      INIT_SEAFILE_MYSQL_ROOT_PASSWORD: "${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:?set INIT_SEAFILE_MYSQL_ROOT_PASSWORD in .env}"
      SEAFILE_MYSQL_DB_CCNET_DB_NAME: ccnet_db
      SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: seafile_db
      SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: seahub_db
      TIME_ZONE: "${TIME_ZONE:-Etc/UTC}"
      # First admin account. Used on the first start only; later changes here do nothing.
      # The official file has defaults (me@example.com / asecret); here both must be set so nobody runs with a public password.
      INIT_SEAFILE_ADMIN_EMAIL: "${INIT_SEAFILE_ADMIN_EMAIL:?set INIT_SEAFILE_ADMIN_EMAIL in .env}"
      INIT_SEAFILE_ADMIN_PASSWORD: "${INIT_SEAFILE_ADMIN_PASSWORD:?set INIT_SEAFILE_ADMIN_PASSWORD in .env}"
      # The address you type in the browser. Seafile builds its download and upload links from these two values.
      SEAFILE_SERVER_HOSTNAME: "${SEAFILE_SERVER_HOSTNAME:?set SEAFILE_SERVER_HOSTNAME in .env}"
      SEAFILE_SERVER_PROTOCOL: "${SEAFILE_SERVER_PROTOCOL:-http}"
      # At least 32 random characters. Seafile services use it to sign tokens for each other.
      JWT_PRIVATE_KEY: "${JWT_PRIVATE_KEY:?set JWT_PRIVATE_KEY in .env}"
      SITE_ROOT: /
      NON_ROOT: "false"
      SEAFILE_LOG_TO_STDOUT: "false"
      ENABLE_GO_FILESERVER: "true"
      # Redis for the cache.
      CACHE_PROVIDER: redis
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      REDIS_PASSWORD: "${REDIS_PASSWORD:-}"
      # Optional components of the official file, all switched off here: SeaDoc (online documents; needs its own container),
      # the notification server, the metadata server and Seafile AI.
      ENABLE_SEADOC: "false"
      ENABLE_NOTIFICATION_SERVER: "false"
      ENABLE_SEAFILE_AI: "false"
      ENABLE_FACE_RECOGNITION: "false"
    volumes:
      # Libraries (file blocks), configuration (conf/) and logs. This is your data: back it up together with the database.
      - seafile-data:/shared
    healthcheck:
      # The official file only checks that port 80 answers. This one waits for the API (Seahub) and the file server (seaf-server)
      # behind the bundled nginx, which is when uploads work.
      test: ["CMD-SHELL", "curl -fsS http://localhost/api2/ping/ | grep -q pong && curl -fsS http://localhost/seafhttp/protocol-version | grep -q version"]
      interval: 10s
      timeout: 10s
      retries: 60
      start_period: 30s

volumes:
  db:
  seafile-data:
.envVerified 2026-10-16 · Seafile 13.0.28Download .env for Seafile
# Address you type in the browser: no http://, no port, no path. Seafile writes it into its upload and download links.
SEAFILE_SERVER_HOSTNAME=seafile.example.com
# http or https. Behind a TLS reverse proxy use https.
SEAFILE_SERVER_PROTOCOL=http
TIME_ZONE=Etc/UTC

# At least 32 random characters; Seafile's services use it to sign tokens for each other. Choose your own; the stack does not start without it.
# Generate one with:  openssl rand -hex 32
# JWT_PRIVATE_KEY=

# MariaDB root password. Choose your own; the stack does not start without it.
# Generate one with:  openssl rand -hex 24
# INIT_SEAFILE_MYSQL_ROOT_PASSWORD=

# Password of the database user "seafile", which Seafile creates on the first start. Choose your own; the stack does not start without it.
# Generate one with:  openssl rand -hex 24
# SEAFILE_MYSQL_DB_PASSWORD=

# E-mail address of the first admin account (it is the login name). First start only.
INIT_SEAFILE_ADMIN_EMAIL=admin@example.com

# Password of the first admin account (first start only). Choose your own, long; the stack does not start without it.
# A placeholder would become a real, known admin password, so the lab's value is not published and this line is commented out.
# Generate a password with:  openssl rand -hex 16
# INIT_SEAFILE_ADMIN_PASSWORD=

ownCloud Infinite Scale

One service, ocis, with two named volumes: ocis-config (holds the generated secrets in ocis.yaml; without it the data cannot be used) and ocis-data.

compose.yamlVerified 2026-10-16 · ownCloud Infinite Scale 8.2.1Download compose.yaml for ownCloud Infinite Scale
# Verified compose for ownCloud Infinite Scale, tested 2026-10-16 by the SelfHostBench lab (3 runs; the figures are the median).
# Lab host: AMD EPYC 9V45 96-Core Processor, 2 vCPU, 7.8 GiB RAM, x86_64, Docker 28.0.4.
# Floating image tags below were replaced by the version resolved at test time;
# the registry digest is in the comment on each image line.
# Measurements: owncloud.json (schema 3).
# Companion env file: owncloud.env (save it as .env next to this file).
# Secrets are not published: the lab's values are public. In owncloud.env:
#   OCIS_ADMIN_PASSWORD is commented out. Uncomment it and set your own value (the comment above it explains how).

# ownCloud Infinite Scale (oCIS) 8.2: the single-container ownCloud that ownCloud calls its flagship product.
# Follows the Docker examples of ownCloud's own documentation: "Minimalistic Evaluation Guide for oCIS with Docker" (https://owncloud.dev/ocis/guides/ocis-mini-eval/)
# and the `ocis` service of the ocis_full example (https://github.com/owncloud/ocis/tree/stable-8.2/deployments/examples/ocis_full), without that example's
# Traefik, Collabora, ONLYOFFICE, Tika, ClamAV, Keycloak and mail containers. Differences from both, all marked below.
# Infinite Scale has no separate database and no cache container: users, metadata and search index live inside this one container's volumes.
# TLS: oCIS answers on HTTPS with a certificate it generates itself (self-signed). That is fine on a private network and for a browser
# on the same machine; for the internet put a reverse proxy in front (see the article).
name: owncloud

services:
  ocis:
    image: owncloud/ocis:8.2.1  # sha256:5e007d702b78d70e5aeade14ec9da46044664996df6c9482630dedadcc74bffc  (version 8.2.1, from label:org.opencontainers.image.version)
    restart: unless-stopped
    # `ocis init` writes /etc/ocis/ocis.yaml with random secrets on the first start. It fails on later starts because the file exists,
    # so the error is ignored and the server starts (the same line as the ocis_full example).
    entrypoint: ["/bin/sh"]
    command: ["-c", "ocis init || true; exec ocis server"]
    ports:
      # Localhost only. A reverse proxy on the host sends traffic here.
      - "127.0.0.1:9200:9200"
    environment:
      # The address you type in the browser. It is also the OpenID Connect issuer, so it must be the address users really use
      # (with a reverse proxy: https://your.domain). The default works for a browser on the same machine.
      OCIS_URL: "${OCIS_URL:-https://localhost:9200}"
      # Listen on all interfaces, not only inside the container (the evaluation guide sets this too).
      PROXY_HTTP_ADDR: 0.0.0.0:9200
      # oCIS generates a self-signed certificate; the services call each other (and the identity provider) over it, so do not verify it.
      # The ocis_full example sets this to false only when a proxy with a real certificate is in front.
      OCIS_INSECURE: "true"
      # Password of the first account, "admin". Used when oCIS creates its user database on the first start; later changes here do not
      # change an existing password. The official example defaults to the public password "admin"; here it must be set.
      IDM_ADMIN_PASSWORD: "${OCIS_ADMIN_PASSWORD:?set OCIS_ADMIN_PASSWORD in .env}"
      # Not in the evaluation guide. Lets WebDAV clients and scripts that cannot do OpenID Connect log in with user name and password
      # (the ocis_full example has the same switch, off by default and described as "not recommended"). The web interface and the
      # official apps use OpenID Connect and do not need it. Remove it if you only use those.
      PROXY_ENABLE_BASIC_AUTH: "true"
      OCIS_LOG_LEVEL: "${OCIS_LOG_LEVEL:-info}"
    volumes:
      # Configuration with the generated secrets (ocis.yaml). Back it up: without it the data cannot be used.
      - ocis-config:/etc/ocis
      # Every user's files and the metadata. This is your data: back it up.
      - ocis-data:/var/lib/ocis
    healthcheck:
      # The official examples have no healthcheck. status.php answers when the proxy and the frontend are up; the image has curl.
      # -k because the certificate is self-signed.
      test: ["CMD-SHELL", "curl -fsSk https://localhost:9200/status.php | grep -q '\"installed\": true'"]
      interval: 10s
      timeout: 10s
      retries: 30
      start_period: 20s

volumes:
  ocis-config:
  ocis-data:
.envVerified 2026-10-16 · ownCloud Infinite Scale 8.2.1Download .env for ownCloud Infinite Scale
# Address you type in the browser, with https:// and without a trailing slash. It must match what users really use:
# a name like https://cloud.example.com behind a reverse proxy, or the default below for a browser on the same machine.
OCIS_URL=https://localhost:9200

# Password of the first account, "admin" (first start only). Choose your own; the stack does not start without it.
# A placeholder would become a real, known admin password, so the lab's value is not published and this line is commented out.
# Generate one with:  openssl rand -hex 16
# OCIS_ADMIN_PASSWORD=

Lab settings you would change in a real deployment

The file runs the way ownCloud’s evaluation guide runs it, plus one switch for the lab’s script. That guide says the setup is “ONLY intended for a quick evaluation and to access the instance from your local machine using internal certificates only”. Not tested in our lab: any of the changes below.

  • OCIS_INSECURE: "true". Infinite Scale generates a self-signed certificate and its services call each other over it, so the lab told them not to verify it. The proxy page of the 8.2 docs says this setting is “not recommended for production environments” (proxy service), and the production Compose guide says to comment out INSECURE on an internet-facing server (guide).
  • Real certificate and OCIS_URL. The guide puts Traefik with Let’s Encrypt in front. If a reverse proxy ends TLS, the proxy docs say PROXY_TLS can be false, and then “the communication between the reverse proxy and Infinite Scale is not secured”. OCIS_URL is also the OpenID Connect issuer, so it must be the address your users type.
  • PROXY_ENABLE_BASIC_AUTH: "true". Added so a script could use WebDAV with a user name and password. The proxy docs say that in production you want it disabled, which is the default. Remove it unless you need it.
  • The admin password is set from OCIS_ADMIN_PASSWORD on the first start; changing the variable later does not change an existing password.
  • The rest of the stack. The official production example adds Collabora, ONLYOFFICE and other services, and its documentation asks for 4 to 6 GB. Our figures are for the single container above.

What we did not test

  • Desktop and mobile sync clients for any of the three, and how they behave when files change on a laptop. The lab used API scripts.
  • Online office (Collabora, OnlyOffice, Euro-Office, SeaDoc), full-text search, previews and thumbnails.
  • External storage, S3 or other storage backends.
  • LDAP, SSO and OpenID Connect logins (Infinite Scale’s bundled login was bypassed by Basic authentication).
  • More than one user, sharing, public links, and files larger than 50 MB.
  • Arm hardware: one x86-64 runner type only.
  • A large library, and growth in RAM or disk over days. Each run started from an empty install and lasted a few minutes.
  • ownCloud Classic 10 or 11, Seafile 14, and Nextcloud AIO.
  • All three apps on the same CPU model in one job, which a clean timing comparison needs.
  • Upgrades and restores for Seafile and Infinite Scale, and the published files with a real domain and certificate.

Update log

  • Refreshed the Nextcloud column for the Oct 18, 2026 run (35.0.2, AMD EPYC 7763), which measures idle after the cron container's first background run: idle 297 MiB (was 265 on Oct 17), peak 452 MiB (was 367), highest reading used for sizing 479 MiB (was 449), idle CPU 2.52% (was 2.80), upload of 103 files 32.9 s (was 31.3), images to download 676.4 MB (unchanged). Sizing tiers are unchanged (1 GB, 2 GB, 1 GB). The Oct 17 idle figure was taken before cron's first run in two of its three runs. The ratios in the verdicts were recomputed: Infinite Scale's idle median is now 51% of Nextcloud's (was 57%) and its peak 68% (was 83%). Seafile and Infinite Scale are unchanged (runs of Oct 16, EPYC 9V45). Figures: lab/notes/nextcloud-2026-10-18.md.
  • Refreshed the Nextcloud column for 35.0.2 (run of Oct 17, 2026, AMD EPYC 7763; was 35.0.1, run of Oct 8): idle 265 MiB (was 299), peak 367 MiB (was 454), highest reading used for sizing 449 MiB (was 497), idle CPU 2.80% (was 2.32), images to download 676.4 MB (was 674.7). Sizing tiers are unchanged (1 GB, 2 GB, 1 GB). The change is the Nextcloud cron container, not the app, and one Nextcloud run still had a cron burst (details in the Nextcloud guide). Seafile and Infinite Scale are unchanged (runs of Oct 16, EPYC 9V45). The ratios in the verdicts were recomputed. Figures: lab/notes/nextcloud-2026-10-17.md.
  • Syncthing section now links the new Google Drive alternatives page, which has our Syncthing 2.1.6 and File Browser 2.63.23 measurements (run of Oct 16, 2026); it replaces the sentence saying we had not tested Syncthing. This page still has no Syncthing feature comparison, and no measurement on this page changed.
  • First published. Nextcloud 35.0.1 (run of Oct 8, 2026), Seafile 13.0.28 and ownCloud Infinite Scale 8.2.1 (both Oct 16, 2026), three runs each on GitHub Actions runners. The three apps ran in separate jobs; Nextcloud's was on an AMD EPYC 7763, the other two on EPYC 9V45, so timing is not a head-to-head. Seafile's load used its native upload API, the other two WebDAV. ownCloud Classic (PHP) was not tested. The feature rows are researched and marked as such. Figures and sources are in lab/notes/filesync-2026-10-16.md.