Skip to content
appsgit

Deploy guide

How to self-host Nextcloud with Docker Compose

Install Nextcloud with Docker Compose, Postgres and Redis: trusted domains, background cron jobs, HTTPS reverse proxy, backups and safe major upgrades.

  • Updated
  • Intermediate
  • About 30 minutes

You will need

  • 2 vCPU / 4 GB RAM
  • Docker + Docker Compose v2
  • Storage for your files (local disk or attached volume)
  • A domain name with HTTPS

What is Nextcloud?

Nextcloud is a self-hosted content collaboration platform for file sync and sharing, calendars, contacts, notes and video calls. It is open source under the AGPL-3.0 license and has desktop sync clients for Windows, macOS and Linux plus mobile apps for iOS and Android. Its app store adds hundreds of extensions, from office suites to password managers.

Requirements

  • A Linux server with 2 vCPU and 4 GB of RAM for a household or small team.
  • Docker Engine and Docker Compose v2.
  • Enough disk for your files. Put the data volume on the largest disk.
  • A domain name. Nextcloud clients expect a stable HTTPS URL.

Step 1: Prepare the server

This guide assumes Ubuntu 24.04 with Docker installed. If needed, follow the Docker Engine install guide. Create a project folder:

mkdir -p ~/nextcloud && cd ~/nextcloud

Nextcloud also offers All-in-One, which is the officially recommended route and manages everything for you. This guide uses the community-maintained nextcloud image instead, which keeps the stack as a normal Compose file.

Step 2: Create the Docker Compose file

The stack has four containers: Postgres for the database, Redis for file locking and caching, the Nextcloud app, and a cron container that runs background jobs every five minutes. Save as docker-compose.yml:

services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: nextcloud
      POSTGRES_USER: nextcloud
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - db:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}

  app:
    image: nextcloud:35-apache
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    depends_on:
      - db
      - redis
    environment:
      POSTGRES_HOST: db
      POSTGRES_DB: nextcloud
      POSTGRES_USER: nextcloud
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      REDIS_HOST: redis
      REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
      NEXTCLOUD_ADMIN_USER: admin
      NEXTCLOUD_ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com
      OVERWRITEPROTOCOL: https
      OVERWRITECLIURL: https://cloud.example.com
      TRUSTED_PROXIES: 172.16.0.0/12
      PHP_MEMORY_LIMIT: 1G
      PHP_UPLOAD_LIMIT: 16G
    volumes:
      - nextcloud:/var/www/html

  cron:
    image: nextcloud:35-apache
    restart: unless-stopped
    entrypoint: /cron.sh
    depends_on:
      - db
      - redis
    volumes:
      - nextcloud:/var/www/html

volumes:
  db:
  nextcloud:

Create .env next to it:

POSTGRES_PASSWORD=CHANGE_ME
REDIS_PASSWORD=CHANGE_ME
ADMIN_PASSWORD=CHANGE_ME

Generate each value with openssl rand -hex 32. Save the admin password in your password manager. The NEXTCLOUD_ADMIN_* variables and database settings are only read on the very first start, when Nextcloud installs itself. After that, configuration lives in config/config.php inside the volume.

The 35-apache tag follows the latest 35.x release, so patch updates arrive with docker compose pull, while major upgrades stay under your control.

Step 3: Start and open the app

docker compose up -d
docker compose logs -f app

The first start copies Nextcloud into the volume and runs the installer, which takes a minute or two. When the log shows Apache running, finish Step 4 and open https://cloud.example.com. Sign in as admin with the password from .env. Go to Administration settings, Basic settings, and confirm background jobs are set to "Cron". Then visit Overview, where Nextcloud runs its security and setup checks.

Step 4: Put it behind HTTPS

With Caddy on the host:

cloud.example.com {
    request_body {
        max_size 16GB
    }
    redir /.well-known/carddav /remote.php/dav/ 301
    redir /.well-known/caldav /remote.php/dav/ 301
    reverse_proxy 127.0.0.1:8080
}

The .well-known redirects let calendar and contacts apps discover the server. TRUSTED_PROXIES covers Docker's default bridge networks so Nextcloud sees real client IPs. Add the Strict-Transport-Security header once you are sure HTTPS works.

Backups and upgrades

Back up three things: the database (docker compose exec db pg_dump -U nextcloud nextcloud > nextcloud.sql), the nextcloud volume (which holds config/ and data/), and your .env. Put Nextcloud in maintenance mode during the backup for consistency:

docker compose exec -u www-data app php occ maintenance:mode --on
# run your backup
docker compose exec -u www-data app php occ maintenance:mode --off

For patch updates, run docker compose pull && docker compose up -d. For a major upgrade, change the image tag by exactly one version (for example 35-apache to 36-apache) in both services, then pull and start. The container runs the upgrade automatically.

Troubleshooting

  • "Access through untrusted domain": add your domain with docker compose exec -u www-data app php occ config:system:set trusted_domains 1 --value=cloud.example.com.
  • Login loops or wrong redirect URLs: OVERWRITEPROTOCOL must be https behind a TLS proxy. Set it in config.php if the volume already existed.
  • Large uploads fail: raise PHP_UPLOAD_LIMIT and the proxy body size limit together.
  • Warnings about missing indices after an upgrade: run docker compose exec -u www-data app php occ db:add-missing-indices.

Next steps

Install the desktop and mobile sync clients, enable two-factor authentication, add Nextcloud Office or Collabora for document editing, and configure an SMTP server for notifications.

Spotted something out of date? Tell us and we will update the guide.

FAQ

Nextcloud questions

Still curious? Email info@appsgit.com.

What port does Nextcloud use?

The official Apache-based image serves Nextcloud on port 80 inside the container. This guide maps it to port 8080 on the host and puts an HTTPS reverse proxy in front.

Is Nextcloud free?

Yes. Nextcloud Hub is free and open source under the AGPL-3.0 license. Nextcloud GmbH sells enterprise support subscriptions, but the self-hosted software is fully usable without one.

Should I use Nextcloud AIO or the community Docker image?

Nextcloud All-in-One is the officially recommended method and manages its own containers, backups and updates. The community image used in this guide gives you a plain Compose stack that you control fully and that fits next to other services.

Can I skip Nextcloud major versions when upgrading?

No. Nextcloud only supports upgrading one major version at a time, for example 34 to 35. Step through each major version in order.

Nextcloud vs Google Drive?

Nextcloud covers file sync and sharing like Google Drive, and adds calendars, contacts, office editing and video calls through apps, all on your own server. You trade Google's zero maintenance for full control of your data.