Nextcloud combines file sync, sharing, calendars, contacts, collaborative editing, chat, and a large app ecosystem. The supported All-in-One (AIO) stack also runs PostgreSQL, Redis, a web server, and optional services. It therefore needs more planning than a single PHP container.
This guide uses Nextcloud's official AIO master container. The public service gets normal HTTPS on TCP 443, while the self-signed AIO management interface on 8080 is bound to loopback and reached through SSH.
VPS size, CPU, storage, and price
Nextcloud says memory depends heavily on users, apps, files, and activity. AIO's interface calculates additional requirements for optional containers. The values here are a practical small-production plan, not universal upstream limits.
| Item | Planning value |
|---|---|
| Minimum RAM | 4 GB for a small core AIO stack without heavy optional containers |
| Recommended RAM | 8 GB for a small household or team with preview generation and update headroom |
| Expected CPU usage | Roughly 0.05–0.25 vCPU idle; 1–4 vCPU while generating previews, syncing many files, indexing, scanning, or serving active users |
| Storage requirement | Reserve 20–30 GB for Ubuntu, images, database, cache, and logs, plus all user files, file versions, trash, and temporary upload space |
| Exact LayerOne SKU | gc.medium — slug layerone-pro, 4 vCPU, 8 GB RAM, 160 GB disk |
| Expected monthly cost | $0.0205 per active hour; about $14.97 per 730 hours against the advertised $15.00 730-hour equivalent |
A 744-hour month is about $0.0205 × 744 = $15.25. The 160 GB disk is not
160 GB of usable file capacity: the OS, container images, database, versions,
trash, previews, and working space all share it. Existing data sets near 100 GB
deserve a larger SKU and a measured migration plan.
User activity, preview formats, versions, optional apps, transfer, and storage growth vary, and LayerOne bills the allocated VPS hourly. CPU figures are planning estimates, not performance guarantees. Office, Talk, antivirus, full-text search, and large active teams can require substantially more RAM and CPU.
Assumptions
- Ubuntu 24.04 LTS on an x86-64 LayerOne KVM VPS
- A public IPv4 address and a dedicated DNS name such as
cloud.example.com - Docker Engine from Docker's apt repository, not the Ubuntu Snap package; see Running Docker
- DNS already resolves the hostname to this VPS
- A sudo user using SSH keys; replace
ADMIN_IPbelow with its fixed source address - Host ports 80 and 443 are unused; this guide uses AIO's integrated HTTPS path rather than an external reverse proxy
AIO supports a dedicated hostname, not a URL subdirectory. Do not plan to serve
it as example.com/nextcloud.
1. Open only the required ports
In the LayerOne cloud firewall, use inbound default DROP and allow:
| Source | Protocol | Port | Purpose |
|---|---|---|---|
ADMIN_IP/32 |
TCP | 22 | SSH and the management tunnel |
0.0.0.0/0 |
TCP | 80 | Certificate validation and redirect |
0.0.0.0/0 |
TCP | 443 | Nextcloud HTTPS |
TCP/UDP 3478 is needed only if you later enable Nextcloud Talk's TURN server. UDP 443 is optional for HTTP/3. This guide does not publish AIO management ports 8080 or 8443.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from ADMIN_IP to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Docker can bypass UFW for published ports, so keep the same restrictions in the LayerOne cloud firewall.
2. Check Docker and start AIO with its official Compose file
Confirm this is a standard Docker installation and not Docker Snap:
sudo docker info | grep 'Docker Root Dir'
docker compose version
If the root path begins /var/snap/docker, migrate to the supported Docker
Engine installation before continuing.
Nextcloud recommends its example Compose file for production because it makes the master-container configuration reviewable and repeatable. Download the current upstream file into a dedicated project directory:
sudo install -d -m 0750 /opt/nextcloud-aio
sudo chown "$USER":"$USER" /opt/nextcloud-aio
cd /opt/nextcloud-aio
curl -fsSLo compose.yaml https://raw.githubusercontent.com/nextcloud/all-in-one/main/compose.yaml
cp compose.yaml compose.yaml.upstream
Edit the ports list for nextcloud-aio-mastercontainer: change
"8080:8080" to "127.0.0.1:8080:8080", and remove the optional
"8443:8443" line. Keep "80:80". Do not rename the master container or its
configuration volume; AIO depends on those names.
The resulting part of the service must read:
ports:
- "80:80"
- "127.0.0.1:8080:8080"
Do not add port 443 to the master-container service. After setup, AIO creates
the sibling nextcloud-aio-apache container, which claims host TCP 443 for the
actual Nextcloud site even though that port does not appear in this Compose
service. Port 8080 is only the AIO control interface. If another web server
already owns 443, stop here and follow the upstream reverse-proxy mode instead;
that mode sets APACHE_PORT and APACHE_IP_BINDING and proxies to that Apache
port, never to the management interface on 8080.
Validate the entire upstream file and start it:
cd /opt/nextcloud-aio
sudo docker compose config >/dev/null
sudo docker compose pull
sudo docker compose up -d
Although the socket is mounted read-only, the master container is designed to
control sibling containers. Treat access to its interface as privileged host
access. Keep compose.yaml.upstream only as a review reference; your edited
compose.yaml is the active configuration.
Check startup:
sudo docker ps --filter name=nextcloud-aio-mastercontainer
sudo docker logs --tail=100 nextcloud-aio-mastercontainer
curl -kI https://127.0.0.1:8080
3. Complete setup through an SSH tunnel
On your workstation:
ssh -L 8080:127.0.0.1:8080 admin@SERVER_IP
Browse to https://127.0.0.1:8080, accept the expected self-signed certificate,
and save the AIO passphrase in a password manager. Upstream specifically says
to use an IP address, not the eventual Nextcloud domain, on port 8080 because
HSTS can otherwise make the management URL inaccessible later.
Enter cloud.example.com when AIO asks for the Nextcloud domain. Start with the
core containers. Add Collabora, Talk, ClamAV, Imaginary, full-text search, or
other optional services one at a time only after reading the RAM estimate AIO
shows for each.
4. Verify the finished service
After AIO reports the containers healthy, open
https://cloud.example.com, create the Nextcloud administrator, then create a
separate non-admin daily account.
sudo docker ps --format 'table {{.Names}} {{.Status}}'
sudo docker exec --user www-data nextcloud-aio-nextcloud php occ status
curl -I https://cloud.example.com/status.php
Upload a small file, sync it to a second client, rename it, delete it, and restore it from trash. Confirm background jobs run and the Administration Overview has no unresolved configuration warnings. Test one file larger than your reverse-proxy or client defaults before migrating a library.
Security pitfalls
- Keep the AIO interface on loopback. If you deliberately expose 8080 or 8443, restrict it to trusted administration addresses in the cloud firewall.
- Do not put Nginx, Caddy, or another proxy in front of port 8080. An external
proxy must use AIO's documented
APACHE_PORTmode; this guide uses AIO's integrated HTTPS listener on 443. - Enable Nextcloud two-factor authentication and distribute recovery codes before inviting users.
- Keep the administrator account for administration; use an ordinary account for sync clients.
- Do not edit generated AIO containers as if they were a hand-written Compose stack. AIO owns their lifecycle.
- Review app permissions before enabling community apps. Every app executes in the same security context as valuable files and metadata.
- Do not place the database on a network filesystem. Keep database and active application data on the VPS's local SSD-backed disk.
Back up and restore before updating
Nextcloud AIO includes encrypted, deduplicated Borg backups. Configure its backup destination in the AIO interface, ideally as a remote SSH Borg repository on a different provider or physical system. A backup stored only on this 160 GB disk is lost with the VPS and competes with live data for space.
The backup password is required for restoration. Store it outside Nextcloud and outside the server. Enable scheduled backups only after an initial backup and a test restore succeed. External-storage mounts need separate coverage; they are not automatically protected merely because Nextcloud can see them.
Use the AIO interface to stop, update, and start its managed containers. Before each major Nextcloud or AIO update:
- Read the AIO and Nextcloud release notes.
- Run a fresh Borg backup and confirm its archive is visible remotely.
- Export or separately protect irreplaceable encryption and configuration material.
- Update from AIO and watch every container's log.
- Re-run
occ status, upload/download tests, cron checks, and client sync.
LayerOne does not take snapshots or backups. Read Backups and snapshots before loading production files.