Upgrading OJS with the ojs_updater
At the University Library Frankfurt, we currently host 21 OJS journals, with more to come. Since we apply a strategy that runs only a single journal within an OJS instance, we have to maintain 21 different OJS instances. In order to maintain and manage this multiplicity, we found it important to come up with structures on the server and helper tools.
Especially the process of updating a journal instance can be quite tedious, since it involves multiple manual steps and can cause problems when forgetting something in the process. Due to these manual steps, the upgrade of a single OJS instance can take up to 20 minutes – and longer, if something doesn’t go according to plan.
To ease the upgrade process of a single OJS instance and make it less error prone, the FID Biodiversity Research and the FID Linguistics developed the ojs_updater tool. This tool is essentially a wrapper around the
tools/upgrade.php script shipped with OJS that automates all the previously manual tasks, performs checks, creates backups before the upgrade (and rewinds in case of an error in the upgrade process) and gives you some additional customisation options. The tool shrinks down the time for an upgrade to 2 to 3 minutes (the actual time for running the process). It automates 7 of the 12 recommended steps of the official PKP guideline for OJS upgrades.
So, what does the
ojs_updater not do?
- It does not activate the maintenance mode automatically. There are too many possibilities and technologies out there to cover them all with this simple tool.
- You should test the upgrade in a sandbox for yourself. Not only, if the upgrade runs successfully, but also make sure that all your plugins and styles are still working as intended.
- You should also have the version to upgrade to available on your system. For this purpose, we have a separate script running that checks every night for new OJS releases and downloads them.
ojs_updater also does not handle Docker environments. Instead, it expects you to have all your journals in separate folders in the same directory (see next section)
But despite these things, the
ojs_updater got you covered.
This blog post is accompanied by a git repo that includes some of the code examples shown in the text as well as some helper scripts.
You will need the virtual environment package for your Python 3 instance. Under Ubuntu, you would install it with:
apt install python3-venv
ojs updater is actively tested on SUSE Linux Enterprise Server (SLES) and Ubuntu and is known to have worked at some point on other distros/operating systems (e.g. Debian, FreeBSD). However, in order to keep this guide (somewhat) clear, it is assumed that you use Apache 2.4 on Ubuntu 22.10, MariaDB and Python 3.6 or newer. It’s of course possible to use something else; you just need to modify the updater settings accordingly. However, as far as RDBMSes go, only MySQL™ and MariaDB are currently supported. Furthermore, we recommend (and assume) that all your journals are kept in separate folders under the same root directory inside the Apache document root (
/usr/www/html/). This is not required for the
ojs_updater to work, but makes things much easier. Depending on your operating system, the Apache document root can be at different places (
In addition to that, it is required to set up a folder structure for the
ojs_updater itself. For the purpose of this tutorial, we assume that you create the folder structure under
/usr/local. Other places are, of course, possible as well.
Now change into the newly created
ojs/ folder, create a virtual environment and activate it:
After making sure you are in fact in the virtual environment, install the
ojs_updater from PyPI:
Next, we recommend to put a little shell script wrapper in
This allows you to call
ojs-updater directly from the terminal, without the need for activating the virtual environment each time. For convenience, the script is also readily available in the accompanying Github repo of this blog post.
Adapt the script according to your server structure and make it executable with
chmod +x /usr/local/bin/ojs-updater. Next make sure,
/usr/local/bin is in the
PATH variable of root (using your preferred method, e.g. editing
Download the OJS Release Package
Let’s assume you want to upgrade an OJS 3.2 instance to OJS 3.3.0-13. First download and extract the necessary OJS version:
/usr/ojs/versions/ is the directory, where all potential OJS versions live on your system. The
ojs_updater will always use the most current OJS version in this directory. The tool will never try to download any OJS version! Thus, if the latest OJS version in your
/usr/ojs/versions/ is outdated, the
ojs_updater will only upgrade to this outdated version! We recommend to setup a cron job that automatically downloads new OJS versions. An example script for this task is included in the example Github repo.
ojs_updater expects you to define your system settings once in an
ojs_updater_settings.yml file, where you can set the owner and the group of your OJS instances, the path to the available OJS versions that you can upgrade to, the path to the backup directory, and a list of custom files or directories that have to be copied over during the upgrade process (e.g. themes or custom plugins). All the default migration processes (like copying the
public folder and the
config.inc.php) will be carried out by the
ojs_updater without any configuration.
We suggest to start from the example file and modify it according to your local requirements:
Let’s assume you have a server directory structure like this:
Hence, you would set the
ojs_updater_settings.yml like this:
The default setting uses
www as owner and group of the journal directory, respectively, which is the default Apache user/group on SLES. On Ubuntu, it should be
ojs_updater will run permission checks when starting up. If on your system the journal directories are owned by another user, you can also customise this in the
But do not worry. If the
ojs_updater realises that the OJS journal directory is not owned by the expected user, it will just stop and complain. Nothing will break!
You may also see that we decided to set the functions for both
php explicitly. Normally, you should be fine with just setting the output that is given you by
which mysqldump and
which php. But there may be scenarios (e.g. having multiple PHP versions installed on the same system), where this becomes handy.
The important thing is that you set all this up only once and do not have to think about it with every OJS upgrade you do.
All following steps are required to be run either via
sudo or as the root user. The update script itself can only run as root, but drops its privileges to the specified user/group on start-up. This is usually the Apache user (e.g.
wwwrun, …). It also performs a few tests to make sure that no unforeseen permission issues occur during the actual update.
Enter Maintenance Mode
When everything is set up, we can proceed with the actual upgrading process. First, we have to put the journal into maintenance mode. How (or if) you do this, is left to you. This is mostly a precaution. The PKP upgrade guide give a recommendation how to do it on Apache servers.
Run the Upgrade
For the upgrade to start, change to the OJS root directory (
/var/www/html/journals) and call:
This will kick-off the upgrade process: checking permissions, creating backups, copying files, and finally starting the actual upgrade script shipped with OJS. The console logs are quite verbose, so you get a clear idea of what is happening.
After the update, you’ll notice that a new folder appeared (
journal-2_<timestamp>) in your journal directory. This is the original folder of the upgraded journal - only renamed. This folder is just kept for convenience, in case something goes wrong. This folder should be removed once you made sure the update was successful.
If the upgrade process should fail after the database migration started (leaving you with an inconsistent database), the
ojs_updater will use the backups it just created to rewind both the database and the journal directory to their original state. We do not recommend to rely on this mechanism, since we could only test it on our own system, but it should still provide you with some safety net. If the automatic rewinding does not work, the
ojs_updater still provides you with the necessary backups to jump back to the last version manually. The backup files are stored at the configured location (default:
After the upgrade is completed, the
ojs_updater will terminate. Now you only need to leave maintenance mode and check the
config.inc.php.OJSNEW for any new or deprecated settings. You could do so for example with
vimdiff journal-2/config.inc.php journal-2/config.inc.php.OJSNEW. Please also note, that the
ojs_updater does not upgrade any plugins; these are just carried over if configured. You can upgrade the journal’s plugins in the administration backend after the upgrade.
Forcing an Upgrade
ojs_updater will automatically upgrade to the latest version available to it in the directory configured as
ojs_version_folder. If you should try to upgrade an OJS instance that is already on the latest available version, the
ojs_updater will complain and stop safely quite fast. However, should there be a scenario where you need to enforce an OJS update, you can use the
This command will update the OJS instance of journal-2 to OJS 3.3.0-13 (which is the latest version in our example version directory
/usr/local/ojs/versions/) even if this exact version is already running in journal-2.
Since its initial development, the
ojs_updater has become a fundamental part of our OJS maintenance workflow, saving us a lot of manual work. We are happy to share our approach and hope that it will prove helpful to others as well. If you decide to try it out and spot some issues, we’d like to encourage you to get in touch via Github issues.
All tree diagram created with https://tree.nathanfriend.io
Written by Adrian Pachzelt, Thorsten Fritze. Last Modified on 2022-12-21.