Self-hosted • Privacy-first • No tracking
Home / Homelab / Migrate Nextcloud to a New Server: Complete Docker Compose Guide
Homelab #self-hosted#homelab#docker-compose#nextcloud#migration ⏱ 12 min • 👁 2 • Sep 04, 2026

Migrate Nextcloud to a New Server: Complete Docker Compose Guide

Step-by-step guide to migrate Nextcloud to a new server using Docker Compose, including backup, restore, data integrity checks, and common pitfalls.

AdSense — Top (970x90) • Responsive
Migrate Nextcloud to a New Server: Complete Docker Compose Guide

Introduction

Migrating a Nextcloud instance to a new server is a task that many homelab administrators face when upgrading hardware, consolidating services, or moving to a more robust hosting environment. A poorly executed migration can lead to data corruption, broken file sync clients, and hours of troubleshooting. This guide provides a comprehensive, step-by-step approach to migrating Nextcloud using Docker Compose, with a focus on preserving data integrity and minimizing downtime.

You will learn how to back up your existing Nextcloud data and database, set up a new server with Docker and Docker Compose, restore your data with correct file permissions, and verify that everything works as expected. We also cover essential configuration adjustments, reverse proxy setup for SSL, backup strategies, and common errors you may encounter along the way.

By the end of this guide, you will have a fully functional Nextcloud instance on your new server, with all users, files, and settings intact. The instructions are designed for a technical audience familiar with Linux, Docker, and basic networking concepts.

Prerequisites

Before you begin, ensure you have the following:

Component Requirement Notes
CPU 2+ cores (typical for small to medium instances) Performance depends on number of concurrent users and background jobs.
RAM 4 GB minimum, 8 GB recommended Estimated based on typical usage; more RAM improves performance for large file operations.
Storage At least 2x the size of your current data directory Includes space for database, backups, and temporary files during migration.
Operating System Ubuntu 22.04 LTS or Debian 12 Other distros work, but commands may vary.
Software Docker Engine 24+, Docker Compose v2, rsync, mysqldump (or pg_dump for PostgreSQL) Install Docker via official docs: https://docs.docker.com/engine/install/
Network Stable internet connection, ability to transfer large files Consider using a local network for faster data transfer.
Access SSH access to old and new server, sudo privileges Ensure you have the necessary credentials.

Important: The Nextcloud version used in this guide is v34.0.3 (latest official release as of 2026-08-13). Always verify the latest version on the official Nextcloud release page before pinning a version in your Docker Compose file.

Step-by-Step Migration Process

Step 1: Prepare the New Server

First, update your new server and install Docker and Docker Compose if not already installed.

sudo apt update && sudo apt upgrade -y && sudo apt install -y curl git && curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh && sudo usermod -aG docker $USER && newgrp docker && sudo systemctl enable --now docker && sudo apt install -y docker-compose-plugin && docker --version && docker compose version

Log out and back in to ensure your user is in the docker group.

Step 2: Back Up the Existing Nextcloud Data and Database

On the old server, stop the Nextcloud containers to ensure data consistency. If you are using Docker Compose, navigate to the directory containing your docker-compose.yml and run:

cd /path/to/your/nextcloud/docker-compose && docker compose down && rsync -avh --progress /path/to/nextcloud/data/ /tmp/nextcloud-backup/data/ && mysqldump --single-transaction -u nextcloud -p'your_password' nextcloud > /tmp/nextcloud-backup/nextcloud_db.sql

Note: Replace your_password with the actual database password (stored in your .env file) and adjust paths accordingly. For PostgreSQL, use pg_dump instead.

Now, compress the backup for easier transfer:

tar -czvf nextcloud-backup.tar.gz -C /tmp/nextcloud-backup . && ls -lh nextcloud-backup.tar.gz

Transfer the backup to the new server using scp or rsync over SSH:

scp nextcloud-backup.tar.gz user@new-server-ip:/tmp/

Step 3: Set Up Directory Structure and Environment Variables on the New Server

SSH into the new server and create the directory structure for Nextcloud. Then create a .env file to store all sensitive variables.

ssh user@new-server-ip && mkdir -p ~/nextcloud && cd ~/nextcloud && mkdir -p data db config apps && touch .env && chmod 600 .env && nano .env

In the .env file, add the following content (replace values with your own):

NEXTCLOUD_VERSION=34.0.3
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
MYSQL_PASSWORD=ChangeMe_StrongPassword
MYSQL_ROOT_PASSWORD=ChangeMe_RootPassword
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=ChangeMe_AdminPassword
TRUSTED_DOMAINS=nextcloud.example.com

Warning: Never commit your .env file to Git or share it publicly. It contains sensitive credentials. Use a password manager to store these values.

Step 4: Create Docker Compose Configuration

Create a docker-compose.yml file in the ~/nextcloud directory. This configuration uses MariaDB for the database and includes a Redis cache for improved performance.

cd ~/nextcloud && nano docker-compose.yml

Paste the following content:

services:
  db:
    image: mariadb:11.4
    container_name: nextcloud-db
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: nextcloud-redis
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD:-}
    volumes:
      - ./redis:/data
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}

  app:
    image: nextcloud:${NEXTCLOUD_VERSION:-latest}
    container_name: nextcloud-app
    restart: unless-stopped
    ports:
      - "8080:80"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      - ./data:/var/www/html/data
      - ./config:/var/www/html/config
      - ./apps:/var/www/html/custom_apps
      - ./nextcloud-data:/var/www/html
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_HOST=db
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
      - NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
      - NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
      - TRUSTED_DOMAINS=${TRUSTED_DOMAINS}

volumes:
  nextcloud-data:

Note: The nextcloud-data volume mounts the entire Nextcloud installation to the host path ./nextcloud-data. This is useful for easier access to configuration files, but you may prefer to use a named volume instead. Adjust paths as needed.

Step 5: Restore the Backup into the New Server

Extract the backup archive and move the data and database files to the appropriate locations.

cd ~/nextcloud && tar -xzvf /tmp/nextcloud-backup.tar.gz -C . && mv data/* ./data/ && mv config/* ./config/ && mv apps/* ./apps/ && cp /tmp/nextcloud-backup/nextcloud_db.sql ./db/nextcloud_db.sql

Step 6: Start the Database Container and Import the Database

Start only the database container, then import the SQL dump.

docker compose up -d db && sleep 15 && docker compose exec -T db sh -c 'exec mysql -u root -p"$MYSQL_ROOT_PASSWORD"' < ./db/nextcloud_db.sql

Step 7: Start the Remaining Containers

Bring up the Redis and Nextcloud containers. The Nextcloud container will run the upgrade routine automatically on first start.

docker compose up -d && docker compose logs -f app

Wait until you see a message indicating that the upgrade is complete or that the server is ready to accept connections.

Step 8: Verify File Permissions

Nextcloud requires correct file ownership and permissions. The default user inside the container is www-data (UID 33). On your host, set the ownership of the data, config, and apps directories to the UID of the container user. Check your host's user ID with id -u and compare with the container's user ID by running:

docker compose exec app id -u www-data

Then set the correct ownership:

sudo chown -R 33:33 ~/nextcloud/data ~/nextcloud/config ~/nextcloud/apps

Note: The UID 33 is standard for www-data in the official Nextcloud image. Verify this against the image documentation if you are not sure.

Step 9: Update Nextcloud Configuration for the New Server

If your domain or server IP changed, update the trusted_domains in config/config.php.

cd ~/nextcloud && docker compose exec app php occ config:system:set trusted_domains 1 --value="new-server-ip-or-domain"

Also, update the overwrite.cli.url and overwritehost if necessary:

docker compose exec app php occ config:system:set overwrite.cli.url --value="https://nextcloud.example.com" && docker compose exec app php occ config:system:set overwritehost --value="nextcloud.example.com"

Step 10: Run Nextcloud Upgrade and Maintenance Checks

Run the upgrade command and then perform a database integrity check.

docker compose exec app php occ upgrade && docker compose exec app php occ db:add-missing-indices && docker compose exec app php occ maintenance:repair

Step 11: Test the Migration

Access your Nextcloud instance via the browser at http://new-server-ip:8080. Log in with an existing user account and verify that files are present and accessible. Also, run a sync test with a desktop client if possible.

Step 12: Update Your Reverse Proxy and DNS

If you use a reverse proxy like Nginx or Caddy, update its configuration to point to the new server. Then update your DNS records to the new server's IP address. After DNS propagation, you can access Nextcloud via your domain.

Advanced Configuration and Hardening

Reverse Proxy and SSL

For production use, always place Nextcloud behind a reverse proxy with SSL. Here is a sample Caddy configuration:

nextcloud.example.com {
    reverse_proxy nextcloud-app:80
}

Or for Nginx:

server {
    listen 443 ssl;
    server_name nextcloud.example.com;
    ssl_certificate /etc/ssl/certs/nextcloud.crt;
    ssl_certificate_key /etc/ssl/private/nextcloud.key;

    location / {
        proxy_pass http://nextcloud-app:80;
        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 $scheme;
    }
}

Ensure your Nextcloud config.php has the correct trusted_proxies and overwriteprotocol settings.

Backup Strategy

Implement a regular backup routine for both the database and data directory. Use mysqldump or pg_dump for the database and rsync for the data. Store backups on a separate disk or remote location. Test your backups periodically by restoring them to a test environment.

Security Hardening (Optional)

You can add the following security measures to your Docker Compose file, but note that they may require adaptation for your specific environment and may break the containers if applied blindly.

  app:
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
      - DAC_OVERRIDE
    read_only: true
    tmpfs:
      - /tmp

Warning: The above hardening measures may prevent Nextcloud from writing to certain directories. Ensure that the volumes are mounted correctly and that the necessary capabilities are added. Test thoroughly before deploying to production.

Troubleshooting Common Errors

Error Cause Solution
Can't write into config directory Incorrect file permissions Run chown -R 33:33 config and ensure the container can write to the config directory.
Database connection failed Database credentials mismatch or DB not started Check .env values and ensure the db container is healthy. Verify the SQL dump was imported correctly.
Trusted domain error The domain used to access Nextcloud is not in trusted_domains Run occ config:system:set trusted_domains with the correct domain or IP.
Files missing after migration Data directory not properly restored or wrong volume mount Verify the contents of ./data and check that the data volume is mounted correctly.
Upgrade stuck at a step Database schema conflicts or missing indices Run occ maintenance:repair and occ db:add-missing-indices manually.
Redis connection error Redis password mismatch or Redis not running Ensure REDIS_PASSWORD is set in .env and passed to both Redis and Nextcloud containers.
App not accessible after reverse proxy Proxy configuration not forwarding headers Add proxy_set_header X-Forwarded-* directives and set trusted_proxies in config.php.

Conclusion

Migrating Nextcloud to a new server is a delicate process, but with careful planning and execution, you can avoid data loss and downtime. This guide covered the entire migration path: backing up your existing instance, setting up a new Docker Compose environment, restoring data and database, and verifying the migration. We also discussed advanced configurations such as reverse proxy, SSL, and backup strategies, along with common pitfalls and their solutions.

Remember to always test your backups and practice the migration in a staging environment if possible. The Nextcloud community is also a valuable resource for troubleshooting specific issues. With the steps outlined here, you can confidently move your Nextcloud instance to new hardware and continue to enjoy a self-hosted cloud solution that respects your privacy.

FAQ

Q1: Do I need to stop the old Nextcloud instance during migration?

Yes, it is highly recommended to stop the old containers to ensure data consistency. This prevents write operations during the backup, which could lead to an inconsistent state. If you cannot afford downtime, you can use a maintenance mode (occ maintenance:mode --on) to lock the database while you perform the backup.

Q2: Can I use a different database (e.g., PostgreSQL) on the new server?

Yes, Nextcloud supports both MySQL/MariaDB and PostgreSQL. If you switch database types, you must export the data in a compatible format and adjust the Docker Compose configuration accordingly. The migration process becomes more complex because you need to convert the database schema, which is not trivial. It is recommended to stick to the same database type unless absolutely necessary.

Q3: How do I handle large data transfers over the internet?

For large datasets, use rsync with compression and resume capabilities. If you have physical access to both servers, you can copy the backup to an external drive and transfer it directly. Alternatively, you can set up a temporary VPN or use rsync over SSH with --partial to resume interrupted transfers.

Q4: What if I forget to update the trusted domains?

You will see an error message when accessing Nextcloud via the new domain or IP. To fix it, run the occ config:system:set trusted_domains command as shown in Step 9. You can also edit config/config.php directly to add the new domain to the trusted_domains array.

Q5: How can I minimize downtime during migration?

To minimize downtime, perform the backup while the old server is still running, but in maintenance mode. Then, set up the new server and restore the data. Once everything is verified, switch the DNS records and turn off the old server. The downtime will be limited to the time it takes for DNS propagation and the final switchover.

AdSense — In-article (responsive)

Related Guides