Migrate Nextcloud to New Server

by Nicholas Henkey — on  ,  , 

My Raspberry pi deploy of Nextcloud was too slow for my taste. The SD card (while large) was slow and the spinning disk supplemental drive did not handle all of the functionality I was hoping for. As a solve, I set up an old computer with an always-on VM for my new Nextcloud server. The following instructions include the information goes along with my video on this subject.

Video iFrame

Common Issues And Introductory Comments

If you're migrating Nextcloud and are facing a vague "Internal Server Error", There are major causes for this:

  1. The database cannot connect - you will need your old Nextcloud DB admin credentials
  2. The Nextcloud version you are downloading is not exactly the same as your current instance so the software is incompatible
  3. There is a final possibility that your file permissions are incorrect

This document is a step-by-step guide to help avoid these pitfalls but there are A LOT of steps, so be careful!

As an additional word of warning I'm upgrading PHP and doing a manual NC upgrade, which is not normally recommended. These instructions might be of some use to people who are conducting a PHP upgrade. Most likely, the only person who will ever use them is small business IT personnel.

Covered in the Video

  • VM config overview (not covered in blog entry)
  • Quick security setup
  • Packages and dependencies
  • Web server setup (most of this is unique to me)
  • Deploy fresh instance of Nextcloud
  • Import your data
  • Import your database
  • Run manual Nextcloud Upgrade
  • Test (not covered in blog entry)

Prerequisites

The video walks through VirtualBox setup instructions (for newbies & not covered here).

All instructions assume that you are using Ubuntu. Some of these instructions later in the document require PPA's:

  1. You will need to first put your current Nextcloud into Maintenance mode (sudo -u www-data php occ maintenance:mode --on)
    1. Note: I need to run this from inside my Nextcloud directory but your mileage may vary
  2. Back up your database into a .sql files mysqldump -u username -p databasename > filename-$(date +%F).sql
  3. Back up your data directory PRESERVE THE TIMESTAMPS either with rsync or tarball.
    1. I used rsync rsync -Aax /source-directory /destination-directory
    2. This did not work over local network for me due to missing permissions in the new Nextcloud directory so my "destination-directory" was a flash drive
    3. Tarball will not be covered in this document
  4. Back up your Nextcloud config.php files cp /source-directory/Nextcloud/config/config.php <-- source-directory
    1. I cannot stress enough how important this little file is. It is as important as your data and your database. DO NOT LOSE IT!
  5. Prepare your new server with Security updates

Your server should have at least 1 GB of RAM and a current modern single core (Ryzen or Intel / alternatively 4x ARM Cortex 7-series CPUs will serve as well).

Preparing Your Server - Easy

This section includes basic security setup. Most of this guide will not work with at least security patches installed but I will include steps for firewall setup below as well.

System Set-Up

Install Ubuntu and use a strong password with at least 12 characters from a random password generator. Normally I go much tougher because I do use a password manager that can generate these passwords (https://youtu.be/l0N-xzG53j0).

sudo apt update && sudo apt upgrade -y

I used a local machine from my network. You will not need to grab this IP address if you are using a VPS like Digital Ocean or Vultr

sudo apt install net-tools -y
ifconfig

Grab this IP address so you can SSH in from anywhere in your local network! Log in via SSH and we can move on to the next part.

System Log-In Security

UFW Firewall

Since I'm on local, I had some trouble with port 80 (another server is running on my network). I also needed to pick another port because my local ISP will not allow port 80 connections. For me this means:

sudo ufw allow 8080

The above will be port 80 for 99% of you, like the following:

sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 22

Important! If you miss your SSH port (22 in this case), you will lock yourself out of your server. It is generally recommended that you change your SSH port because 22 is common for brute-force attacks. I just use a 256 character long random password, and keep 22 open.

sudo ufw enable
sudo ufw status

Now you should see all correct ports listed as enabled by your firewall. All other connections will default to deny.

If you make a mistake and enable a port that should not be, you can always run ufw deny [insert-port-number]

Permissions Limitation

A common attack with those brute force hackers is to use root as the default username. It is a good idea to disable direct log on as root:

sudo nano /etc/ssh/sshd_config

Change the line that says PermitRootLogin to:

PermitRootLogin no

Exit the document and enter the command:

sudo service sshd restart

Install Required Packages

My Nextcloud install required PHP 8.0 because 8.2 was not supported by the Nextcloud team, yet. This meant that I needed to install via a PPA:

sudo add-apt-repository ppa:ondrej/php

The above will vary for you depending on when you find my guide and video.

Next you can install the webserver and database.

sudo apt update
sudo apt install apache2 mariadb-server libapache2-mod-php8.0 -y
sudo apt upgrade

Now that PHP, the web server (Apache2), and your database are installed you can gather additional required packages.

sudo apt install php8.0-gd php8.0-mysql php8.0-curl php8.0-mbstring php8.0-xml php8.0-zip php8.0-intl php8.0-bcmath php8.0-gmp php8.0-imagick -y
sudo apt-get install php8.0-apcu php8.0-fpm -y 

Remember that the php versions listed above will depend on which PHP version you have installed and I am using 8.0. Also, sometimes these packages change to drop the version number, if you get an error with php8.x-[package] try each package individual and drop the 8.x part if one of them gives you an error.

Now we have a solid foundation of required packages to install Nextcloud!

Web Server Setup - EASY (but partially custom for my use-case)

This section is unique to my set-up because I can't use port 80 with my local ISP. I tenatively recommend that you skip my Apache2 instructions and seek an independent guide for this section for this reason. Additionally, I install my Nextcloud server into /var/www/html/nextcloud which does seem to cause some problems. If you follow this guide nearly verbatim, be sure to follow the subsection regarding .htaccess below to prevent access control issues.

sudo nano /etc/apache2/ports.conf

In the above I changed port 80 to 8080. You should not need to do this.

sudo nano /etc/apache2/sites-available/000-default.conf

Set target directory to:

/var/www/html/nextcloud

I also changed port 80 to port 8080 under virtualhost in the above document because of my unique scenario.

Now you can restart Apache2:

sudo systemctl restart apache2

Now the Web Server is set up and configured for local ISP's without port 80 access.

Resolve .htaccess Error

The error will say something about .htaccess which is very critical because it controls who can see which files in Nextcloud. This will be an issue with my instructions because I direct my webserver to point to /var/www/html/nextcloud rather than setting it to /var/www/nextcloud.

To eliminate the .htaccess error, navigate to:

nano /etc/apache2/apache2.conf

Change AllowOverride None to AllowOverride All:

<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

To:

        AllowOverride All 

Hopefully this part helps some random people on the internet. The error drove me up a wall.

Edit php.ini to Allow Proper Files (DO NOT SKIP)

NextCloud requires a couple tweaks to the php.ini file to prevent errors and to make sure you can upload normal size user files. Edit the php.ini file:

sudo nano /etc/php/8.0/apache2/php.ini

Allow Nextcloud to use at least 512 MB of RAM by changing the following entry:

; Maximum amount of memory a script may consume
; http://php.net/memory-limit
memory_limit = 128M

To:

memory_limit = 1024M

Allow uploads greater than 2MB by changing the following entry:

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 2M

To:

upload_max_filesize = 2G

Allow uploads of more than a handful of files at once by changing the following entry:

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

To:

max_file_uploads = 120

This section should eliminate some of the errors you would normally see in a vanilla NextCloud setup.

Deploy Nextcloud - VERY EASY

Yes, this seems like a lot so far but the groundwork has been laid and now we just have to deploy Nextcloud before we can do the data and database migrations.

Navigate to:

cd /var/www/html

Now download and unpack the latest Nextcloud. At time of install, 23.0.0 was the latest available for me:

curl https://download.nextcloud.com/server/releases/nextcloud-23.0.0.tar.bz2 | sudo tar -jxv

Again, the above will vary for you depending on when you find my guide and video. At time of blog publication we are on version 23.0.3.

Migrate in Nextcloud Data and Config Files - HARD

This is considered the hard part because there are a ton of very detail-oriented steps that can trip users up. Even I got tripped up in my own video. Unlike the previous sections, the little steps aren't really standard web-server instructions. There are a few steps in here that are unnecessary, but I left them in because

  1. They are in the video so users can follow along
  2. They help me stay focused on where I am in the setup process

For my migration I had the config.php file, data directory information, and database on a USB thumb drive. You can also use tarball for this process and migrate over the network if your Nextcloud drive has enough space.

Create Data Folder with Correct Permissions

Now we can begin migrating the data into Nextcloud. First we need a directory to add our files to:

sudo mkdir -p /var/www/html/nextcloud/data

Set www-data as data folder owner:

sudo chown -R www-data:www-data /var/www/html/nextcloud/

The NextCloud folder still has improper permissions, so now we can correct this by navigating outside of the Nextcloud directory:

cd /var/www/html/

And setting appropriate read/write permissions for the entire directory:

find nextcloud/ -type d -exec chmod 750 {} \;
find nextcloud/ -type f -exec chmod 640 {} \;

Make the Old data Directory Available to the New System

This instance shows how to do this with a USB drive. You can follow suit by connecting it to the system and creating a mount directory (the following path is optional but should work on a fresh Ubuntu instance):

sudo mkdir /media/usb

Then mounting the drive to that folder (sdb1) was my case but this will vary for you):

sudo mount -t ext4 /dev/[sdb1] /media/usb

Migrate Important Files

Migrate Config File

Your old Nextcloud config.php file is critical to get the new system running like the old. It has important information like the keys to your database in it, from the flash drive, migrate it into the ../nextcloud/config folder:

cp /media/usb/[your-path]/config/config.php /var/www/html/nextcloud/config/

Update the file permissions of the config.php document:

sudo chown -R www-data:www-data /var/www/html/nextcloud/config/config.php

Now we need to allow connections from our desired domains by editing the array in the trusted domains section in the config.php file:

nano /var/www/html/nextcloud/config/config.php

Just set the domain how you want it. This can also be a URL from a domain you have purchased. In the video I allowed connections from my URL and from my local network since it is running from my home at 192.168.1.27:8080 which will not work for you. This just illustrates that you can permit connections from multiple domain entries.

Migrate Data Folder Files

Your entire old data folder needs to be moved over. The files alone are not sufficient. You will need to preserve your timestamps and can use tarball if you wish. The following rsync command preserved my timestamps but there may be another command that guarantees to preserve this information:

rsync -Aax /media/usb/[your-path]/data/* /var/www/html/nextcloud/data

This will take a while to complete. For the video I broke the next section into a "part 2" but will leave it in the appropriate section here. Once the transfer is complete, you need to give www-data user permissions to access the files. Run the following commands based on the paths I used during setup above:

cd /var/www/html/
find nextcloud/ -type d -exec chmod 750 {} \;
find nextcloud/ -type f -exec chmod 640 {} \;

Import Old Database

It's best to log in as root to do a database import. For the instructions here I am using example usernames and example passwords. Users that are doing a migration MUST know their usernames and passwords. If you do not know these automatically, they are published in plain text in the config.php file in the Nextcloud you are migrating (the file I said was super important at the beginning of this post):

  • Database user is dbuser
  • Database name is dbname
  • Database password is dbpassword

Hopefully this illustrates the importance of the config.php file for a Nextcloud migration. This little file contains all of the most critical information.

Now promote yourself to superuser to make this easier:

sudo su

The following step is unnecessary but I like having my database in my database folder. The intermediate step is useful because most Linux users don't always have complete file paths memorized such as /etc/mysql/db-import-file; instead, we typically navigate and call db-import-file from the local directory:

cp /media/usb/[path]/ncdb64-dump.sql /etc/mysql/

Now log into the database

mysql -u root -p

If you have another database with the same name as what you are importing, drop it (this will delete the old database):

DROP DATABASE Nextcloud;

Create the new database that matches the old database name:

CREATE DATABASE Nextcloud;

The following are example commands to create a user that matches your old database user:

CREATE USER 'nc-admin'@'localhost' IDENTIFIED BY 'PASSWORD';

Grant the new database user all permissions:

GRANT ALL PRIVILEGES ON **.** TO 'nc-admin'@'localhost' WITH GRANT OPTION;

Now:

FLUSH PRIVILEGES;
EXIT

The database is now created and you can import your old database:

mysql -h localhost -u root -p Nextcloud < /etc/mysql/ncdb64-dump.sql

The hard part is now over so we can recap briefly what this major section does.

How The Migration Fits Together

It may be difficult to understand what we have done in this "Migrate in Nextcloud Data and Config Files" section so this is a quick recap:

  • We created and prepared the data directory within the nextcloud superdirectory
  • We migrated the config.php file - This file allows the Nextcloud software (scripts in the /var/www/html/nextcloud/ directory and it's subdirectories) to access the database
  • We migrated the old data directory over - There are files in here that the database needs AND any missing files will cause errors in Nextcloud since the database will not be able to find them
  • We migrated and imported the database - This allows the web front-end to find your files. Every file in nextcloud needs to be accounted for within the database

These are all of the core components to get a functional Nextcloud system. Unfortunately they will not talk to each other yet because the system scripts are different versions from the database and data directory files.

The web upgrade system will not work to get them onto the same version but the manual update does synchronize the system files.

Finalization - Upgrade Nextcloud (Easy)

Note before you read this section, php8.0 is likely out of date at your time of installation. When you are running your OCC commands, be sure to use whichever PHP version is installed on your system.

Now that everything is in its place we need to call on the Nextcloud update script. This will get all of our software synced up and ready to go. To do this, navigate to:

cd /var/www/html/nextcloud/

Now, call occ as the www-data user. I could not get this to run with the full path, I had to be in the Nextcloud folder to get it to run:

sudo -u www-data php8.0 --define apc.enable_cli=1 occ upgrade

Now we can turn maintenance mode off by navigating into the following file and setting maintenance from true to false:

nano /var/www/html/nextcloud/config/config.php

Alternatively you can toggle maintenance mode off with the following command:

sudo -u www-data php8.0 /var/www/html/nextcloud/occ maintenance:mode --off

Now everything should be running just fine. For good measure you can restart your webserver by running the following command:

systemctl restart apache2

And your system should be ready for testing!

Final Thoughts

Migrating a Nextcloud instance was an extremely in-depth project to tackle. It serves as a reminder that Open Source projects meet their financial targets off consulting instead of licenses. A 2 hour consult during this setup likely would have saved me 20 hours of time.

I do want to thank the Nextcloud team and their contributors on the Nextcloud forums. They provided the hint that you can perform a manual upgrade once all of your files, config, and database files have been migrated. Without that tidbit, I likely never would have completed the migration.

No regerts. This process helped me to better understand Nextcloud which makes me far less concerned about future migrations.