はじめに

「既にサポート終了になっているRedmine 5.1。これをバージョンアップしたい」がそもそものきっかけ。

しかし、Redmineのメジャーバージョンアップは、RubyやRailsの更新だけではありません。利用しているプラグインやテーマとの互換性、添付ファイル、データベース、さらにはWebサーバーやWAFとの兼ね合いまで確認しなければならず、思いのほか確認項目は多くなります。

特に本番環境を運用している場合、「とりあえずアップデートしてみる」というわけにはいきません。

迂闊にアップデートするとRedmineそのものが動くならない事象が発生します。

そこで今回は、稼働中のRedmine 5.1環境をそのまま複製し、本番とは完全に独立した検証環境を同一サーバー上へ構築しました。

目的は単なるバックアップではなく、Redmine 6.xへの移行を何度でも試行錯誤できる環境を作ることです。

構築環境

今回の構成は次のとおりです。

項目内容
OSUbuntu 24.04 LTS
WebサーバーApache 2.4
WAFModSecurity + OWASP CRS
Ruby3.2系(aptビルトイン)
Redmine5.1系
データベースMySQL 8.x
SSLLet's Encrypt
添付ファイルS3互換ストレージ(Wasabi)

同一サーバー上へ検証環境を追加するため、Apache・Ruby・MySQLは共有しながら、Redmine本体・データベース・ログ・添付ファイルのみを完全に分離します。

本番環境と検証環境の構成

今回の構成では、以下のように役割を分離しています。

項目本番環境検証環境
URLredmine.example.comredmine-test.example.com
アプリケーション/home/www-data/redmine/home/www-data/redmine-clone
DocumentRoot/home/www-data/redmine/public/home/www-data/redmine-clone/public
データベースredmineredmine_clone
DBユーザーredmineredmine_clone
ログ/var/log/redmine/var/log/redmine-clone
添付ファイル/mnt/storage/redmine/files/mnt/storage/redmine-clone/files

このようにしておけば、本番環境へ一切影響を与えることなく、何度でもアップグレードの検証を繰り返せます。

さっくりしていそうでさっくりしない手順

あくまでも筆者の手順です。

  1. MySQLダンプを取得
  2. Redmine環境の(アプリの)クローン

1. まずはMySQLのダンプを取得する

アプリケーションをコピーする前に、現在のデータベースをバックアップしておきます。

※DB名、ユーザー名は自分の環境に合わせてください。

mysqldump \
  --single-transaction \
  --routines \
  --triggers \
  --default-character-set=utf8mb4 \
  -u redmine \
  -p \
  redmine \
  > redmine.sql

--single-transactionを利用しているため、InnoDB環境であればサービス停止なしで整合性の取れたバックアップを取得できます。

2. Redmine本体を複製する

アプリケーション本体は cp ではなく rsync を利用しました。

ACLや拡張属性も含めてそのまま複製できるため、権限周りで悩むことが少なくなります。

※ディレクトリ名も自分の環境に合わせます。

cd /home/www-data
sudo rsync -aX redmine/ redmine-clone/

ここではまだ添付ファイルやログは本番環境を参照しています。(エイリアスを切っているため)

次の手順で検証環境用へ切り替えます。

3. 添付ファイルとログを分離する

添付ファイルはS3互換ストレージをマウントしているため、検証用ディレクトリへ切り替えます。

※サーバ上にそのまま保存している場合でも容量に注意しましょう

cd /home/www-data/redmine-clone
sudo ln -sf /mnt/storage/redmine-clone/files files

続いてログディレクトリを作成します。

sudo mkdir -p /var/log/redmine-clone
sudo chown -R www-data:www-data /var/log/redmine-clone
sudo ln -sf /var/log/redmine-clone log

これで本番・検証それぞれのログを独立して取得できます。

4. 検証用データベースを作成する

MySQLへログインし、新しいデータベースとユーザーを作成します。

※DBの向き先は要注意です。パスワードもポリシーに則り、適切なものを指定します。

CREATE DATABASE redmine_clone CHARACTER SET utf8mb4;
CREATE USER 'redmine_clone'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON redmine_clone.* TO 'redmine_clone'@'localhost';
FLUSH PRIVILEGES;

5. ダンプをリストアする

取得したバックアップを検証用データベースへ投入します。

※※要注意※※

リストア先とリストア元は三回ぐらい深呼吸して、事前に確認しましょう。

「クローン先のDB名」が先で、「クローン元のダンプファイル」が後です。

mysql \
  -u redmine_clone \
  -p \
  redmine_clone \
  < redmine.sql

これでデータベースも本番環境と同じ状態になります。


6. database.ymlを書き換える

Redmineが参照するデータベースを検証環境へ向けます。

production:

- database: redmine
+ database: redmine_clone

- username: redmine
+ username: redmine_clone

password: ********

忘れがちですが、この変更をしないと検証環境が本番データベースへ接続してしまいます。死ぬほど笑えない事象は、往々にしてこういうところから始まります。(始まりました)

7. ModSecurityの除外設定を追加する (オプション)

今回はApacheでModSecurityとOWASP CRSを利用しています。

RedmineはPATCHやPUTなどのHTTPメソッドを使用するため、通常のCRSでは誤検知されるケースがあります。

本番環境ですでに除外ルールを適用している場合は、検証用ホスト名も同様に対象へ追加します。

- redmine.example.com
+ redmine.example.com
+ redmine-test.example.com

これを忘れると、画面上では保存ボタンを押しただけなのに403 Forbiddenになることがあります。

8. Apache VirtualHostを追加する

本番用VirtualHost/etc/apache2/sites-available/redmine.confをコピーし、/etc/apache2/sites-available/redmine-clone.conf

  • ServerName
  • DocumentRoot
  • ErrorLog
  • CustomLog

を検証環境用へ変更します。

例えば、

/home/www-data/redmine/public

/home/www-data/redmine-clone/public

へ変更し、

/var/log/redmine

/var/log/redmine-clone

へ変更します。

設定後は有効化してApacheを再読み込みします。

sudo a2ensite redmine-test.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

動作確認

ここまで終わったら、検証環境へアクセスして以下を確認します。

  • ログインできる
  • チケット・Wiki・プロジェクトが一致している
  • 添付ファイルが表示される
  • ログが検証用ディレクトリへ出力される
  • ModSecurityで403にならない

ここまで確認できれば、Side-by-Side構成のクローン環境は完成です。

おわりに

サーバー運用では「バックアップを取ってから更新する」は半ば常識になっています。しかし、メジャーバージョンアップのような大きな変更では、それだけでは十分とは言えません。

実際に必要なのは、「失敗してもやり直せる環境」を用意しておくことです。

今回のように本番と完全に切り離した検証環境を用意しておけば、Redmine 6.xへのアップグレードだけでなく、Rubyやgemの更新、不要プラグインの整理、設定変更なども心置きなく試せます。

運用者であれば「更新前にバックアップを取る」は自然とできるようになります。しかし、その先の「何度でも検証できる環境を用意する」まで仕組みにしておくと、運用はさらに一段安定します。

私自身、今回の移行作業ではこの検証環境のおかげで、結果として、一度きりの「勝負」ではなく、納得いくまで検証を重ねた上で本番移行へ臨めます。