Notes on migrating Nextcloud to docker with version mismatch

Some quick notes (mostly to myself) on how to migrate nextcloud to another server, while changing to a docker-based system, and also updating across multiple major versions. In my case, I had a server running version 19, and the current stable version at time of update was 21. Direct migration across multiple major steps is not supported, so I first ported to 19, and then upgraded first to 20, and then to 21. This took a while to figure out from multiple sources, so here a brief summary of the main steps.

Step 1: Pull database backup on old server:

mysqldump --single-transaction -h localhost -unextcloud -pYOUR_DB_PASSWORD nextcloud > db_backup.sql

Step 2: Set up docker instance on new server

I’m installing Nextcloud in folder /home/nextcloud.

Create docker-compose.yml in /home/nextcloud (adapted from https://github.com/nextcloud/docker/tree/master/.examples , example with-nginx-proxy)

  • copy docker-compose.yml, db.env, and the proxy folder into /home/nextcloud
  • create the following folders:
    • app
    • certs
    • data
    • database
    • proxy
    • vhost.d
  • edit your password in db.env
  • Edited docker-compose.yml:
version: '3'

services:
  db:
    image: mariadb
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: always
    volumes:
      - ./database:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD="<YOUR_DB_PASSWORD>"
    env_file:
      - db.env

  redis:
    image: redis:alpine
    restart: always

  app:
   # here you can specify the version of Nextcloud to install. 
   # Should match the version of old system
    image: nextcloud:19-apache
    restart: always
    volumes:
      - ./app:/var/www/html
      - ./data:/var/www/html/data
    environment:
      - VIRTUAL_HOST=the.domain.com     # enter your domain name
      - LETSENCRYPT_HOST=the.domain.com # enter your domain name
      - LETSENCRYPT_EMAIL=it@domain.com # enter your admin email here
      - MYSQL_HOST=db
      - REDIS_HOST=redis
    env_file:
      - db.env
    depends_on:
      - db
      - redis
    networks:
      - proxy-tier
      - default

  cron:
    image: nextcloud:apache
    restart: always
    volumes:
      - ./app:/var/www/html
    entrypoint: /cron.sh
    depends_on:
      - db
      - redis

  proxy:
    build: ./proxy
    restart: always
    ports:
      - 80:80
      - 443:443
    labels:
      com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
    volumes:
      - ./certs:/etc/nginx/certs:ro
      - ./vhost.d:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - proxy-tier

  letsencrypt-companion:
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    volumes:
      - ./certs:/etc/nginx/certs
      - ./vhost.d:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - proxy-tier
    depends_on:
      - proxy

volumes:
  database:
  app:
  data:
  certs:
  vhost.d:
  html:

networks:
  proxy-tier:

Step 3: pull files and database across to new server

cd /home/nextcloud/data
rsync -aAXv -e ssh root@the.old_domain.com:/path/to/data/folder .
scp root@the.old_domain.com:db_backup.sql /root/

Step 4: Bring up the docker instance:

cd /home/nextcloud
docker-compose build --pull
docker-compose up -d  # alternatively, if this is a re-run, add --force-recreate --build

Step 5: Import database

docker cp /root/db_backup.sql nextcloud_db_1:/dmp
docker-compose exec db sh -c "mysql -unextcloud -pYOUR_DB_PASSWORD nextcloud < /dmp"

Step 6: import old config

  • copy config/config.php from old server to new server into /home/nextcloud/app/config/config.php
  • check settings, in particular the host name, database name, database user
  • change dbhost to 'dbhost' => 'db'

Step 7: Run Nextcloud in browser

Nextcloud should now come up (might take a minute or two). It should accept logins from existing user accounts. Log in as admin. If there is a “finish setup” screen, something went wrong (probably wrong config.php). Things to check:

  • if there are server errors, it might be a permissions problem. All files in app and data should be www-data:root:
docker-compose exec app chown -R www-data:root /var/www/html/data
docker-compose exec app chown -R www-data:root /var/www/html/ # (should not be needed)

if there are errors, try to run occ diagnostics:

docker exec -it -u 33 nextcloud_app_1 /bin/bash  # run as www-data user
php occ integrity:check-core

  • log in as admin, go to settings/overview, check if there are any problems that need fixing
  • if there is an error about running cron, try going to “basic settings”, change cron settings to something, and back to “cron”. This seems to fix it.

Step 8: roll versions forward

Assuming everything worked fine, now it is time to update to the newest version. In Docker installs, this can’t be done through the web interface updater. The process is to pull the newest version with docker-compose, and rebuild the instance. However, as we’ve specified version 19 above, it won’t pull the latest version. So we edit the docker-compose file: change

  image: nextcloud:19-apache

to:

image: nextcloud:20-apache

and rebuild/restart everything:

docker-compose pull
docker-compose up -d

It may take a minute or two until Nextcloud comes back up in the browser, as it is running the update in the background. After it comes up again, log in as admin and check for problems. Then repeat the process to go from 20 to 21. The last update brought up errors regarding database keys and bigints, which can be fixed with some occ commands (instructions will be given by Nextcloud on the settings/overview page).

Leave a Reply

Your email address will not be published. Required fields are marked *