Deploy and Maintain Redmine, the Right Way
Disclaimer: This is not your usual “How to Install Redmine” guide. I won’t go into setting up your database or installing a web server here. I also won’t cover configuring Redmine. The Redmine Documentation is pretty complete in that regard, and what’s not mentioned there is general Rails application running procedure and can be found all over the web.
Instead, this is about maintaining your own, more or less customized version of Redmine that can be deployed with a single shell command whenever necessary.
Ready? Here we go.
Skip the All-in-One Installers and Ready-to-Run Virtual Machines
Bitnami installers or pre-installed VMs are nice for quickly trying Redmine out, but not suited for productive use. Why? Because there is no upgrade path. Oh wait, Bitnami has one. Except that it’s a joke. “Install the new version of the whole stack to another directory, and move over your data” is not upgrading. There’s no word about configuration, customizations and plugins, which you probably also want to preserve and reinstall. Good luck with that.
Redmine patch releases come out every month or two, security related bug fixes are released whenever necessary - you don’t want to miss these, right?
This is a thing people often forget about - the timing for updates is not always up to you. Of course you can postpone an upgrade to the next Redmine minor version for a few weeks. Probably even longer. But in case of newly discovered security issues in Redmine or Rails you don’t want to sit around with an unpatched system until you manage to free up some time for installing and configuring a new Bitnami stack, and manually moving over all your data.
Installation is just the tip of the iceberg. Upgrading is what you will be doing all the time.
Looking for the easiest set-up path definitely misses the point once you have decided to use Redmine in production. It’s easy maintenance and upgradeability what you should be looking for instead, in order to minimize the cost and risk associated with running your own Redmine.
Read on to learn how to keep your Redmine up to date over time, with ease.
Use Git
Even if you intend to just run stock Redmine without any customizations or Plugins - use a Git repository to hold your copy of Redmine. At the very least having a dedicated repository will give you a place to store all the things necessary for deployment (more on that later). But trust me, sooner or later you (or your users) will want to have some plugin or a custom theme installed, and then you already have the complete infrastructure in place. Experimenting with changes, trying out plugins and themes in local branches without breaking the production code - things like that will be very easy once you have your own Redmine git repo. So start with setting that up now.
While Redmine’s primary repository is a Subversion instance, there is a semi-official repository on Github which is maintained by a core committer and always up to date. Use this to set up your own repository:
$ git clone git@github.com:redmine/redmine.git
$ cd redmine
$ git remote rename origin upstream
$ git remote add origin git@yourserver.com:redmine.git
$ git checkout -b redmine/3.2-stable upstream/3.2-stable
$ git checkout -b local/3.2-stable
$ git push --set-upstream origin local/3.2-stable
Replace 3.2-stable
with whatever the latest stable version of Redmine currently is.
The git@yourserver.com
remote should be a private repository since it’s going to hold your deployment config and probably other things you don’t want to go public.
Since the deployment process outlined later will pull code from there, this repository needs to be reachable whenever you deploy, so don’t put it on some desktop machine. Ideally it’s also reachable from the web server you deploy to, but that can be worked around if necessary.
You now have two local branches - redmine/3.2-stable
tracks vanilla Redmine 3.2 from the github/redmine repository represented by the upstream remote, and local/3.2-stable
, which is where all your deployment config, customizations, themes and plugins will go.
Patch Version Upgrades
Redmine follows a x.y.z Major/Minor/Patch version numbering scheme.
Each minor release has it’s own stable
branch where bugfixes and security patches will be applied over time (as long as this version is still maintained). In our case that’s the 3.2-stable
branch.
Every now and then this upstream branch will receive some new commits. Your task is to incorporate these new commits into the local/3.2-stable
branch for deployment.
While you could simply merge the upstream branch regularly, I suggest using git rebase
from the start to maintain your own set of changes on top of the stock Redmine code:
$ git checkout redmine/3.2-stable
$ git pull # new upstream commits coming in
$ git checkout local/3.2-stable
$ git rebase redmine/3.2-stable
The rebase command will
- undo all your local changes in
local/3.2-stable
- upgrade
local/3.2-stable
to reflect the changes that took place inredmine/3.2-stable
- re-apply all your local changes on top of that
The result of following this regime is a clean history where your own (local) commits are always on top of the latest (upstream) Redmine commits.
Minor / Major Upgrades
If there’s a new stable branch, say 3.3-stable
, you do the same thing, rebase your changes on top of that. Due to the change of the upstream branch, the git commands are slightly different:
$ git fetch upstream
$ git checkout -b redmine/3.3-stable upstream/3.3-stable
$ git checkout -b local/3.3-stable local/3.2-stable
$ git rebase --onto redmine/3.3-stable redmine/3.2-stable local/3.3-stable
This first creates two new local branches for the 3.3 version, one from upstream and the other one from the local 3.2 branch. It then rebases your local changes (the diff between redmine/3.2-stable
and local/3.3-stable
(which still equals local/3.2-stable
)) on top of redmine/3.3-stable
.
Now local/3.3-stable
holds Redmine 3.3 plus any local changes you did.
For a new major version you would do the same.
OMG I Got Conflicts
Sooner or later, probably at the time you upgrade to another minor version for the first time, you will run into merge conflicts. During a rebase, Git applies your commits one by one, and will stop everytime a commit doesn’t apply cleanly.
In this case, git status
will show you the problematic files.
Check which commit it is that failed, find out what the intention of the commit was (meaningful commit messages are a big help here), fix the files, git add
each of them when you’re done with it. With no conflicting files left, you can review what’s going to be committed with git diff --cached
, and continue the rebase with git rebase --continue
once you’re satisfied.
If you find yourself in conflict hell unexpectedly and don’t have time to resolve that in this minute, you can simply abort the ongoing rebase with the --abort
switch which will restore your working copy to the state it was before.
What next?
With a proper Git workflow in place, it’s time to automate your deployment, which I’m going to cover in part two of this guide.