Self-Hosting·8 min read·

Setting Up Nextcloud for File Sync and Backup

Deploy Nextcloud with Docker Compose to self-host file sync and backup, then tune clients, cron jobs, caching, and storage backups on your VPS.

NB

Netbay Cloud Team

Netbay Engineering

On this page

Nextcloud is the reference self-hosted replacement for Dropbox or Google Drive. It gives you file sync on every desktop and phone, a built-in text editor, calendar, contacts, and a growing app store — all running on hardware you control. For privacy-conscious teams and solo builders, it is the most turnkey way to own your data plane.

The pitch is simple: instead of renting a folder on someone else's servers, you run the whole service and keep the files where you can see them. You control retention, sharing links, who can log in, and when old versions of documents get purged. There is no per-user price tag and no surprising quota that appears when you actually need space.

Setting it up well on a VPS is less about the install and more about storage layout, background jobs, and sync clients. This guide walks through a stable Compose deployment and the config that keeps sync reliable at scale.

Nextcloud sync architecture desktop client desktop mobile client mobile Nextcloud app webdav + occ apache SQL MariaDB metadata ./data files + backup tarball

The Core Compose Setup

A healthy Nextcloud needs three roles: the web app, a database, and a cache. We add Redis because Nextcloud's locking and preview machinery crawl without it. Without a shared cache, every instance fights over the same metadata and performance collapses under load.

yaml
services:
  app:
    image: nextcloud:29-apache
    container_name: nextcloud
    environment:
      - NEXTCLOUD_ADMIN_USER=admin
      - NEXTCLOUD_ADMIN_PASSWORD=choose-a-strong-one
      - MYSQL_HOST=db
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_PASSWORD=secret-db-pass
      - REDIS_HOST=redis
    volumes:
      - ./html:/var/www/html
      - ./data:/var/www/html/data
    ports:
      - "127.0.0.1:8080:80"
    restart: unless-stopped

  db:
    image: mariadb:11
    environment:
      - MARIADB_ROOT_PASSWORD=root-secret
      - MARIADB_DATABASE=nextcloud
      - MARIADB_USER=nextcloud
      - MARIADB_PASSWORD=secret-db-pass
    volumes:
      - ./db:/var/lib/mysql
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

Two volume decisions matter. The html volume holds application code, so upgrades become a simple matter of swapping the image and running a migration. The data volume holds your actual files and must be treated as precious and irreplaceable. Keep them separate so you can snapshot just the data layer and restore it independently of the code.

Because the app and database talk over a private Docker network, never publish the MariaDB or Redis ports to the host. Only the web app needs to accept external traffic, and it should do so only through the reverse proxy. Treat the container environment variables as the place where secrets live only in development; for anything that resembles production, move database credentials into a separate .env file and keep it out of version control.

For upgrades, the flow is deliberately boring: pull the new image, restore the html volume from the previous app code if a migration fails, and run the occ upgrade step the container prompts for. Pin to a major image tag and test each upgrade on a scratch instance first if you run many apps.

Background Jobs & CLI Maintenance

Nextcloud schedules maintenance like file scanning and preview generation. Rely on the built-in cron rather than Ajax pings for predictable behaviour, especially once the library grows past a few thousand files. The web UI exposes the scheduler choice, but the actual trigger belongs in the host crontab.

php
# set the scheduler from the web admin: Settings -> Basic settings -> Background jobs -> Cron
# then add this to the host crontab:
*/5 * * * * docker exec -u www-data nextcloud php cron.php

Verify your instance from the command line with the occ tool, which every admin should learn. It is the same binary that runs in the container, and it handles configuration, file scanning, and repair without touching the web UI:

bash
docker exec -u www-data nextcloud php occ status
docker exec -u www-data nextcloud php occ files:scan --all
docker exec -u www-data nextcloud php occ maintenance:repair

Sync Clients and Overrides

Desktop clients handle large trees poorly unless you configure chunking and exclusions. The desktop app supports exclude patterns, and Nextcloud's config file lets you tune server-side behavior to match. A sensible override adds the caching and locking backends plus the public URL:

ini
; config/config.php
'overwrite.cli.url' => 'https://cloud.example.com',
'default_phone_region' => 'IN',
'memcache.local' => '\OC\Memcache\Redis',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'http_limiter' => ['rate' => 800, 'burst' => 1000],

Set the correct overwrite.cli.url so sync clients and web URLs always resolve the public hostname. Without it, files sync over internal LAN IPs and break for remote users, a classic silent failure that is hard to diagnose later.

Backing Up the Data Layer

The database and the file tree must be treated as one unit, because Nextcloud stores file metadata in the database and file contents on disk. A simple rolling backup script dirties neither in place:

bash
#!/usr/bin/env bash
STAMP=$(date +%Y%m%d)
docker exec -u www-data nextcloud php occ maintenance:mode --on
mysqldump nextcloud > /backups/nextcloud-$STAMP.sql
tar -czf /backups/files-$STAMP.tgz ./data
docker exec -u www-data nextcloud php occ maintenance:mode --off

Test restores on a scratch instance before you trust any backup. Off-site the archive to a second region or an object store if your workflow can tolerate the latency, since a file service's true test is whether you can recover a specific document after a failure.

Takeaway

Nextcloud on a VPS replaces a commercial storage subscription with a self-owned sync layer, calendar, and document suite. Fast SSD storage pays off here because previews and file chunks are read-heavy, and the whole stack is manageable by a single admin.

You can get a 2 GB Ubuntu instance on Netbay with High-Speed SSD storage in under a minute and deploy this stack — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance