How to back up and restore Nextcloud
Nextcloud's admin manual backs up five things: the config folder, the data folder, the custom apps and theme folders, and the database. Turn on maintenance mode with occ maintenance:mode --on, copy the folders with rsync, dump the database with --single-transaction, then turn it off. config/config.php holds the secret and instanceid that encrypted data and sessions depend on, so a data backup without it is incomplete.
What to back up
| Part | Where | Holds |
|---|---|---|
| Config | config/ in the install directory | config.php: database password, secret, passwordsalt, instanceid. |
| Data | datadirectory in config.php, data/ by default | Users' files, versions, deleted files, the hidden .ncdata file, and encryption keys. |
| Apps you installed | The folder apps_paths in config.php names | Needed only if you added apps. |
| Themes | themes/ | Custom themes. |
| Database | MySQL/MariaDB, PostgreSQL or SQLite | Users, shares, file metadata, calendars and contacts. |
The simplest way to cover all of it is the manual's alternative: copy the whole installation directory, which also brings back the exact Nextcloud version, plus the data directory if it lives elsewhere. Run occ as the web server user, www-data on Debian and Ubuntu, as the manual does. To find the data directory:
sudo -E -u www-data php /var/www/nextcloud/occ config:system:get datadirectorydbtype, dbname, dbhost and dbuser work the same way. Keep the backup's paths: Nextcloud identifies local storage by its absolute path, and its docs say moving the data directory is not supported without database edits.
The manual says secret and instanceid are tied to all encrypted data and user sessions and must be copied verbatim. With server-side encryption on, the keys live in data/files_encryption and data/<user>/files_encryption, and losing them or the secret means permanent data loss. Keep config.php with every data backup, and keep both private.
Turn on maintenance mode
sudo -E -u www-data php /var/www/nextcloud/occ maintenance:mode --onThis locks the sessions of logged-in users, blocks new logins and shows a maintenance page, so files and database cannot drift apart while you copy them. Setting 'maintenance' => true in config.php does the same.
Copy the folders
The manual's command, here writing to a backup disk mounted at /mnt/backup:
rsync -Aavx /var/www/nextcloud/ /mnt/backup/nextcloud-dirbkp_$(date +%Y%m%d)/-acopies recursively and keeps permissions, owners, timestamps and symlinks. Timestamps matter: the manual warns that clients re-download every file if they change.-Akeeps ACLs.-vlists each file.-xstays on one filesystem. Ifdatais a separate disk mounted inside the install directory,-xskips its contents: copy it with its own rsync.- The trailing slash on the source copies its contents rather than the directory itself.
Maintenance mode lasts as long as the copy. To shorten it, add --delete to the rsync, run it once while Nextcloud is online, then turn maintenance mode on and run it again: the second pass only transfers what changed. Only that second pass is consistent.
Each run makes a full copy. The script below keeps daily history with hard links instead, and restic or Borg add deduplication and encryption.
Dump the database
Do this while maintenance mode is still on. For MySQL or MariaDB, put the credentials from config.php in an option file so the password stays out of ps:
[client]
user=nextcloud
password="your-password-here"
host=localhostchmod 600 /etc/mysql/nextcloud-backup.cnfmysqldump --defaults-extra-file=/etc/mysql/nextcloud-backup.cnf --single-transaction --default-character-set=utf8mb4 --no-tablespaces nextcloud | gzip > /mnt/backup/nextcloud-sqlbkp_$(date +%Y%m%d).sql.gz--single-transactiondumps InnoDB tables from one snapshot without locking them.--default-character-set=utf8mb4is the manual's addition when 4-byte support is on, which'mysql.utf8mb4' => truein config.php shows.--no-tablespacesavoids needing the globalPROCESSprivilege, which a Nextcloud user granted only its own database lacks.- On MariaDB,
mariadb-dumptakes the same options, as the manual shows.
PostgreSQL, with the password in ~/.pgpass and -w so a missing password fails instead of prompting:
pg_dump -h localhost -U nextcloud -w -f /mnt/backup/nextcloud-sqlbkp_$(date +%Y%m%d).sql nextcloudSQLite keeps the database as a file in the data directory, so the copy above includes it; the manual also dumps it with sqlite3 data/owncloud.db .dump. See the SQLite guide and the mysqldump guide.
Then turn maintenance mode off:
sudo -E -u www-data php /var/www/nextcloud/occ maintenance:mode --offRestore on the same or a new server
The manual is firm: you need the config, the data and the database; you cannot restore without all three. On a new server, first install the web server, a supported PHP with Nextcloud's extensions, the database server, and every service config.php uses, such as Redis. Then copy the files back:
rsync -Aax /mnt/backup/nextcloud-dirbkp_20261003/ /var/www/nextcloud/The database must be empty before the import, so the manual drops and recreates it. As root at the MySQL or MariaDB prompt, with the character set from Nextcloud's database setup guide:
DROP DATABASE IF EXISTS nextcloud;
CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;On a new server, also create the user with the password in config.php, and put the option file from above in place:
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'your-password-here';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost';gunzip -c /mnt/backup/nextcloud-sqlbkp_20261003.sql.gz | mysql --defaults-extra-file=/etc/mysql/nextcloud-backup.cnf nextcloudFor PostgreSQL, drop and recreate the database the same way, then load the dump with psql -h localhost -U nextcloud -d nextcloud -f and the file. On a new server, review config.php before starting: the manual lists dbhost, dbname, dbuser, dbpassword, trusted_domains, overwrite.cli.url, the memcache and Redis settings, mail_smtphost and logfile. Keep datadirectory, secret, instanceid and serverid exactly as they were. Then fix ownership as the install guide does, and restore the background jobs cron entry for www-data:
chown -R www-data:www-data /var/www/nextcloud/*/5 * * * * php -f /var/www/nextcloud/cron.phpA backup taken in maintenance mode restores in maintenance mode, because the flag lives in config.php. Start the web server, check you see the maintenance notice and a clean log, then run occ maintenance:mode --off as above.
Resync clients and rescan files
If the restored data is older than what users' desktop clients hold, run this once:
sudo -E -u www-data php /var/www/nextcloud/occ maintenance:data-fingerprintClients then know a backup was restored: instead of making their copies match the server, they upload files the server lacks and ask users when contents differ. The manual warns it can cause conflict dialogs, so use it only when the backup is outdated, or after a move when the old config.php had a non-empty data-fingerprint. It does not need maintenance mode.
If files and database come from different moments, or files were copied into the data directory by hand, update the file cache:
sudo -E -u www-data php /var/www/nextcloud/occ files:scan --allfiles:scan belongs to the files app, and apps do not load in maintenance mode, so run it after maintenance mode is off.
Verify the restore
sudo -E -u www-data php /var/www/nextcloud/occ statusExpect installed: true, the version you backed up, maintenance: false and needsDbUpgrade: false. For scripts, occ status -e prints nothing and exits 0 when all is well and 1 in maintenance mode. occ integrity:check-core checks core files against Nextcloud's signature. Then log in as a test user, open a few files and a share link, check Calendar and Contacts if you use them, and watch a desktop client sync. Testing restores explains how to rehearse this.
Automate it with cron
This root script follows the manual's order, turns maintenance mode off even if a step fails, and keeps one dated folder per day. --link-dest makes files unchanged since the previous run hard links, so each folder looks complete but only changes take space. If the data directory is outside the install directory, add a second rsync for it.
#!/bin/bash
set -euo pipefail
NC="/var/www/nextcloud"
DEST="/mnt/backup/nextcloud"
KEEP_DAYS=14
TODAY="$DEST/$(date +%F)"
occ() { sudo -u www-data php "$NC/occ" "$@"; }
mkdir -p "$TODAY"
occ maintenance:mode --on
trap 'occ maintenance:mode --off' EXIT
mysqldump --defaults-extra-file=/etc/mysql/nextcloud-backup.cnf \
--single-transaction --default-character-set=utf8mb4 --no-tablespaces \
nextcloud | gzip > "$TODAY/nextcloud-db.sql.gz"
gunzip -c "$TODAY/nextcloud-db.sql.gz" | tail -n 1 | grep -q "Dump completed"
rsync -Aax --delete --link-dest="$DEST/latest/nextcloud" "$NC/" "$TODAY/nextcloud/"
occ maintenance:mode --off
trap - EXIT
ln -sfn "$TODAY" "$DEST/latest"
CUTOFF="$(date -d "-$KEEP_DAYS days" +%F)"
for d in "$DEST"/20??-??-??; do
if [[ "$(basename "$d")" < "$CUTOFF" ]]; then rm -rf -- "$d"; fi
donechmod 700 /usr/local/bin/nextcloud-backup.shPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
30 2 * * * root flock -n /run/lock/nextcloud-backup.lock /usr/local/bin/nextcloud-backup.sh >> /var/log/nextcloud-backup.log 2>&1The first run warns that latest does not exist yet and makes a full copy. Keep /mnt/backup on a different disk from the server's own, then send it off-site with rclone or restic; the cron guide covers alerts.
Nextcloud All-in-One
Nextcloud AIO, the Docker-based install, has its own backup built on BorgBackup and run from the AIO interface: incremental, compressed and encrypted, to a local path or a remote Borg repository, with restores from the same screen. Its default retention is --keep-within=7d --keep-weekly=4 --keep-monthly=6. On AIO, use it instead of the steps above.
Common errors
| Error | Fix |
|---|---|
Access through untrusted domain | Add the hostname to trusted_domains in config.php. |
Your data directory is invalid. | .ncdata is missing from the data directory: the copy skipped hidden files, or datadirectory points elsewhere. Copy with rsync -a, not cp data/*. |
| The maintenance page never goes away | The restored config.php has 'maintenance' => true. Run occ maintenance:mode --off. |
Nextcloud is in maintenance mode, no apps are loaded. | App commands such as files:scan need maintenance mode off. |
| Files are listed but cannot be opened, or are missing | The file cache and the data differ. Run occ files:scan --all. |
| Desktop clients remove files the restored server lacks | Run occ maintenance:data-fingerprint, ideally before clients reconnect, so they upload them instead. |
Redis server went away | Install and configure Redis on the new server, as config.php expects. |
Access denied; you need (at least one of) the PROCESS privilege(s) for this operation | Add --no-tablespaces to mysqldump. |
Frequently asked questions
- Do I need maintenance mode to back up Nextcloud?
- The manual's procedure uses it, so files and database match. Without it, a file uploaded mid-copy can exist in one and not the other; files:scan can repair the file cache afterwards, but shares and metadata may not match.
- Is backing up the data folder enough?
- No. The manual says a restore needs the config, the data and the database. config.php holds the secret that encrypted data depends on, and the database holds shares, calendars and contacts.
- When should I run occ maintenance:data-fingerprint?
- After restoring a backup that is older than the files on users' devices. Clients then upload what the server lost instead of deleting it locally.
- How do I back up a very large Nextcloud data directory?
- Use an incremental tool: rsync with --link-dest, restic or Borg. After the first run each backup copies only changes, which keeps the maintenance window short.
How this was checked
Commands, limits and prices were checked against these official pages, on October 3, 2026:
- Nextcloud Administration Manual: Backup
- Nextcloud Administration Manual: Restoring backup
- Nextcloud Administration Manual: Migrating to a different server
- Nextcloud Administration Manual: Configuration parameters
- Nextcloud Administration Manual: Server-side encryption
- Nextcloud Administration Manual: Using the occ command
- Nextcloud Administration Manual: occ system commands (maintenance, status)
- Nextcloud Administration Manual: occ file commands (files:scan, integrity)
- Nextcloud Administration Manual: occ config commands
- Nextcloud Administration Manual: Database configuration
- Nextcloud Administration Manual: Installation on Linux
- Nextcloud Administration Manual: Background jobs
- Nextcloud Administration Manual: General troubleshooting (data directory)
- Nextcloud All-in-One: Backup
- MySQL 8.4 Reference Manual: mysqldump
- PostgreSQL documentation: pg_dump