Redmine 3.4 から 4.2 へ移行
2021/8 に Redmine/Git サーバーを刷新した際の覚書。半年以上も前の内容だが、メンテナンスなどで読み返すこともありそうなのでブログとして書いておくことにした。
非常に長いため Redmine 構築と Git (Gitolite) で記事をわける。
移行の動機
Redmine/Git サーバーの稼働している CentOS 6 がサポート終了したこと、その標準ミドルウェア群が古すぎて Redmine 4 系へ移行できない問題を踏まえ、移行を決定。移行元、先ともにサーバーはさくらの VPS 4GB プランとした。
OS は CentOS Stream 8 を選択。当初 CentOS 8 想定だったが CentOS の方針変更によりこのバージョンはサポート短縮、代わりに Stream という名前でローリング リリースしてゆくのだという。つまり OS やミドルウェアの破壊的なバージョン更新もありえる。そのため従来方針の代替になる Rocky Linux と迷ったが、移行の動機が環境の古さなので受け入れることにした。
しかし現在としては Rocky Linux のほうがよかったかも、と考えている。ローリング リリースで環境は新しくなるものの、バージョン系の移行は 3 年周期ぐらいで十分なので。今回の作業で 7 年物の古い Redmine/Git も刷新できたから、同じ RHEL 系であればサーバー乗り換えは楽になったはず。
バージョン更新で致命的な問題が起きたら、改めて Rocky Linux へ移行するかもしれない。
バックアップ
はじめに Redmine 関連をバックアップする。サーバーに SSH 接続して以下を実行。プラグインは利用していないため MySQL の DB ダンプ、Redmine の添付ファイルと設定だけを対象とした。これらをまとめて ZIP 保存。
$ cd
$ mkdir redmine-backup
$ mysqldump -u xxxx -p yyyy > redmine-backup/redmine.sql
$ cp -r /var/lib/redmine/files redmine-backup
$ cp -r /var/lib/redmine/config redmine-backup
$ zip -r redmine-backup.zip redmine-backup/
次に Git リポジトリーの保存。Gitolite の設定は git-admin というリポジトリーとして git clone
済みなので、新サーバーへこれを push すれば済む。よって管理化の各種リポジトリーの実体を保存して ZIP 保存。
$ cd
$ sudo su root
# cp -r /home/gituser/repositories .
# zip -r repositories.zip repositories/
Redmine/Git 両方のバックアップ ZIP ファイルをローカルにダウンロードして終了。
MySQL の文字エンコーディング変換
これまで MySQL の文字エンコーディングは utf8
を利用していた。しかし最近は様々な媒体で Unicode 絵文字が普及しており、これを MySQL で扱うためには文字エンコーディングを utf8mb4
へ移行しなければならない。そのためにバックアップした MySQL DB のダンプ ファイルを加工する。
ZIP を展開したディレクトリー上で以下を実行。単なる文字列の置換なのでテキスト エディターなどで処理してもよい。
$ sed -e "s/CHARSET=utf8/CHARSET=utf8mb4/g" ./redmine.sql > ./redmine_utf8mb4.sql
この方法は手軽だが雑である。より安全に変換したいなら MySQL 上で SQL を実行するほうがよい。
ALTER DATABASE redmine CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
今回はダンプ内の検索で対象がテーブルの文字エンコーディング指定しか存在しないことを確認済みなので、お手軽なテキスト置換を採用。変換した redmine_utf8mb4.sql
を含めてディレクトリーを再度 ZIP に固め、この作業は終了とする。
新サーバー構築
ここからは移行先となるサーバー環境を構築してゆく。前述のように
- さくらのVPS 4GB プラン
- CentOS Stream 8
を対象とする。
さくらのVPS コントロール パネルからサーバー マシンを起動。初期状態は root
ユーザーへ VPS 作成時に入力しやパスワードが設定されている。そのため以下のような感じで SSH 接続可能なことを確認しておく。
$ ssh root@xxxx.vs.sakura.ne.jp -o PreferredAuthentications=password -o PubkeyAuthentication=no
本記事では新サーバーのドメイン名を xxxx.vs.sakura.ne.jp
にしているので、参考にする場合は自身の環境へあわせて変更すること。
作業ユーザー追加と sudo 設定など
ユーザーを追加してパスワードを設定。本記事では akabeko
としておく。
# useradd akabeko
# passwd akabeko
Changing password for user akabeko.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
sudo
を設定。
# visudo
ユーザー akabeko
が sudo
を利用できるように設定を追加。この場所を探すには vi
をコマンドモードにして /Allow
と入力して検索すればよい。root
の行を直下にコピペしてユーザー名を akabeko
に書き換える。
## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
## user MACHINE=COMMANDS
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
akabeko ALL=(ALL) ALL
:wq
で保存してから sudo
が通ることを確認。ユーザーを akabeko
に変更してからシステム更新コマンド dnf
を実行してみる。パスワードを聞かれて設定したものを入力確定、正常に sudo dnf
が実行できた。
# su - akabeko
$ sudo dnf
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for akabeko:
usage: dnf [options] COMMAND
...以下略
sudo
時のコマンド実行におけるパス通し、プロンプトの書式と色、ロケールなどを設定しておく。
$ cd
$ vi .bash_profile
設定内容は以下。
# User specific environment and startup programs
export PS1="\[\e[1;32m\][\u@\h \W]\\$\[\e[00m\] "
# locale
export LANG=en_US.UTF-8
export LC_ALL=$LANG
# sudo
PATH=$PATH:$HOME/bin
PATH=$PATH:/sbin
PATH=$PATH:/usr/sbin
PATH=$PATH:/usr/local/sbin
ファイルを保存したら設定を読み直す。
$ source .bash_profile
プロンプトが設定したとおり緑系の色になったので OK。
公開鍵認証
SSH のパスワード認証を禁止して公開鍵認証のみとする。
ローカルの macOS 上で鍵を作成。パスワードは未設定とした。これらのファイルは ~/.ssh
内に保存しておくこと。Windows の場合は C:¥Users¥ユーザー名¥.ssh
とする。.ssh
フォルダーがなければ作成しておく。
$ ssh-keygen -f xxxx.vs.sakura.ne.jp
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
...以下略
サーバーに公開鍵を送信。コマンド末尾の :
を忘れると空振りするので注意する。成功したら akabeko
ユーザーのホーム ディレクトリーにファイルが転送されているはず。
$ scp -P 22 xxxx.vs.sakura.ne.jp.pub xxxx.vs.sakura.ne.jp:
xxxx.vs.sakura.ne.jp's password:
xxxx.vs.sakura.ne.jp.pub
akabeko
でサーバーにログイン。
$ ssh akabeko@xxxx.vs.sakura.ne.jp
akabeko
として先ほど転送された公開鍵ファイルを利用して認証を設定。その後にサーバーから抜ける。
$ cd
$ mkdir .ssh
$ chmod 700 .ssh
$ mv xxxx.vs.sakura.ne.jp.pub .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys
$ exit
秘密鍵ファイル xxxx.vs.sakura.ne.jp
がローカルの ~/.ssh
に配置されていることを確認。同ディレクトリーの config
ファイルへ以下の設定を追加する。
HOST xxxx.vs.sakura.ne.jp
HOSTNAME xxxx.vs.sakura.ne.jp
USER akabeko
PORT 22
IDENTITYFILE ~/.ssh/xxxx.vs.sakura.ne.jp
これで ssh xxxx.vs.sakura.ne.jp
に対する公開鍵認証 SSH が実行可能となった。以降のサーバー接続はこれで実行する。
公開鍵認証を設定したのでサーバに SSH 接続してから root
ユーザーとパスワードによるログインを禁止する。
$ sudo vi /etc/ssh/sshd_config
以下のように編集。PasswordAuthentication
のほうはコメントアウトされているので解除のうえ、yes
を no
に書き換える。
PermitRootLogin no
... 中略 ....
PasswordAuthentication no
SSH デーモンを再起動。
$ sudo systemctl restart sshd
これで一通り OK。試しに公開鍵認証していない root
で SSH 接続してみるとエラーになることが確認できるはず。成功した場合は sshd_config
を見直すこと。
$ ssh root@xxxx.vs.sakura.ne.jp
root@xxxx.vs.sakura.ne.jp: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
FileZilla によるファイル送信
新サーバーとファイルをやりとりする際、GUI を利用できると便利だ。というわけで FileZilla を設定する。SCP で十分とか他のツールを使う場合、本項は読み飛ばして OK。
FileZilla をセットアップしたら接続先として以下を作成して保存。
項目 | 値 |
---|---|
設定名 | xxxx.vs.sakura.ne.jp |
プロトコル | SFTP |
ホスト | xxxx.vs.sakura.ne.jp |
ポート | |
ログオン タイプ | 鍵ファイル |
ユーザー | akabeko |
鍵ファイル | 公開鍵認証用に作成した秘密鍵ファイルのパス |
古いバージョンの FileZilla は OpenSSH 形式の秘密鍵を Putty 形式の PPK ファイルに変換する必要があった。しかし現行版は OpenSSH 対応しているので ~/.ssh
の秘密鍵をそのまま鍵ファイルに指定すればよい。
これで接続できることを確認したら akabeko
のホーム ディレクトリーへ Redmine のバックアップ ZIP ファイルをアップロードしておくこと。
logwatch
サーバー上のログを監視するため logwatch
を設定。インストールして動作確認してみる。
$ sudo dnf install logwatch
$ sudo logwatch --output stdout
問題なければ以下を実行して設定を更新。
$ sudo cp -p /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf
$ sudo vi /etc/logwatch/conf/logwatch.conf
変更箇所を抜粋。
MailTo = レポート メール送信先アドレス
MailFrom = logwatch@xxxx.vs.sakura.ne.jp
Detail = High
これで保存して改めて動作確認。
$ sudo logwatch --output stdout
...ここにサーバーの状態が出力される
問題なければメール送信をテストしてみる。
$ sudo logwatch --output mail
Can't exec "/usr/sbin/sendmail": No such file or directory at /sbin/logwatch line 1146, <TESTFILE> line 1.
Can't execute /usr/sbin/sendmail -t: No such file or directory
しかしエラーになった。原因は CentOS 8 から sendmail
が標準で提供されないから。なので手動追加する。
$ sudo dnf install sendmail
$ systemctl start sendmail
$ sudo systemctl enable sendmail
Created symlink /etc/systemd/system/multi-user.target.wants/sendmail.service → /usr/lib/systemd/system/sendmail.service.
Created symlink /etc/systemd/system/multi-user.target.wants/sm-client.service → /usr/lib/systemd/system/sm-client.service.
改めて実行したところエラーなし。
$ sudo logwatch --output mail
以降は logwatch
が cron
に登録した時刻で毎日、レポート メールが届くはず。送信先が Gmail だと迷惑メールとしてフィルターされがちなので注意すること。
firewalld
の起動と初期設定
ファイヤーウォール firewalld
を利用する。まずは動作確認。
$ sudo firewall-cmd --state
not running
動作していないので起動する。
$ sudo systemctl start firewalld
$ sudo firewall-cmd --state
running
OS 起動時の実行を設定。
$ sudo systemctl enable firewalld.service
Created symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service → /usr/lib/systemd/system/firewalld.service.
Created symlink /etc/systemd/system/multi-user.target.wants/firewalld.service → /usr/lib/systemd/system/firewalld.service.
HTTP/HTTPS のポートを許可。
$ sudo firewall-cmd --zone=public --add-service=http --permanent
$ sudo firewall-cmd --zone=public --add-service=https --permanent
$ sudo firewall-cmd --reload
この時点では IP 制限をしない。Apache を入れてから HTTP/HTTPS だけ制限する予定。
Apache
Apache のインストールと設定。
$ sudo dnf install httpd
$ sudo vi /etc/httpd/conf/httpd.conf
標準の Options
から Indexes
を削除。
<Directory "/var/www/html">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.4/mod/core.html#options
# for more information.
#
# Options Indexes FollowSymLinks
Options FollowSymLinks
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
#
AllowOverride None
#
# Controls who can get stuff from this server.
#
Require all granted
</Directory>
これが指定されていると index.html
のないディレクトリーにアクセスされた際、自動的に内容リストを表示する。そのため隠しファイルなどがあると存在が露見し、攻撃するための情報を提供することになるので無効化した。
設定ファイルに構文エラーがないかを確認。
$ sudo apachectl configtest
Syntax OK
httpd
を起動。ついでに自動起動も設定。
$ sudo systemctl start httpd
$ sudo systemctl enable httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
この状態で http://xxxx.vs.sakura.ne.jp/ を開くと Apache の情報が表示される。これを防ぐためにダミー ページを作成。
$ cd /var/www/html/
$ sudo touch index.html
$ sudo chown akabeko:akabeko index.html
$ vi index.html
内容は <h1>Welcome to xxxx.vs.sakura.ne.jp</h1>
とだけ表示する簡素なもの。Redmine/Git サーバーなら基本的にここへアクセスする機会はないため、これでよい。
IP 制限
職場 Redmine を秘匿するために firewalld
を利用して HTTP/HTTPS アクセスを IP 制限する。まずは現状の設定を表示。
$ sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens3
sources:
services: cockpit dhcpv6-client http https ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
はじめに public
ゾーンの http
と https
を削除してアクセス不能とする。
$ sudo firewall-cmd --permanent --remove-service=http
$ sudo firewall-cmd --permanent --remove-service=https
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens3
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
Web ブラウザーで http://xxxx.vs.sakura.ne.jp/ を開いてエラーになることを必ず確認しておくこと。
次に Web アクセスを制限するためのゾーンを追加。名前は myWeb
としておく。アドレスは自社ネットワーク用の固定 IP を指定する。社内イントラネット、または相当となる VPN 接続した状態で Web ブラウザーから アクセス情報【使用中の IP アドレス確認】 を表示すれば簡単に確認できる。ここでは xxx.xxxx.xxx.xxx
としておく。
$ sudo firewall-cmd --permanent --new-zone=myWeb
$ sudo firewall-cmd --permanent --zone=myWeb --set-target=ACCEPT
$ sudo firewall-cmd --permanent --zone=myWeb --add-source=xxx.xxxx.xxx.xxx
$ sudo firewall-cmd --permanent --zone=myWeb --add-service=http
$ sudo firewall-cmd --permanent --zone=myWeb --add-service=https
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all --zone=myWeb
myWeb (active)
target: ACCEPT
icmp-block-inversion: no
interfaces:
sources: xxx.xxxx.xxx.xxx
services: http https
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
$ sudo firewall-cmd --get-active-zones
myWeb
sources: xxx.xxxx.xxx.xxx
public
interfaces: ens3
設定後、イントラネットまたは VPN 経由からなら http://xxxx.vs.sakura.ne.jp/ にアクセス可能なこと、なしならエラー表示されることを確認できた。IP 制限をやめる場合はゾーンを削除してから public
に http
と https
を再設定する。
$ sudo firewall-cmd --permanent --delete-zone=myWeb
$ sudo firewall-cmd --zone=public --add-service=http --permanent
$ sudo firewall-cmd --zone=public --add-service=https --permanent
$ sudo firewall-cmd --reload
Redmine 4.2 から 2 要素認証が利用可能となった。そのためユーザー全員がこれを設定済みならば IP 制限をやめてもよさそう。
MySQL
Redmine の DB を格納するために MySQL を構築。バージョンが CentOS 6 の 5 系から一気に 8 系へ更新されていた。
$ sudo dnf install mysql-server
$ mysql --version
mysql Ver 8.0.21 for Linux on x86_64 (Source distribution)
設定ファイルをバックアップしてから書き換える。
$ cd
$ cp /etc/my.cnf ./
$ sudo vi /etc/my.cnf
CentOS 6 時代のデフォルトは以下だったが、
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
CentOS 8 だとこうなっている。
#
# This group is read both both by the client and the server
# use it for options that affect everything
#
[client-server]
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
以下の記事を読むと MySQL 8.0.1 以降の文字エンコーディングは標準で utf8mb4
とのこと。
- MySQL 8 のデフォルト文字セット系をすべて utf8mb4 にする cnf の書き方メモ – oki2a24
- MySQL :: MySQL 8.0 Reference Manual :: 5.1.8 Server System Variables
インストールしたバージョンは Ver 8.0.21
なので設定ファイルは変更しないでおく。
MySQL の自動起動登録と起動。
$ sudo systemctl enable mysqld
Created symlink /etc/systemd/system/multi-user.target.wants/mysqld.service → /usr/lib/systemd/system/mysqld.service.
$ sudo systemctl restart mysqld
ルートにパスワードを設定。SSL で保護せよと警告されるが今回は同一サーバー内なのでよしとしておく。
$ sudo mysqladmin -u root password 'パスワード'
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
パスワードが設定されたことを確認。
$ mysql -u root -p
Enter password:
...中略
mysql> exit;
Bye
OK。不要なユーザーとデータベースを削除する。
$ mysql -u root -p mysql
mysql> SELECT user, password, host FROM user;
ERROR 1054 (42S22): Unknown column 'password' in 'field list'
昔はこの時で先程パスワードを設定したユーザーを識別できたのだがエラーになった。改めて実行。
mysql> SELECT user, host FROM user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
現在は不要なユーザーと思えるものがない。次はデータベースの確認。
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
これも昔は test
というのがあって不要だったのだけど現在は必要最小で構成されているようだ。
rbenv で Ruby 構築
rbenv 経由で Ruby をインストールする。
sudo
経由で rbenv を実行するための設定をおこなう。visudo で設定ファイルを新規作成。
$ sudo visudo -f /etc/sudoers.d/00_base
以下を記述して保存。
Defaults !secure_path
Defaults env_keep += "PATH RBENV_ROOT"
設定ファイルに記述した環境変数を追加。
$ export RBENV_ROOT=/usr/local/rbenv
$ export PATH=${RBENV_ROOT}/bin:${PATH}
この環境変数を利用して GitHub のリポジトリから rbenv と ruby-build を clone する。
$ sudo git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT}
$ sudo git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build
rbenv 初期化。コマンドを実行すると export された環境変数などが表示される。
$ sudo rbenv init -
export PATH="/usr/local/rbenv/shims:${PATH}"
export RBENV_SHELL=sudo
command rbenv rehash 2>/dev/null
rbenv() {
local command
command="${1:-}"
if [ "$#" -gt 0 ]; then
shift
fi
case "$command" in
rehash|shell)
eval "$(rbenv "sh-$command" "$@")";;
*)
command rbenv "$command" "$@";;
esac
}
現在のユーザーで rbenv を利用するために .bash_profile
へ設定を追加しておく。
$ vi .bash_profile
以下を追記して保存。
# rbenv
export RBENV_ROOT="/usr/local/rbenv"
export PATH="${RBENV_ROOT}/bin:${PATH}"
eval "$(rbenv init -)"
保存された設定を反映するため .bash_profile
を読み直す。
$ source ~/.bash_profile
これで PATH
が通ったはず。試しに rbenv
コマンドをオプション指定なしで実行してみるとバージョンやオプションなどが表示される。
$ rbenv
rbenv 1.1.2-61-g585ed84
Usage: rbenv <command> [<args>]
Some useful rbenv commands are:
commands List all available rbenv commands
local Set or show the local application-specific Ruby version
global Set or show the global Ruby version
shell Set or show the shell-specific Ruby version
install Install a Ruby version using ruby-build
uninstall Uninstall a specific Ruby version
rehash Rehash rbenv shims (run this after installing executables)
version Show the current Ruby version and its origin
versions List installed Ruby versions
which Display the full path to an executable
whence List all Ruby versions that contain the given executable
See `rbenv help <command>' for information on a specific command.
For full documentation, see: https://github.com/rbenv/rbenv#readme
Ruby をインストールする。rbenv
は Ruby のバージョンを自由に選択できる。
$ rbenv install -l
2.6.8
2.7.4
3.0.2
jruby-9.2.19.0
mruby-3.0.0
rbx-5.0
truffleruby-21.2.0
truffleruby+graalvm-21.2.0
Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all / -L' to show all local versions.
最新は 3.0.2 のようだ。しかし以下を見ると 3.x 系は掲載されていない。
不安になったので Twitter でつぶやいたら Redmine コミッターの前田さんから即レスあり。いわく
Redmine 4.2 はまだ Ruby 3.0 には対応していません。2.4 から 2.7 までです。Ruby 3.0 には Redmine 5.0 から対応します。
とのこと。よって今回は 2.7 系の最新となる 2.7.4
を選ぶ。
$ sudo rbenv install 2.7.4
Downloading ruby-2.7.4.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.bz2
Installing ruby-2.7.4...
BUILD FAILED (CentOS Stream 8 using ruby-build 20210726-3-g075ad3b)
Inspect or clean up the working tree at /tmp/ruby-build.20210801171024.23522.h79LiI
Results logged to /tmp/ruby-build.20210801171024.23522.log
Last 10 log lines:
from ./tool/rbinstall.rb:846:in `block (2 levels) in install_default_gem'
from ./tool/rbinstall.rb:279:in `open_for_install'
from ./tool/rbinstall.rb:845:in `block in install_default_gem'
from ./tool/rbinstall.rb:835:in `each'
from ./tool/rbinstall.rb:835:in `install_default_gem'
from ./tool/rbinstall.rb:799:in `block in <main>'
from ./tool/rbinstall.rb:950:in `block in <main>'
from ./tool/rbinstall.rb:947:in `each'
from ./tool/rbinstall.rb:947:in `<main>'
make: *** [uncommon.mk:373: do-install-all] Error 1
ビルドでエラーになった。必要なパッケージが足りないらしいので追加。
$ sudo dnf install gcc openssl-devel readline-devel zlib-devel
再試行したら無事に成功。
$ sudo rbenv install 2.7.4
Downloading ruby-2.7.4.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.bz2
Installing ruby-2.7.4...
Installed ruby-2.7.4 to /usr/local/rbenv/versions/2.7.4
インストールしたバージョンをグローバルに設定。
$ sudo rbenv global 2.7.4
$ sudo rbenv rehash
確認のため sudo
なしでバージョンを表示。
$ ruby --version
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux]
OK。
Bundler と Passenger、失敗編
Redmine を動作させるために Bundler と Passenger をインストール。まずは Bundler。過去にはオプションとして --no-rdoc --no-ri
を指定していたが現行バージョンだと invalid option: --no-rdoc
というエラーになる。これを踏まえてオプションなしで実行。
$ sudo gem install bundler
Fetching bundler-2.2.25.gem
Successfully installed bundler-2.2.25
Parsing documentation for bundler-2.2.25
Installing ri documentation for bundler-2.2.25
Done installing documentation for bundler after 2 seconds
1 gem installed
次は Passenger。これを使って Apache や Nginx 上で Rails アプリを動かす。
$ sudo gem install passenger
Fetching passenger-6.0.10.gem
Fetching rack-2.2.3.gem
Successfully installed rack-2.2.3
Building native extensions. This could take a while...
Successfully installed passenger-6.0.10
Parsing documentation for rack-2.2.3
Installing ri documentation for rack-2.2.3
Parsing documentation for passenger-6.0.10
Installing ri documentation for passenger-6.0.10
Done installing documentation for rack, passenger after 39 seconds
2 gems installed
グローバルな Ruby 環境に gem をインストールしたので rbenv
をリフレッシュ。
$ sudo rbenv rehash
Passenger の Apache 用モジュールをインストール。
$ sudo passenger-install-apache2-module
Use <space> to select.
If the menu doesn't display correctly, press '!'
‣ ⬢ Ruby
⬡ Python
⬡ Node.js
⬡ Meteor
--------------------------------------------
Checking for required software...
...中略
Found: no
Error: Cannot find the `curl-config` command.
* Checking for Apache 2 development headers...
Found: no
* Checking for Apache Portable Runtime (APR) development headers...
Found: no
* Checking for Apache Portable Runtime Utility (APU) development headers...
Found: no
Some required software is not installed.
But don't worry, this installer will tell you how to install them.
Press Enter to continue, or Ctrl-C to abort.
エラーになった。curl-config
が足りないとのこと。パッケージとしてはこの名前ではなく curl-devel
らしいので入れてみる。
$ sudo dnf install curl-devel
Some required software is not installed.
のほうも入れる。
$ sudo dnf install httpd-devel
再試行するも途中でエラー。
mkdir -p buildout/apache2/module_libpassenger_common
rake aborted!
ArgumentError: Malformed version number string Stream
Tasks: TOP => apache2 => buildout/apache2/mod_passenger.so => buildout/apache2/module_libpassenger_common/LoggingKit.o
(See full trace by running task with --trace)
--------------------------------------------
It looks like something went wrong
Please read our documentation for troubleshooting tips:
https://www.phusionpassenger.com/library/install/apache/
https://www.phusionpassenger.com/library/admin/apache/troubleshooting/
If that doesn't help, please use our support facilities. We'll do our best to help you.
https://www.phusionpassenger.com/support
--help
オプションでヘルプを表示してみたら --no-compile
というオプションがあった。コンパイルしないでインストールするらしい。これで再試行してみたらいけた。
$ sudo passenger-install-apache2-module --no-compile
Apache 用モジュール設定。httpd.conf
本体に書くのではなく専用ファイルを用意する。passenger.conf
という名前で作成。
$ sudo vi /etc/httpd/conf.d/passenger.conf
設定は以下で確認できる。
$ sudo passenger-install-apache2-module --snippet
LoadModule passenger_module /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10
PassengerDefaultRuby /usr/local/rbenv/versions/2.7.4/bin/ruby
</IfModule>
これを passenger.conf
に記述。してついでに Redmine を公開するときのディレクトリ設定も加えて保存。今回は http://ホスト名/redmine に公開するので以下のようになる。パスを見ると gem のバージョンが含まれているため rbenv でバージョンを切り替える場合はここも変更する必要あり。
LoadModule passenger_module /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10
PassengerDefaultRuby /usr/local/rbenv/versions/2.7.4/bin/ruby
</IfModule>
RailsBaseURI /redmine
しかし Apache の構文確認でエラーになる。
$ sudo apachectl configtest
[sudo] password for akabeko:
httpd: Syntax error on line 357 of /etc/httpd/conf/httpd.conf: Syntax error on line 1 of /etc/httpd/conf.d/passenger.conf: Cannot load /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10/buildout/apache2/mod_passenger.so into server: /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10/buildout/apache2/mod_passenger.so: cannot open shared object file: No such file or directory
mod_passenger.so
が見つからないそうだ。実際、このパス上に存在しない。コンパイルなしではダメなのだろうか?Passenger を uninstall
してら再試行してみたが、やはりコンパイル途中で rake abort
するしで対処のしようがない。
Passenger 再び
Passenger のインストールで失敗して困っていることを Twitter でつぶやいていたら以下のリプがあった。
はじめまして。これって、CentOS Stream上で実施されてますか? だとすると、(正しいやり方ではないと思いますが)、/etc/centos-releaseの記述を一時的に「CentOS 8」と書き換えて、passenger-install-apache2-moduleを実行すると、私の場合は進みました。
— a5hlynx (@a5hlynx) August 13, 2021
試しに OS のバージョンを表示。
$ cat /etc/centos-release
CentOS Stream release 8
これはプレーン テキスト ファイルに記述されているので Twitter で提案されているとおり編集してみる。
$ sudo vi /etc/centos-release
内容は Stream
を削除して CentOS release 8
とした。:wq
で保存後にバージョン表示すると変更が反映されていた。
$ cat /etc/centos-release
CentOS release 8
この状態で再実行したらエラーにならず成功した!嬉しい!!!
$ sudo passenger-install-apache2-module
--snippet
オプション付きで実行して設定を確認。
$ sudo passenger-install-apache2-module --snippet
LoadModule passenger_module /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10
PassengerDefaultRuby /usr/local/rbenv/versions/2.7.4/bin/ruby
</IfModule>
RailsBaseURI /redmine
これに対して Redmine を URL のサブディレクトリーとする設定を加える。
$ sudo passenger-install-apache2-module --snippet
LoadModule passenger_module /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /usr/local/rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/passenger-6.0.10
PassengerDefaultRuby /usr/local/rbenv/versions/2.7.4/bin/ruby
</IfModule>
RailsBaseURI /redmine
この内容を Apache の設定ファイルとして書き込み保存。構文確認もしておく。
$ sudo vi /etc/httpd/conf.d/passenger.conf
$ sudo apachectl configtest
Syntax OK
OK だったので OS のバージョン情報を書き戻す。CentOS release 8
としたものを CentOS Stream release 8
にして保存後、反映を確認。
$ sudo vi /etc/centos-release
$ cat /etc/centos-release
これで Passenger 構築は完了。
Redmine
作業用ユーザーの HOME に最新版 Redmine をダウンロード。この時点の最新は 2021/8/1 リリースの 4.2.2 だった。
$ curl -OL https://www.redmine.org/releases/redmine-4.2.2.zip
$ unzip redmine-4.2.2.zip
$ rm redmine-4.2.2.zip
/var/lib
直下へ redmine
というディレクトリー名で移動。
$ sudo mv redmine-4.2.2 /var/lib/redmine
Redmine 専用のユーザーとデータベースを作成。XXXXXXXXXXXXXXXX
部分はパスワード。私は KeePassXC ランダム生成したものにした。ユーザーは 'redmine'@'localhost'
としておく。文字エンコーディングは旧環境の DB ダンプを utf8mb4
に変換したのであわせる。
$ mysql -u root -p
mysql> CREATE DATABASE redmine DEFAULT CHARACTER SET utf8mb4;
mysql> CREATE USER 'redmine'@'localhost'' IDENTIFIED BY 'XXXXXXXXXXXXXXXX';
mysql> GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> exit;
旧環境の移行
新規ならこの部分は実行しなくてよい。
旧環境から持ってきたバックアップが作業用ユーザー HOME 直下に置かれていると仮定する。サブ ディレクトリー内なら以降のパス指定やカレントを適宜、自分の環境にあわせて変更すること。
ファイル | 内容 |
---|---|
redmine_utf8mb4.sql |
MySQL DB のダンプ。CHARSET を utf8 から utf8mb4 に変換済み。 |
files/ |
Redmine の添付ファイル格納ディレクトリー。 |
config |
Redmine の設定ファイル格納ディレクトリー。 |
バックアップを新環境のデータベースに取り込む。
$ cd
$ mysql -u redmine -p redmine < redmine_utf8mb4.sql
添付ファイルの移行。
$ cd
$ mv /var/lib/redmine/files/ /var/lib/redmine/_files/
$ mv files/ /var/lib/redmine/
$ rm -rf /var/lib/redmine/_files/
config/
は旧環境の有無に関わらず編集が必要なので、バックアップしたものを参考に次項で書き換えること。
セットアップ
以下を参考にしながら Redmine をセットアップしてゆく。
設定ファイル置き場に移動。
$ cd /var/lib/redmine/config/
データベース設定ファイルを作成して編集する。
$ cp database.yml.example database.yml
$ vi database.yml
データベースの設定にあわせて変更してゆく。ここまでの手順を実行しているなら username
を redmine
にして password
へ MySQL の redmine
ユーザーへ割り当てたパスワードを指定すればよい。編集したら保存する。
production:
adapter: mysql2
database: redmine
host: localhost
username: redmine
password: "XXXXXXXXXXXXXXXX"
# Use "utf8" instead of "utfmb4" for MySQL prior to 5.7.7
encoding: utf8mb4
メール設定。
$ cp configuration.yml.example configuration.yml
$ vi configuration.yml
旧環境だとシンプルだった。
production:
email_delivery:
delivery_method: :sendmail
しかし Redmine 4.2 では設定やサンプルが大量に定義されている。途中に
# ==== Sendmail command
#
# email_delivery:
# delivery_method: :sendmail
という箇所があるのでこれを参考に冒頭の方を書き換えて保存。前述の logwatch
用に sendmail
をインストール済みなので、これを Redmine でも利用することにした。
# default configuration options for all environments
default:
# Outgoing emails configuration
# See the examples below and the Rails guide for more configuration options:
# http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
email_delivery:
delivery_method: :sendmail
Redmine の依存ソフトウェアをインストール。まずは基本となる bundler
から。
$ cd
$ sudo gem install bundler
次に Redmine 関連。
$ cd /var/lib/redmine
$ sudo bundle install --without development test
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
エラーになった。ググると以下の記事が出たので
参考に設定を足してみたが
$ sudo bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
エラーになった。ログを見るとビルドに失敗しているのでもしかすると mysql-devel
がインストールされていないからだろうか。追加してみる。
$ sudo dnf install mysql-devel
再び実行したら成功した。
$ sudo bundle install --without development test
Installing mysql2 0.5.3 with native extensions
Bundle complete! 36 Gemfile dependencies, 63 gems now installed.
Gems in the groups 'development' and 'test' were not installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
セッション管理用の鍵を初期化し、データベースをマイグレート。
$ bundle exec rake generate_secret_token
$ RAILS_ENV=production bundle exec rake db:migrate
Web サイトとしてはサブディレクトリー公開するので var/www/html
にシンボリック リンクを貼る。
$ sudo ln -s /var/lib/redmine/public /var/www/html/redmine
firewalld
で IP 制限しているなら VPN 接続などでその IP となってから http://xxxx.vs.sakura.ne.jp/redmine
のようにアクセスすると Redmine が表示されるはず。私の環境では正常に動作することを確認できた。
テーマ追加
手前味噌だが私の作成したテーマをインストールしておく。
$ cd
$ curl -OL https://github.com/akabekobeko/redmine-theme-minimalflat2/releases/download/v1.7.0/minimalflat2-1.7.0.zip
$ unzip minimalflat2-1.7.0.zip
$ mv minimalflat2 /var/lib/redmine/public/themes/
Redmine 管理画面でこれを有効にすれば OK。
HTTPS 化
Redmine サイトを HTTPS 化。証明書は Let's Encrypt で運用する。そのためのパッケージとして certbot
が提供されているものの標準リポジトリーにはないので EPEL を追加しておく。
$ sudo dnf install epel-release
certbot
をインストール。依存として膨大な Python 関連が表示されるが、そのまま実行。この時点のバージョンは 1.18.0 であった。
$ sudo dnf --enablerepo=epel install certbot
$ certbot --version
certbot 1.18.0
証明書を取得する。xxxx.vs.sakura.ne.jp
部分は自分のドメインに変更すること。しかし実行したらエラーになった。
$ sudo systemctl stop httpd
$ sudo certbot certonly --webroot -w /var/www/html/ -d xxxx.vs.sakura.ne.jp
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: xxxx.vs.sakura.ne.jp
Type: connection
Detail: Fetching http://xxxx.vs.sakura.ne.jp/.well-known/acme-challenge/XXXX: Error getting validation data
Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
チャレンジ ファイルのダウンロードに失敗したのだという。Detail に示されたファイルを curl
でダウンロードしてみる。
$ curl -OL http://xxxx.vs.sakura.ne.jp/.well-known/acme-challenge/XXX
... 中略
Failed to connect to xxxx.vs.sakura.ne.jp port 80: Connection refused
原因判明。Let's Encrypt 側からもポート 80 でこのサーバーへアクセスする必要があるのに firewalld
で遮断されているようだ。なので制限用のゾーン設定を削除して HTTP/HTTPS を許可する。
$ sudo firewall-cmd --permanent --delete-zone=myWeb
$ sudo firewall-cmd --zone=public --add-service=http --permanent
$ sudo firewall-cmd --zone=public --add-service=https --permanent
certbot
を再実行したら成功した。
$ sudo certbot certonly --webroot -w /var/www/html/ -d xxxx.vs.sakura.ne.jp
Successfully received certificate.
firewalld
の設定を戻しておく。
$ sudo firewall-cmd --permanent --remove-service=http
$ sudo firewall-cmd --permanent --remove-service=https
$ sudo firewall-cmd --permanent --new-zone=myWeb
$ sudo firewall-cmd --permanent --zone=myWeb --set-target=ACCEPT
$ sudo firewall-cmd --permanent --zone=myWeb --add-source=xxx.xxx.xxx.xxx
$ sudo firewall-cmd --permanent --zone=myWeb --add-service=http
$ sudo firewall-cmd --permanent --zone=myWeb --add-service=https
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all --zone=myWeb
証明書を更新するたびにこれを実行するのは面倒だ。IP 制限については Redmine ユーザー全員が 2 要素認証したら廃止したい。
Apache 関連の設定
Apache に設定するための証明書を確認。
$ sudo ls -l /etc/letsencrypt/live/xxxx.vs.sakura.ne.jp
total 4
lrwxrwxrwx 1 root root 42 Aug 22 17:51 cert.pem -> ../../archive/xxxx.vs.sakura.ne.jp/cert1.pem
lrwxrwxrwx 1 root root 43 Aug 22 17:51 chain.pem -> ../../archive/xxxx.vs.sakura.ne.jp/chain1.pem
lrwxrwxrwx 1 root root 47 Aug 22 17:51 fullchain.pem -> ../../archive/xxxx.vs.sakura.ne.jp/fullchain1.pem
lrwxrwxrwx 1 root root 45 Aug 22 17:51 privkey.pem -> ../../archive/xxxx.vs.sakura.ne.jp/privkey1.pem
-rw-r--r-- 1 root root 692 Aug 22 17:51 README
Apache に証明書を設定して HTTPS 対応させる。はじめに SSL モジュールを追加してから設定ファイルを開く。
$ sudo dnf install mod_ssl
$ sudo vi /etc/httpd/conf.d/ssl.conf
以下のように設定変更。SSLCertificateFile
と SSLCertificateKeyFile
はデフォルト設定をコメントアウトしてから追記。SSLCertificateChainFile
はもともとコメントアウトされた状態だったのでそのまま追記した。ひととおり設定したら保存。
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/letsencrypt/live/xxxx.vs.sakura.ne.jp/cert.pem
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /etc/letsencrypt/live/xxxx.vs.sakura.ne.jp/privkey.pem
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
SSLCertificateChainFile /etc/letsencrypt/live/xxxx.vs.sakura.ne.jp/fullchain.pem
Apache 設定ファイルの構文チェック & 再起動 & ステータス確認。
$ sudo apachectl configtest
Syntax OK
$ sudo systemctl restart httpd
$ sudo systemctl status httpd
Redmine の URL 先頭を http
から https
に変更してアクセス可能であることを確認。私の環境では OK だった。
HTTP でアクセスされた場合、自動的に HTTPS へリダイレクトさせる。まずはこの機能を担当するモジュールの存在を確認。
$ sudo httpd -M | grep rewrite
rewrite_module (shared)
有効なので設定ファイルを追加。
$ sudo vi /etc/httpd/conf.d/rewrite.conf
以下を記述して保存。
<ifModule mod_rewrite.c>
RewriteEngine On
LogLevel alert rewrite:trace3
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</ifModule>
構文チェック、Apache 再起動、状態確認。
$ sudo apachectl configtest
Syntax OK
$ sudo systemctl restart httpd
$ sudo systemctl status httpd
HTTP の URL でアクセスして HTTPS にリダイレクトされることを確認。また HTTP の時に開いていたページをリロードすると自動的に HTTPS へリダイレクトされることを確認できた。
まとめ
ひとまず HTTPS で Redmine が動作し、旧環境のデータが引き継げているところまで確認できた。次回は Git 関連の移行と Redmine 連携について書く。