This documentation describes the step-by-step process to deploy Nextcloud All-in-One (AIO) on a Proxmox VM, exposed securely via an Nginx reverse proxy running on the Proxmox host.
The Nextcloud AIO mastercontainer does not serve Nextcloud itself — it only manages sibling containers. The actual Nextcloud interface is served by the Apache sibling container on port 11000. Do not confuse port 8080 (AIO management UI) with port 11000 (Nextcloud).
$ dig drive.yourdomain.com
docker exec certbot certbot certonly --webroot \ -w /var/www/certbot \ -d drive.yourdomain.com \ --email your@email.com \ --agree-tos --non-interactive
/etc/letsencrypt/live/drive.yourdomain.com/fullchain.pem /etc/letsencrypt/live/drive.yourdomain.com/privkey.pem
$ nano /etc/nginx/conf.d/drive.yourdomain.com.conf
upstream drive_backend { server 192.168.1.121:11000; } server { server_name drive.yourdomain.com; listen 80; return 301 https://$host$request_uri; } server { server_name drive.yourdomain.com; listen 443 ssl http2; ssl_certificate /etc/letsencrypt/live/drive.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/drive.yourdomain.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_pass http://drive_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-Host $host; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; client_max_body_size 0; proxy_read_timeout 600s; proxy_send_timeout 600s; } location /.well-known/acme-challenge/ { root /var/www/certbot; auth_basic off; allow all; try_files $uri =404; } }
$ docker exec nginx nginx -s reload
$ ssh sysadm@192.168.1.121
$ mkdir ~/nextcloud-aio && cd ~/nextcloud-aio $ nano compose.yaml
name: nextcloud-aio services: nextcloud-aio-mastercontainer: image: ghcr.io/nextcloud-releases/all-in-one:latest init: true restart: always container_name: nextcloud-aio-mastercontainer volumes: - nextcloud_aio_mastercontainer:/mnt/docker-aio-config - /var/run/docker.sock:/var/run/docker.sock:ro network_mode: bridge ports: - 80:80 - 8080:8080 - 8443:8443 # Do NOT add 11000:11000 here — Apache sibling container binds it automatically environment: APACHE_PORT: 11000 SKIP_DOMAIN_VALIDATION: true volumes: nextcloud_aio_mastercontainer: name: nextcloud_aio_mastercontainer
Do not add port 11000:11000 to the mastercontainer's ports section. The Apache sibling container binds this port on its own. Adding it to the mastercontainer will cause a port conflict and prevent the domain check from passing.
$ docker compose up -d
Since the VM is terminal-only, use an SSH tunnel from your local machine to access the AIO web UI:
$ ssh -L 9821:192.168.1.121:8080 admin@your-proxmox-host
https://localhost:9821
$ sudo docker exec nextcloud-aio-mastercontainer \ cat /mnt/docker-aio-config/data/configuration.json | python3 -m json.tool | grep -i password
$ ss -tlnp | grep 11000
$ curl -I http://192.168.1.121:11000
https://drive.yourdomain.com
| Error | Cause | Fix |
|---|---|---|
Connection reset by peer | Nginx sending plain HTTP to an HTTPS backend | Use proxy_pass http: since Nginx terminates SSL |
SSL handshake failed (alert 80) | Caddy inside AIO trying to get its own cert, failing | Set APACHE_PORT and SKIP_DOMAIN_VALIDATION: true in compose |
Connection refused on port 11000 | Apache sibling container not started yet, or port conflict | Complete AIO setup via the web UI; remove 11000:11000 from mastercontainer ports |
Domain check container not running | Port 11000 already bound by mastercontainer | Remove - 11000:11000 from compose ports section and restart |
Wrong login or password | AIO passphrase ≠ Nextcloud admin password | Use credentials from “reveal initial credentials” button in AIO UI |
— Nadir Habib 2026/02/22 13:13