How to Install and Configure Nextcloud AIO on Ubuntu 24.04 LTS
This guide walks you through installing and configuring Nextcloud All-in-One (AIO) on an Ubuntu 24.04 LTS (Noble) server, with software RAID, a custom data directory on dedicated storage, and full IPv6 support. It is written from a real Noiz production install (noiz.cloud) running on a dedicated cloud server, and it reflects the specific configuration changes needed to make AIO work reliably on a modern Ubuntu host. The same procedure also works on Ubuntu 22.04 LTS (Jammy), which shares the same networking stack.
Last reviewed: 27 July 2026, against Nextcloud All-in-One (latest stable) on Ubuntu 24.04 LTS. This guide is written for Noiz hosting and documents a real Noiz production deployment. It complements, and does not replace, the official Nextcloud AIO and Docker documentation linked below.
Official Documentation Reference
Section titled “Official Documentation Reference”- Nextcloud AIO repository and documentation: github.com/nextcloud/all-in-one
- Docker Engine install on Ubuntu: docs.docker.com/engine/install/ubuntu
- Docker IPv6 networking: docs.docker.com/engine/daemon/ipv6
- Nextcloud admin manual: docs.nextcloud.com/server/latest/admin_manual
Hardware Setup Assumptions
Section titled “Hardware Setup Assumptions”The following hardware setup is assumed. Adjust to your own where the specifics differ.
- NVMe Drives: Two NVMe SSDs in a RAID 1 array, hosting the operating system, swap, and boot partition.
- HDDs: Four hard disk drives in a RAID 5 array for bulk data storage, providing redundancy with one drive of fault tolerance.
- Network: A network interface with a routed public IPv6
/64from your provider. - Resources: At least 4 CPU cores and 8 GB RAM. A fully featured AIO install can run up to around 14 containers (a master, five core services, and several optional add-ons), so more resources help.
Prerequisites
Section titled “Prerequisites”- OS: Ubuntu 24.04 LTS (Noble), 64-bit. The same steps also work on 22.04 LTS (Jammy).
- Software: Docker Engine from the official Docker APT repository (not the Snap package),
mdadm, and basic system tools. - Network: Public IPv4 and, ideally, a routed IPv6
/64. - Access: Root or sudo on the host.
Step 1: Set Up Software RAID
Section titled “Step 1: Set Up Software RAID”NVMe RAID 1 is typically pre-configured by the hosting provider. This step covers building the RAID 5 array on the HDDs for Nextcloud data.
1.1 Verify Current Block Devices
Section titled “1.1 Verify Current Block Devices”lsblkConfirm the NVMe drives are already part of the existing arrays (/dev/md0 for swap, /dev/md1 for /boot, /dev/md2 for /) and that the HDDs (sda, sdb, sdc, sdd) are unused.
1.2 Create the RAID 5 Array
Section titled “1.2 Create the RAID 5 Array”mdadm --create --verbose /dev/md3 --level=5 --raid-devices=4 /dev/sda /dev/sdb /dev/sdc /dev/sddMonitor build progress:
cat /proc/mdstatFormat the array (this may take a long time on large arrays):
mkfs.ext4 /dev/md31.3 Mount the Array Persistently
Section titled “1.3 Mount the Array Persistently”mkdir /datamount /dev/md3 /dataGet the array UUID:
blkid /dev/md3Add to /etc/fstab using that UUID (replace with your own):
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults 0 0Test the fstab entry:
mount -a1.4 Persist the RAID Configuration
Section titled “1.4 Persist the RAID Configuration”mdadm --detail --scan | grep md3 | tee -a /etc/mdadm/mdadm.confupdate-initramfs -uThis ensures the array is assembled correctly on every boot.
Step 2: Install Docker Engine
Section titled “Step 2: Install Docker Engine”Install Docker from the official Docker APT repository. Do not use the Ubuntu Snap package. Its sandboxing causes problems with bind mounts, networks, and AIO’s container management.
2.1 Add the Docker APT Repository
Section titled “2.1 Add the Docker APT Repository”apt-get updateapt-get install ca-certificates curlinstall -m 0755 -d /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.ascchmod a+r /etc/apt/keyrings/docker.ascecho "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/nullapt-get update2.2 Install Docker
Section titled “2.2 Install Docker”apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin2.3 Verify the Install
Section titled “2.3 Verify the Install”docker run hello-worldStep 3: Configure Docker daemon.json (DNS + IPv6)
Section titled “Step 3: Configure Docker daemon.json (DNS + IPv6)”This is the most important step and the one most likely to be done incorrectly. There are two issues to solve at the Docker daemon level.
3.1 Why DNS Configuration Matters
Section titled “3.1 Why DNS Configuration Matters”Ubuntu 24.04 (and 22.04 before it) uses systemd-resolved, which puts 127.0.0.53 in the host’s /etc/resolv.conf as a stub resolver. When Docker copies this resolv.conf into containers, the loopback address resolves to the container itself rather than the host’s resolver, and DNS resolution silently fails inside every container. The AIO master container’s first action on startup is a curl to ghcr.io to check for updates, so this DNS failure causes the master to crash-loop indefinitely.
The fix is to explicitly set DNS servers in daemon.json so every container gets working resolvers regardless of what is in the host’s resolv.conf.
3.2 Why the Default IPv6 Example Is Wrong
Section titled “3.2 Why the Default IPv6 Example Is Wrong”Many guides (including older versions of this one) use 2001:db8:1::/64 as the fixed-cidr-v6 value. This is the RFC 3849 documentation prefix, which is reserved for use in examples and must never appear on a production network. Containers assigned addresses in this range cannot route to the internet, because no router on the internet will accept traffic from or send traffic to this prefix.
The correct approach is to sub-allocate a slice from your provider’s routed /64.
3.3 Determine Your IPv6 Sub-Prefix
Section titled “3.3 Determine Your IPv6 Sub-Prefix”Check what IPv6 prefix your host has:
ip -6 addr show scope globalLook for the public IPv6 on your main network interface. On a typical dedicated cloud server it often looks like 2a01:4f8:13b:3004::2/64, meaning your provider has routed 2a01:4f8:13b:3004::/64 to the server. This value is an example only; substitute your provider’s actual routed prefix.
Pick a /80 sub-prefix from inside this /64 that does not conflict with the host’s own address. A safe pattern is to use a discriminator nibble like :1::/80, giving:
2a01:4f8:13b:3004:1::/80Replace 2a01:4f8:13b:3004 with your own prefix.
3.4 Write the daemon.json
Section titled “3.4 Write the daemon.json”cat > /etc/docker/daemon.json <<'EOF'{ "ipv6": true, "fixed-cidr-v6": "2a01:4f8:13b:3004:1::/80", "ip6tables": true, "default-network-opts": { "bridge": { "com.docker.network.enable_ipv6": "true" } }, "dns": ["1.1.1.1", "8.8.8.8"]}EOF3.5 Apply
Section titled “3.5 Apply”systemctl restart docker3.6 Verify IPv6 Works in a Container
Section titled “3.6 Verify IPv6 Works in a Container”docker run --rm alpine sh -c "ip -6 addr show eth0 && ping6 -c 2 ipv6.google.com"You should see that the container has a public address in your sub-prefix (for example 2a01:4f8:13b:3004:1::3/80) and that ping6 succeeds with reasonable latency.
Step 4: Install Nextcloud AIO
Section titled “Step 4: Install Nextcloud AIO”Deploy the AIO master container with the data directory pointed at the RAID 5 array.
4.1 Prepare the Data Directory
Section titled “4.1 Prepare the Data Directory”AIO expects the data directory to be owned by UID 33 (which is www-data inside the AIO Nextcloud container):
mkdir -p /data/ncdatachown 33:0 /data/ncdatachmod 750 /data/ncdata4.2 Run the Master Container
Section titled “4.2 Run the Master Container”docker run -d \ --init \ --sig-proxy=false \ --name nextcloud-aio-mastercontainer \ --restart always \ --publish 80:80 \ --publish 8080:8080 \ --publish 8443:8443 \ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \ --volume /var/run/docker.sock:/var/run/docker.sock:ro \ --env NEXTCLOUD_DATADIR="/data/ncdata" \ ghcr.io/nextcloud-releases/all-in-one:latestThe --restart always flag ensures the master comes back up automatically on reboot or after a Docker daemon restart.
Note on DNS: Because DNS servers were set in daemon.json in Step 3, the master container inherits working DNS automatically. If you did not complete Step 3, you would need to add --dns 1.1.1.1 --dns 8.8.8.8 to this docker run command to avoid the crash-loop described earlier.
4.3 Confirm the Master Is Healthy
Section titled “4.3 Confirm the Master Is Healthy”docker ps | grep nextcloud-aio-mastercontainerExpected: Up X seconds (healthy). If you see Restarting, check the logs with docker logs nextcloud-aio-mastercontainer to diagnose.
Step 5: Configure the Firewall
Section titled “Step 5: Configure the Firewall”Open the ports AIO needs, plus your chosen SSH port:
ufw allow 80,443,8080,8443,3478,2222/tcpufw allow 3478/udpufw reloadufw enableAdjust 2222 to whichever non-standard port your SSH service listens on. Ensure IPv6 is also enabled in UFW: check /etc/default/ufw for IPV6=yes.
Port summary:
- 80: HTTP (used by the AIO Apache container for ACME/Let’s Encrypt challenges and HTTP-to-HTTPS redirects).
- 443: HTTPS (the main Nextcloud entry point, served by the AIO Apache container).
- 8080: AIO management interface (self-signed cert; see the HSTS note below).
- 8443: AIO management interface, alternate.
- 3478/tcp+udp: Nextcloud Talk STUN/TURN.
Step 6: First Access to the AIO Interface
Section titled “Step 6: First Access to the AIO Interface”6.1 Access Via Server IP, Not Domain
Section titled “6.1 Access Via Server IP, Not Domain”The AIO management interface uses a self-signed certificate by design. Once Nextcloud is set up and HSTS is enabled on the domain (which it will be), browsers refuse to accept the self-signed cert on port 8080 even though it is a different port. Always access the AIO interface using the server IP, not the domain name:
https://<your-server-ipv4>:8080For example: https://203.0.113.10:8080 (the address shown here is an example; use your own). Accept the self-signed certificate warning in your browser. Use HTTPS, not HTTP.
6.2 Retrieve the AIO Passphrase
Section titled “6.2 Retrieve the AIO Passphrase”The AIO interface displays a one-time generated passphrase on first run. If you missed it or need to retrieve it later, run the following on the host:
docker exec nextcloud-aio-mastercontainer grep password /mnt/docker-aio-config/data/configuration.jsonSave this passphrase in your password manager. It is required for every login to the AIO management interface.
6.3 Complete the Setup Wizard
Section titled “6.3 Complete the Setup Wizard”Log in, enter your Nextcloud domain name, select the optional containers you want (Office, Talk, Whiteboard, and so on), and confirm the data directory shows /data/ncdata.
6.4 Start the Containers
Section titled “6.4 Start the Containers”This step is missed easily. After completing the wizard, you must click Start containers in the AIO interface to begin pulling and launching the child containers (Apache, Nextcloud, PostgreSQL, Redis, and any optional add-ons). The initial pull takes 10 to 20 minutes depending on bandwidth, since AIO pulls a dozen or more container images.
Monitor progress in the AIO interface (the indicators turn green as each container becomes healthy) or from the host:
docker psStep 7: Post-Installation
Section titled “Step 7: Post-Installation”7.1 Verify Everything Is Up
Section titled “7.1 Verify Everything Is Up”docker psdocker logs nextcloud-aio-mastercontainerls -l /data/ncdataYou should see the master container plus its child containers: the five core services (Apache, Nextcloud, PostgreSQL, Redis, and Notify Push) and any optional add-ons you enabled. All should be Up and, eventually, (healthy). The data directory will contain Nextcloud’s data files owned by UID 33.
7.2 Enable Backups
Section titled “7.2 Enable Backups”Configure the backup target in the AIO interface (a local /mnt/backup path or a remote borg repository). Daily backups are recommended.
7.3 Updates
Section titled “7.3 Updates”Future updates of Nextcloud and all child containers are performed via the Stop containers then Start and update containers sequence in the AIO interface. Do not attempt to update child containers directly from the command line, because AIO is the authoritative manager.
7.4 Reboot Persistence
Section titled “7.4 Reboot Persistence”To confirm the install survives a reboot, run reboot on the host and verify that after the host comes back, docker ps shows all containers Up within 1 to 2 minutes. The master comes back via --restart always and starts the children automatically.
Troubleshooting
Section titled “Troubleshooting”Master Container Crash-Looping
Section titled “Master Container Crash-Looping”If docker ps -a | grep mastercontainer shows Restarting:
docker logs --tail 30 nextcloud-aio-mastercontainerLook for Could not resolve host: ghcr.io, which indicates the DNS problem described in Step 3. Verify /etc/docker/daemon.json contains the "dns" entry and that systemctl restart docker was run after the change.
AIO Interface Unreachable
Section titled “AIO Interface Unreachable”If https://<server-ip>:8080 times out:
- Confirm UFW allows port 8080 (
ufw status). - Confirm any provider-level firewall (for example a cloud firewall in your provider’s control panel) also allows port 8080 inbound.
- Confirm the master container is up and bound to 8080 (
docker ps).
HSTS Blocks the AIO Interface
Section titled “HSTS Blocks the AIO Interface”If your browser shows SEC_ERROR_UNKNOWN_ISSUER with no “Accept Risk and Continue” option when accessing https://<your-nextcloud-domain>:8080, this is HSTS blocking. Use the server’s IP address instead of the domain name. HSTS is hostname-bound, so the IP is unaffected.
IPv6 Not Working in Containers
Section titled “IPv6 Not Working in Containers”Verify the container actually got an address in your sub-prefix:
docker run --rm alpine ip -6 addrIf the container’s IPv6 is in a different range than expected, recheck daemon.json and confirm systemctl restart docker was run. If containers have addresses but cannot ping external IPv6 hosts, check that ip6tables: true is set in daemon.json and that the host itself has working outbound IPv6.
Data Directory Permissions
Section titled “Data Directory Permissions”If AIO complains it cannot write to the data directory:
chown 33:0 /data/ncdatachmod 750 /data/ncdataUID 33 corresponds to the www-data user inside the AIO Nextcloud container.
Automation Script
Section titled “Automation Script”The following script automates Steps 3 and 4 (daemon.json configuration and master container launch). It assumes Docker is already installed (Step 2) and the data partition is mounted at /data (Step 1). Edit the IPV6_PREFIX variable to match your own routed IPv6 sub-prefix before running.
#!/bin/bashset -e
# === Edit this to match your environment ===IPV6_PREFIX="2a01:4f8:13b:3004:1::/80"DATA_DIR="/data/ncdata"# ============================================
echo "Writing /etc/docker/daemon.json..."cat > /etc/docker/daemon.json <<EOF{ "ipv6": true, "fixed-cidr-v6": "${IPV6_PREFIX}", "ip6tables": true, "default-network-opts": { "bridge": { "com.docker.network.enable_ipv6": "true" } }, "dns": ["1.1.1.1", "8.8.8.8"]}EOF
echo "Restarting Docker..."systemctl restart docker
echo "Verifying IPv6 in a test container..."docker run --rm alpine sh -c "ip -6 addr show eth0 | grep inet6"
echo "Preparing data directory at ${DATA_DIR}..."mkdir -p "${DATA_DIR}"chown 33:0 "${DATA_DIR}"chmod 750 "${DATA_DIR}"
echo "Launching Nextcloud AIO master container..."docker run -d \ --init \ --sig-proxy=false \ --name nextcloud-aio-mastercontainer \ --restart always \ --publish 80:80 \ --publish 8080:8080 \ --publish 8443:8443 \ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \ --volume /var/run/docker.sock:/var/run/docker.sock:ro \ --env NEXTCLOUD_DATADIR="${DATA_DIR}" \ ghcr.io/nextcloud-releases/all-in-one:latest
echo "Done. Access the AIO interface at https://$(hostname -I | awk '{print $1}'):8080"echo "Retrieve the AIO passphrase with:"echo " docker exec nextcloud-aio-mastercontainer grep password /mnt/docker-aio-config/data/configuration.json"Save as setup_nextcloud_aio.sh, make it executable, and run:
chmod +x setup_nextcloud_aio.sh./setup_nextcloud_aio.shSupport
Section titled “Support”For Noiz hosting customers, open a support ticket via the client area at www.noiz.co.za with the output of docker ps -a, docker logs nextcloud-aio-mastercontainer, and a description of the symptoms.

