Kituwa IT · Self-hosting guides

Install Nextcloud with Docker Compose

Self-hosted file sync and collaboration

file syncofficecalendar

Nextcloud is the closest thing the FOSS world has to Google Drive, Office 365 and a contacts app in one box. Files sync across desktop, web and mobile, and it adds document editing, shared calendars, contacts, video calls and an app store on top.

Category
Files & sync
License
AGPL-3.0
Needs
MariaDB + Redis
Image
nextcloud:apache

What it is

Files land on your own disk and stay there. Clients sync opportunistically, so a flaky mobile connection doesn't lose work. You get versioning, end-to-end-encrypted folders, CalDAV/CardDAV, Talk video calls, and a plugin ecosystem that's been compounding for a decade.

Before you start

  • A domain with an A record pointing at the host. Trustworthy TLS is not optional for Nextcloud — the clients refuse plain HTTP.
  • Generate real secrets now: openssl rand -base64 24, four times, one per placeholder.
  • Pick a stable data directory on a real disk. If ./app is on the root filesystem you'll eventually fill it and corrupt your install.

1 — Create the data directories

Command / configuration
mkdir -p ~/services/nextcloud/{app,db}
cd ~/services/nextcloud

2 — Write the compose file

Command / configuration
services:
  db:
    image: mariadb:11.4
    container_name: nextcloud-db
    restart: unless-stopped
    command: >-
      --transaction-isolation=READ-COMMITTED
      --log-bin=binlog
      --binlog-format=ROW
    volumes:
      - ./db:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: CHANGE_ME_root
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: CHANGE_ME_nextcloud
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 30s
      timeout: 5s
      retries: 3

  redis:
    image: redis:7-alpine
    container_name: nextcloud-redis
    restart: unless-stopped
    command: redis-server --requirepass CHANGE_ME_redis --save ""
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "CHANGE_ME_redis", "ping"]
      interval: 30s
      timeout: 5s
      retries: 3

  app:
    image: nextcloud:apache
    container_name: nextcloud
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./app:/var/www/html
    environment:
      MYSQL_HOST: db
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: CHANGE_ME_nextcloud
      REDIS_HOST: redis
      REDIS_PASSWORD: CHANGE_ME_redis
      NEXTCLOUD_ADMIN_USER: CHANGE_ME_admin
      NEXTCLOUD_ADMIN_PASSWORD: CHANGE_ME_adminpass
      TRUSTED_PROXIES: 172.16.0.0/12
      OVERWRITEPROTOCOL: https
      OVERWRITEHOST: cloud.example.com
      OVERWRITECLIURL: https://cloud.example.com/
      OVERWRITECLIURL_PORT: 443
      PHP_MEMORY_LIMIT: 512M
      PHP_UPLOAD_LIMIT: 16G
Why 172.16.0.0/12 in TRUSTED_PROXIESIf anything sits in front of Nextcloud, it has to be declared trusted or you'll spend an afternoon debugging "client IP is 172.20.0.1" errors in the security settings.

3 — Start it

Command / configuration
docker compose up -d
docker compose logs -f app | grep -i "Nextcloud is now ready\|finished"

First boot unpacks roughly 400 MB and takes a minute or two. Wait for the "Nextcloud is now ready" line before you trust the health.

4 — First-run setup

  1. Put a reverse proxy in front of 127.0.0.1:8080 and issue a real certificate. See Nginx Proxy Manager for the easy route, or Caddy if you'd rather not manage a UI.
  2. Create the first admin account in the browser. The NEXTCLOUD_ADMIN_* values above only apply if the database was completely empty at boot — if the install wizard still shows, the installer is running normally and you can ignore them.
  3. Run the security and integrity checks from the admin panel. Fix anything red. Setup warnings are almost always the admin password being weak or a missing setdefault mail config.
  4. Add cloud.example.com to Settings → Administration → Security → Trusted domains if you ever see "untrusted domain" on any client.

5 — Lock it down and maintain it

Command / configuration
docker exec -u www-data -it nextcloud php occ config:system:set \
  mail_smtpmode smtp
docker exec -u www-data -it nextcloud php occ background:cron
docker exec -u www-data -it nextcloud php occ security:setup-app-password admin
The two mistakes everyone makes1. No backups. A Nextcloud config/ + data/ + database dump is all you need. 2. Leaving OVERWRITECLIURL on the default — cron jobs and share links then generate http://localhost URLs that nobody can click.

Help when you need it

Want help getting this running?

We can help with a supported Linux host, application setup, migration or troubleshooting. Contact us to confirm the software, scope and scheduling before ordering.

Related guides

← Browse all 30 guides · Back to top