Migrate Baikal with minimal downtime

Migrate_Baikal_with_minimal_downtimeBaikal is a CalDAV and CardDAV implementation based on PHP and MySQL. This post will explain how to migrate a Baikal installation from one server to another with minimum downtime.

DNS entries can take up to 24 hours to be propagated to all DNS servers around the world. Even if you have moved your Baikal installation to another server and changed the DNS entries, for up to 24 hours users might still get the IP of the old server. That can of course get your Baikal installation into trouble! For example, if users change their contacts or calendar entries on the old installation, the new one will not know about it.

Make MySQL accessible

The approach to migrate a Baikal installation from one server to another is similar to the one taken in my post Migrate WordPress site with minimal downtime. As described there, an SSH tunnel needs to be created to allow access to the same MySQL database, if you do not have direct access.

infoExposing the MySQL port to the public internet is something I would only advise if there is an absolute need to do it. As an alternative to an SSH tunnel you can secure a connection to MySQL as we use it here by restricting the access to the database (via Firewall rules) to the IP of your server.

Configure Baikal

Lets assume the access to MySQL is configured, whether it’s by SSH tunnel or a direct connection does not make a difference at this point. Download the complete directory from the old server containing all the Baikal files and upload them to the new server. (Configuration of the webserver itself will not be covered in this article). On the new server that you want to move Baikal to, open the configuration file “Specific/config.system.php”. You should find a line looking similar to this one:

# MySQL > Host, including ':portnumber' if port is not the default one (3306)
define("PROJECT_DB_MYSQL_HOST", "127.0.0.1");

If you have configured a port forwarding tunnel using SSH, you might only have to change the “127.0.0.1” to “127.0.0.1:12345” where 12345 is the port number you used to forward to the remote MySQL. The documentation line above the configuration item suggests that this is all you need to do. But sadly it is not!

As Baikal has a bug in the database connection class, connecting to a non-standard port doesn’t work at all. I have investigated this and fixed this problem. As long as this fix isn’t implemented by the owner of the Baikal project, you need to modify one PHP file manually.

The file “Core/Frameworks/Flake/Core/Database/Mysql.php” needs to be modified. Starting from line 40 you will find the following function:

	public function __construct($sHost, $sDbName, $sUsername, $sPassword) {
		$this->sHost = $sHost;
		$this->sDbName = $sDbName;
		$this->sUsername = $sUsername;
		$this->sPassword = $sPassword;

		$this->oDb = new \PDO(
			'mysql:host=' . $this->sHost . ';dbname=' . $this->sDbName,
			$this->sUsername,
			$this->sPassword
		);
	}

The following changes will replace the “:” with “;port=” so the PDO syntax is valid and the database connection works. As you can see this is just one line of code. I just added a comment line to explain what it does:

	public function __construct($sHost, $sDbName, $sUsername, $sPassword) {
		$this->sHost = $sHost;
		$this->sDbName = $sDbName;
		$this->sUsername = $sUsername;
		$this->sPassword = $sPassword;

		# This will replace the "host.com:3307" sytax with the PDO sytax "host=host.com;port=3307".
		$this->sHost = preg_replace('/\:/', ';port=', $this->sHost);

		$this->oDb = new \PDO(
			'mysql:host=' . $this->sHost . ';dbname=' . $this->sDbName,
			$this->sUsername,
			$this->sPassword
		);
	}

You can check the bug report I have filed for more details: https://github.com/jeromeschneider/Baikal/issues/129.

With this fix in place you can specify any MySQL port for Baikal and it will just work fine. The only thing you need to watch out for is an update. When you update Baikal you most likely will override this file and your changes will be gone. I hope a proper fix for this issue will be available soon so you don’t have to worry about this any more, but at the time of writing this bug still exists.

Change the DNS

As both Baikal installations now are now using the same database, you can change the DNS entry pointing to the old server. As soon as the DNS changes take effect and the entry points to the new server, you can move the MySQL server to the new server with minimum down time by dumping the database on the old server and loading the dump to the new one, but the details of doing this are not in the scope of this article.


Read more of my posts on my blog at http://blog.tinned-software.net/.

This entry was posted in DNS and tagged , , . Bookmark the permalink.