Nextcloud AIO: Worth It or Not
An honest look at the all-in-one installer, the Docker socket it wants, and who it actually suits

Contents
Every few months someone in a forum thread asks why their Nextcloud install has fourteen containers, three of which they don’t remember adding, and whether there’s an easier way. The answer they get is always the same three letters: AIO. And then, six weeks later, the same person is back asking why AIO won’t let them mount their existing data directory, or why it insists on owning a Docker socket, or why the upgrade they didn’t ask for broke Collabora.
I’ve run Nextcloud on my own hardware in most of the shapes it comes in — a hand-rolled Compose stack, the snap, a bare PHP-FPM install behind nginx that I maintained out of stubbornness for far too long, and AIO. Each has a personality. AIO’s personality is that of a very competent contractor who will build you an excellent kitchen and will absolutely not discuss the plumbing with you. Whether that’s a good trade depends entirely on what kind of person you are, which is why “is AIO worth it” has no universal answer and a very clear personal one.
This is my attempt at the honest version. If you want the ground-up approach instead, I wrote about building your own Google Drive with Nextcloud on Linux a while back, and most of that still applies.
What AIO actually is
The mental model most people arrive with is wrong, and it causes about 80% of the pain. People read AIO as a Compose file with sensible defaults. AIO is a container that runs other containers.
You start exactly one thing: the mastercontainer. It exposes a web interface on port 8080 (TLS, self-signed) where you type a domain, click a few checkboxes for optional components, and press start. The mastercontainer then reaches out to the Docker daemon and creates everything else itself — Apache, the Nextcloud PHP container, PostgreSQL, Redis, and then whichever of Collabora, Talk, Imaginary, Whiteboard, ClamAV and Fulltextsearch you ticked. It manages their lifecycle, their volumes, their environment, their update order, and their inter-container networking.
That is the whole design. The mastercontainer is an orchestrator with a web UI, and Nextcloud is its payload.
| |
Look at that volume mount on the second-to-last line. That’s the whole conversation, really, and we’ll come back to it.
The why matters here. Nextcloud’s support burden has historically been dominated by people running it wrong: PHP memory limits at 128M, no Redis so file locking is done in the database, opcache.interned_strings_buffer at the default so the admin overview screams at you, a reverse proxy that doesn’t forward the right headers, cron running as the wrong user so background jobs never fire. AIO exists because Nextcloud GmbH got tired of debugging other people’s stacks. It’s a deployment method built to eliminate a support queue, and it’s very good at that specific job. The tuning is correct out of the box. The database is the one they test against. The cron container actually runs. Collabora talks to Nextcloud on the first try, which anyone who has hand-wired a WOPI setup will recognise as a small miracle.
The Docker socket, and why I stopped pretending it’s fine
Mounting /var/run/docker.sock into a container gives that container the ability to create other containers. Any container that can create containers can create a privileged one mounting / and read your host filesystem. The exploit chain is one docker run long. Access to the Docker socket is functionally equivalent to root on the host.
AIO mounts it read-only, and the :ro flag is doing much less than it looks like it’s doing — the socket is an API endpoint, and “read-only” prevents nothing that matters, because the dangerous operations are all API calls over that socket rather than writes to a file. The AIO documentation is honest about this and even suggests a socket-proxy arrangement for the hardened case.
I take the socket seriously enough that it’s the main reason I went down the Podman road for everything that distrusts the Docker daemon. The usual mitigation is a socket proxy that filters the API surface, and the awkward part for AIO specifically is that the mastercontainer needs a genuinely broad slice of that API — container create, start, stop, remove, exec, image pull, volume create, network connect. Once you’ve allowed that set, the proxy is filtering out /info and /events and not much else of consequence. You get a nice log of what AIO asked for. You do not get meaningfully constrained blast radius.
So my position: on a dedicated machine whose only job is Nextcloud, AIO’s socket access is an acceptable risk, because compromising the mastercontainer gets you a box that already only runs Nextcloud. On the shared box where you also keep your password manager, your backup keys and your monitoring stack, it’s a bad trade, and I wouldn’t do it. That’s the same reasoning I apply in the homelab threat model piece: the question is never “is this dangerous” in the abstract, it’s “what does an attacker get, on this machine, if this thing falls over”.
Putting it behind the reverse proxy you already have
This is the single biggest source of AIO frustration, and it’s mostly a documentation-reading problem. AIO wants to own port 443 by default, because it wants to manage its own certificate. Most of us already have Caddy or Traefik sitting there doing exactly that job for a dozen other services.
The supported answer is APACHE_PORT. You tell the mastercontainer to bind its Apache container on a plain HTTP port — 11000 is the conventional choice — and then you proxy to it yourself.
| |
Three things bite people here, in descending order of frequency:
The domain validation check. Before AIO will start anything, it resolves your domain and confirms that it points at this machine and that a request to it comes back with a token AIO placed. If you’re doing split-horizon DNS and your internal resolver answers with a private address while the check expects the public one, you’ll get a validation failure that reads like a DNS problem and is actually an architecture problem. SKIP_DOMAIN_VALIDATION=true exists and is the correct escape hatch when you know what you’re doing.
Upload size limits. Caddy defaults are generous; nginx is not. If you’re on nginx, client_max_body_size 10G and a matching proxy_request_buffering off will save you an evening.
Timeouts. Big uploads and Collabora’s long-poll connections both want a proxy read timeout well above the default. Sixty seconds will produce intermittent, un-Googleable failures in the Office editor.
If you’re still choosing your proxy, I’ve made the case for Caddy and automatic HTTPS elsewhere, and for AIO it’s the one I’d pick: you’re proxying a single upstream and you want to be able to read the config file in six months. The Traefik and Nginx Proxy Manager comparison covers the alternatives if you’ve already committed elsewhere.
Where AIO genuinely earns it
I’m about to be rude about AIO for several paragraphs, so let me be fair first, because two of its features are legitimately excellent.
The backup implementation. AIO ships BorgBackup, wired up properly: it stops the containers, snapshots the volumes, restarts them, and gives you a one-click restore that actually restores. It’s the only Nextcloud deployment method I’ve used where the backup story is coherent by default. If you’ve read my Borg vs restic comparison you’ll know I’m partial to Borg anyway, but the point here is that the container-stop-snapshot-start dance is handled for you. Consistent database backups are exactly the thing people get wrong, and AIO gets it right without asking.
The daily maintenance window. AIO does its updates and its Borg run in a configurable window, in the correct order, and it tells you plainly when it’s done. Compare that to a Compose stack where you’re either running Watchtower and praying, or doing it by hand and forgetting for eight months. I’ve written before about why unattended latest pulls are a bad habit in container image housekeeping; AIO’s scheduled, ordered, backed-up window is the shape of the right answer, even though it takes your version choice away in exchange.
The Collabora integration deserves an honourable mention too. Getting a working Office suite into a hand-rolled Nextcloud is a genuine afternoon of WOPI URLs, allow-lists and nc_ssl_verify flags. AIO does it with a checkbox.
Where it grinds
You cannot pin a version. This is the big one. AIO decides which Nextcloud major you run. When a new major lands and AIO’s channel picks it up, you’re going with it during your next maintenance window. There’s no image: nextcloud:31.0.4 line you can hold at. For a system holding every document you own, “I’ll upgrade when the app ecosystem catches up” is a reasonable position that AIO simply does not let you take. Apps break on majors. They always have.
The data directory rules are strict. NEXTCLOUD_DATADIR lets you point the data at a host path, and it must be set before first start. Change your mind later and you’re doing a manual volume shuffle that AIO didn’t plan for. Similarly NEXTCLOUD_MOUNT for external storage — decide up front or do it the hard way.
occ is behind two doors. Everything you’d normally type as sudo -u www-data php occ becomes:
| |
Workable, and I have it aliased, though it’s a reminder that you’re a guest in someone else’s deployment.
PHP tuning is off the table. The PHP_MEMORY_LIMIT and PHP_UPLOAD_LIMIT environment variables exist and cover the common cases. Beyond those, the values are AIO’s. Usually they’re right. When they’re not, you have no lever.
Debugging is indirect. Something’s broken, you want logs, and there are eight containers. docker logs nextcloud-aio-nextcloud is the usual first stop, and the mastercontainer’s own log is where the orchestration failures hide. Central log aggregation helps more than you’d expect here — shipping the lot into Loki is worth the afternoon precisely because AIO turns “read the logs” into “read the right one of eight logs”.
Troubleshooting the four things that actually go wrong
The mastercontainer UI is unreachable on 8080. Nine times in ten this is the firewall, and once in ten it’s APACHE_IP_BINDING=127.0.0.1 doing its job while you try to reach the box from your laptop. Tunnel it:
| |
Domain validation fails with a token mismatch. Confirm what the world sees versus what you see:
| |
Two different answers from those first two commands means split-horizon DNS is the culprit. Either make the internal view match, or skip validation.
Containers won’t start after an update, with a volume error. Check that the mastercontainer can see them at all. If a previous run was killed mid-update, AIO can have containers in a half-created state:
| |
The mastercontainer log will name the specific step that failed. Stopping everything from the AIO UI and starting it again clears most of these, because AIO recreates containers from scratch rather than resuming them.
Collabora loads a blank frame. Almost always the proxy. Check that WebSocket upgrade headers survive your proxy and that your read timeout is measured in minutes. If you’re on Traefik, the middleware ordering matters and the symptom is identical.
“Your data directory is invalid” after a restore. Borg preserved the ownership; your restore target didn’t. chown -R 33:33 on the data path — 33 being www-data inside the container — resolves it. This is also the moment you discover whether you’d ever tested a restore, which is a topic I’ve been tiresome about before.
The verdict
AIO is worth it if Nextcloud is the point rather than the hobby. If you want Office, Talk, full-text search and a backup that works, on a machine that does nothing else, and you’d like to spend your weekend on something other than PHP tuning — AIO is the best-supported way to get there, and the backup implementation alone justifies it. It is genuinely, unusually good at being an appliance.
AIO is the wrong choice if you need version pinning, if the box is shared with things you care about protecting from a Docker-socket compromise, if you have an existing data layout you’re unwilling to reshape, or if you’re the sort of person who will inevitably want to change one PHP setting and will be furious when you can’t. That last one is more predictive than the technical criteria. I know which sort I am.
My own setup is a Compose stack, because I want to pin majors and I want the socket nowhere near that host. I’ve also recommended AIO to four different people and every one of them still has a working Nextcloud, which is a better hit rate than my own advice usually manages. Those two facts sit together comfortably. The right answer here is a personality test with a technical wrapper — the trick is being honest about which result you got.




