タグ: MySQL Page 1 of 2

MySQLのデータベースを暗号化してバックアップするスクリプト。

概要

以前も作成していた、MySQLのデータベースのバックアップを自動的に取得するスクリプトを少々リファインさせました。

変数指定により、複数のDBを任意にバックアップできます。

スクリプトの動き

  • サーバ内にあるDBのバックアップを取得し、暗号化して指定ディレクトリに保存します。
  • 複合化のパスワードはスクリプトが自動生成し、暗号化と同時に別ディレクトリに保存します。
  • cronの自動実行を前提としているため、古い暗号化ファイルと複合化のパスワードは一定期間後に削除を行います。

動作を確認したサーバ

  • Ubuntu 24.04
  • MySQL 8.0.39

前準備

アカウントファイル

任意のディレクトリに、db_account.txtといった、DBにユーザー名とパスワードを記したファイルを作成しておきます。

[client]
user = db_user
password = "password"
  • パーミッションは400にします。(chmod 400 db_account.txt)
  • 取り扱いは慎重に行ってください。

バックアップDBの格納先

  1. 冗長性があり
  2. 機密性が保たれる

場所を指定してください。筆者はクラウドストレージ(wasabi)をマウントしています。

パスワードの格納先

/home/hoge/dbrestore_password のように、複合化のパスワードを格納するディレクトリを作っておきます。
こちらも運用に合わせ、適切に保管ができる場所を指定します。

それぞれ、スクリプト実行アカウントがアクセス/実行できるものにします。

スクリプト

スクリプト内容

  • スクリプトファイル名(例)
    • mysql_db_backup.sh

変数などは間違いの無いように指定ください。

#!/bin/bash

## 変数ここから ##
# $HOMEの変数を指定します。
HOME_DIR="/home/hoge"
# SQLをバックアップするディレクトリ(保管先)を指定します。運用に合わせて指定ください。
backup_dir="/path/to/backup/directory"
# 保持するバックアップの世代を日数で指定します。
keep_days=7
# ファイルに付与する日付/作業ディレクトリ名/バックアップファイル名を指定します。
current_date=$(date +%Y%m%d)
backup_name="backup_mysql_${current_date}"
zip_file="backup_mysql.${current_date}.zip"
# アカウントファイルを指定します。運用に合わせて指定ください。
credentials_file="${HOME_DIR}/script/config/db_account/db_account.txt"
# パスワードを記録するファイル名を指定します。運用に併せてして指定ください。
password_dir="${HOME_DIR}/dbrestore_password"
password_file="${password_dir}/db-restore.${current_date}.txt"
# redmineのデータベース名を指定します。
database_name=database
# バックアップ時に指定するオプションを指定します。
options="--defaults-extra-file=$credentials_file --no-tablespaces --single-transaction"
# バックアップファイルのパターンを指定します。
backup_file_pattern="backup_mysql.*.zip"
# パスワードファイルのパターンを指定します。
password_file_pattern="*restore*.txt"
## 変数ここまで ##

## 処理ここから ##

# 1.アカウントファイルのパーミッションが400かどうかチェックします。
# 400以外は処理そのものを終了します。
permissions=$(stat -c "%a" "$credentials_file")
if [ "$permissions" != "400" ]; then
echo "アカウントファイルのパーミッションは400である必要があります。"
exit 1
fi

# 2.一時的なバックアップディレクトリを作成します。
mkdir "${backup_dir}/${backup_name}"

# 3. mysqldumpを実行してデータベースのバックアップを取ります。
mysqldump $options -h localhost $database_name > "${backup_dir}/${backup_name}/${backup_name}.sql"

# 4. パスワードによる暗号化を実施します。
password=$(openssl rand -base64 12)
cd "${backup_dir}/${backup_name}"
zip -r "${backup_dir}/${zip_file}" -P "$password" .
cd -

# 5. 一時的なバックアップディレクトリを削除します。
rm -rf "${backup_dir}/${backup_name}"

# 6. 解凍パスワードを指定ディレクトリに保存します。
echo $password > $password_file

# 7.パスワードの読み取り権限を600に変更します。
chmod 600 $password_file

# 8. 保持期間より古いバックアップファイルを削除します。
find "$backup_dir" -name "$backup_file_pattern" ! -type f -newermt "${keep_days} days ago" -delete
find "$password_dir" -name "$password_file_pattern" ! -type f -newermt "${keep_days} days ago" -delete

## 処理ここまで ##

作成後、

chmod +x mysql_db_backup.sh

で実行権を付与します。

スクリプトの動かし方

スクリプトの動き

./mysql_db_backup.sh

として実行すると、

  1. 変数で指定したアカウントファイルを読み込み、mysqldumpでバックアップを取ります。
  2. バックアップ作成後、パスワード付きzipファイルに圧縮します。
  3. 圧縮されたバックアップと複合化のためのテキストファイルを変数で指定したディレクトリに格納します。
  4. 変数で指定した期日が過ぎたバックアップファイルと複合化のためのテキストファイルは自動的に削除されます。

バックアップDBの解凍

unzip backup_mysql.yyyymmdd.zip

とすると、パスワードを尋ねられます。

db-restore.yyyymmdd.txtに表示された文字列を入力します。

または、

unzip -P $(cat /path/to/password_file.txt) /path/to/zip_file.zip -d /path/to/output_directory

でファイルを直接引数にして解凍することもできます。

cronの指定

動作を確認したら、

crontab -e -u hoge

でcron編集画面を出し、

0 2 * * * /home/hoge/script/directory/mysql_db_backup.sh

などとして指定すれば、日次のDBバックアップを取得可能です。

NextcloudのDB、照合順序を変更。

NextcloudのインストールでDBを作成す際に

CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

としていました。

運用中、より正確な比較やソートが必要という判断をしたのでDBの照合順序をci(Case Insentive)ではなく、bin(Binary)に変更します。

DBを操作するため、作業前後にメンテナンスモードに入るとともに、ユーザーへの周知は徹底して行ってください。

メンテナンスモードを実行

  • Nextcloudのルートディレクトリ移動
cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

  • メンテナンスモード有効化
sudo -u www-data php occ maintenance:mode --on
  • メンテナンスモード確認

運用中のNextcloudのURLにアクセスし、メンテナンスモードであることを確認します。

mysqldumpでバックアップを取得する

  • 作業ディレクトリに移動
cd /hoge && pwd

任意のディレクトリを指定します。

  • DBバックアップ作成
mysqldump -h localhost -u nextcloud -p --no-tablespaces --single-transaction nextcloud > nextcloud_backup.$(date +%Y%m%d).sql

DB名やユーザーは自分の環境に合わせます。

  • DBバックアップ作成確認
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

DB設定変更

  • 管理者権限でMySQLにログインする
mysql -u root -p
  • 対象のDBを確認する
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

  • データベース全体の照合順序を変更する
ALTER DATABASE nextcloud COLLATE utf8mb4_bin;
  • 既存のデーテーブルの照合順序を変更する
USE nextcloud;
SET @DATABASE_NAME = 'nextcloud';

DB名は自分の環境に合わせます。

SET @COLLATE = 'utf8mb4_bin';
SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE ', @COLLATE, ';')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = @DATABASE_NAME
AND TABLE_TYPE = 'BASE TABLE';
  • MySQLから抜ける
EXIT

メンテナンスモードの解除を実行

  • Nextcloudのルートディレクトリ移動
cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

  • メンテナンスモード無効化
sudo -u www-data php occ maintenance:mode --off
  • メンテナンスモード確認

運用中のNextcloudのURLにアクセスし、普通にアクセスできることを確認します。

切り戻し

何か不具合があった場合の切り戻し手順です。上記、メンテナンスモードを有効化してから行ってください。

  • バックアップしたDBがあることを再確認する
ls -l /hoge/nextcloud_backup.$(date +%Y%m%d).sql

バックアップを行ったディレクトリを指定します。

head -100 /hoge/nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあること、平文で読めることを確認します。

  • 管理者権限でMySQLにログインする
mysql -u root -p
  • 対象のDBを確認する
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

  • 不具合が発生したDBを削除する

二回ほど深呼吸して、落ち着いて作業しましょう。

DROP DATABASE nextcloud;
  • DBを再作成する
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
  • MySQLから抜ける
EXIT
  • DB復元

mysql -h localhost -u nextcloud -p nextcloud < /hoge/nextcloud_backup.$(date +%Y%m%d).sql

この後、メンテナンスモードを解除して、以前と同じ状態か確認します。

作業後:バックアップDBの削除

平文でSQLがサーバ上にあるのは危険な状態なので、以下の措置を執ります。

  • 作業ディレクトリに移動
cd /hoge && pwd

バックアップを行ったディレクトリを指定します。

  • DBバックアップ確認
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

  • バックアップしたDBの削除
rm nextcloud_backup.$(date +%Y%m%d).sql
  • DBバックアップ削除確認
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルが無いことを確認します。

アカウントファイルを用いたDBログインとバックアップ。

概要

バックアップスクリプトなどでMySQLにログインして処理を行う場合のTIPSです。

何かと使うのでメモに残します。

さっくりとした手順

  1. アカウントファイルを作ります。
  2. ログインできることを確認します。
  3. アカウントファイルを用いたコマンドでバックアップできることを確認します。

アカウントファイル作成

  • ディレクトリ作成
sudo mkdir -p /home/hoge/db_password

運用に合わせて指定ください。

cd /home/hoge/db_password && pwd

指定したディレクトリに移動します

  • アカウントファイル作成

以下の内容を教義・信仰に沿ったエディタで作成します。(【】内は取り除き、自分の設定に合わせます)

  • アカウントファイル内容
  • ファイル例:account.txt
[client]
user = 【RedmineのDBユーザ】
password = "【RedmineのDBユーザ用パスワード】"

password は""で囲みます。

  • アカウントファイルのパーミッション変更
chmod 400 account.txt
ls -l account.txt

パーミッションが400であることを確認します。

ファイルを用いてのログインを確認

mysql --defaults-extra-file=/path/to/directory/account.txt

--defaults-extra-file=は、アカウントファイルの絶対パスです。

ログインできることを確認します。

SHOW DATABASES;

アカウントの権限で指定されたDBの表示を確認します。

EXIT

MySQLから抜けます。

SQL Dumpの取得

  • SQL Dump
mysqldump --defaults-extra-file=/path/to/directory/account.txt --no-tablespaces -h [DBサーバ] [DB名] > backup.sql
  • --no-tablespacesはPROCESS特権がないユーザでもダンプできるようにするためです。
  • バックアップ先も必要に応じて絶対パスで指定できます。
  • ファイル確認
ls -l backup.sql

ファイルの内容にDBがあれば成功です。取り扱いには慎重を期してください。

MySQLコンソールにログインせず、使われているテーブルの名前を検索する。

コマンド概要

MySQLのテーブルを検索する際、「使われているテーブルの名前を知りたい」時に使います。

コマンド

テーブルの一覧を確認する

mysql -u [user] -p -D [DB] -e "show tables"
mysql -u root -p -D redmine -e "show tables"

ここでは、DB:redmineのテーブル一覧を確認しています。 (rootユーザを用いています。特権などにより、適切なアカウントを指定してください)

特定の文字列が使われているテーブルを一覧表示する

mysql -u [user] -p -D [DB] -e "show tables like '%[文字列]%'"
mysql -u root -p -D redmine -e "show tables like '%issue%'"

ここでは、DB:redmineから、「issue」を含むテーブルのみを一覧表示します。

いちいち、

mysql -u [user] -p

の後に

USE [DB名];
SHOW TABLES LIKE '%issue%';

QUIT

と打ち込むより早いワンライナーでした。 (パスワードを入力するので厳密には異なりますが)

Redmine脆弱性対応。(4.2.x→4.2.10へのバージョンアップ)

これを行うきっかけ

こちらの記事:

https://blog.redmine.jp/articles/redmine-security-scanner/

で運用中のRedmineに既知の脆弱性がないかをチェックできるWebサービスの存在を知ったからでした。

で、現在のRedmineのURLを調べてみたら

E。

何度見てもEです。多少自信はあったので、この結果はその鼻っ柱を打ち砕くものでした。

そこで、現在運用中のRedmineのバージョンアップを図り脆弱性に対応します。

環境

  • Ubuntu 20.04 (AWS Lightsailで稼働中)
  • 動かしていたRedmine:4.2.9
  • Apache 2.4 / mod-passangerでRubyアプリを使用(Ruby 2.7系)
  • MySQL 8.0.3

作業に備えての前提

  • 本手順では「使用するDBの削除」を伴います。作業の際には慎重に行って下さい。
  • Webサービスを止める/何も入っていないRedmineが途中でできるため、ユーザアクセスができない状況が発生します。
  • また、筆者環境はfiles配下をクラウドストレージにマウントしています。手順は自身の環境に合わせてください。

さっくりとした手順

  1. スナップショットのバックアップ
  2. DBのバックアップ
  3. redmineのディレクトリを一度mvでリネームしてバックアップ。
  4. apache停止
  5. redmineのDBを消す。
  6. redmineのDBを新たに作る。(ユーザは全て権限があるので問題なし)
  7. apache再開
  8. ディレクトリを再作成し、新しい空のRedmineを作る。
  9. themesとpluginを再配置。filesのシンボリックリンクを貼り替える。
  10. themesとpluginを再配置した状態でDBマイグレーション。
  11. DBリストア。

データバックアップ

万一に備え、AWSからインスタンスのスナップショットを取得します。

mysqlによるDBバックアップ

mysqldump -h localhost -u redmine -p --no-tablespaces --single-transaction redmine > redmine_backup.$(date +%Y%m%d).sql
# DB名やDBユーザは自信の環境に合わせます

データ退避

cd /var/lib
# Redmineが格納されているディレクトリの親ディレクトリに移動します

ls -ld redmine
# 退避対象のディレクトリがあることを確認します

sudo mv redmine redmine_$(date +%Y%m%d)

ls -ld redmine_$(date +%Y%m%d)

apache停止

ここでWebサービスを停止するのは、DBを削除するためです。

systemctl status apache2.service

sudo systemctl stop apache2.service

systemctl status apache2.service

DB削除

慎重に行って下さい。

sudo mysql -u root -p
show databases;
/* redmineのDBがあることを確認 */

drop database redmine;

show databases;
/* redmineのDBがないことを確認 */

CREATE DATABASE redmine character set utf8mb4;

show databases;
/* redmineのDBがあることを確認 */

exit

Redmine再インストール

ソースダウンロード

sudo mkdir /var/lib/redmine

sudo chown -R www-data:www-data /var/lib/redmine

sudo -u www-data svn co https://svn.redmine.org/redmine/branches/4.2-stable /var/lib/redmine
# 4.2系の最新安定版をダウンロードします

退避させたディレクトリからconfigファイルコピー

sudo cp -pi /var/lib/redmine_$(date +%Y%m%d)/config/database.yml /var/lib/redmine/config/database.yml

cat /var/lib/redmine/config/database.yml
#中身確認

sudo cp -pi /var/lib/redmine_$(date +%Y%m%d)/config/configuration.yml /var/lib/redmine/config/configuration.yml

cat /var/lib/redmine/config/configuration.yml
#中身確認

Redmineインストール

cd /var/lib/redmine

sudo -u www-data bundle install --without development test --path vendor/bundle

sudo -u www-data bundle exec rake generate_secret_token

sudo -u www-data RAILS_ENV=production bundle exec rake db:migrate

sudo -u www-data RAILS_ENV=production REDMINE_LANG=ja bundle exec rake redmine:load_default_data

apache再開

systemctl status apache2.service

sudo systemctl start apache2.service

systemctl status apache2.service

再開後の仮パスワード作成

対象のRedmineにアクセスします。

IDとパスワードがadmin / admin に戻っている状態のため、仮パスワードを発行します。

退避したディレクトリからデータを再配置

cd /var/lib/redmine_$(date +%Y%m%d)/plugins

sudo cp -pir ./* /var/lib/redmine/plugins/
# プラグイン一式をコピーします

cd /var/lib/redmine_$(date +%Y%m%d)/public/themes

sudo cp -pir ./* /var/lib/redmine/public/themes/
# テーマ一式をコピーします

シンボリックリンク貼り替え

これは筆者の環境が

  • logディレクトリとfilesディレクトリを別の場所にリンクを張っているための措置です。
  • それ以外の場合は上述した /var/lib/redmine_$(date +%Y%m%d)からfilesやlogをコピーして下さい。
cd /var/lib/redmine

sudo rm -rf files

sudo rm -rf log

sudo ln -sf /mnt/wasabi/redmine/files files
# wasabiクラウドストレージを利用しています。

sudo chown -h www-data:www-data files

sudo ln -sf /var/log/redmine log
# ログは/var/log配下で一括管理しています。

sudo chown -h www-data:www-data log

データ再マイグレーション

プラグイン再マイグレーション

cd /var/lib/redmine

sudo -u www-data bundle install

sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production

apacheリスタート

systemctl status apache2.service

sudo systemctl restart apache2.service

systemctl status apache2.service

DBリストア

cd /hoge
# mysqldumpを行ったディレクトリ

mysql -h localhost -u redmine -p redmine < redmine_backup.$(date +%Y%m%d).sql
# パスワードはredmineインストール時に設定したDBユーザのものです

apacheリスタート

systemctl status apache2.service

sudo systemctl restart apache2.service

systemctl status apache2.service

動作確認

この状態でRedmineに管理者権限でログインします。手順通りなら

  • テーマ
  • 添付ファイル
  • プラグイン

などが正常に動いていると思います。

バージョンアップ後の診断

2023/03/18現在のRedmine4.2系の最新安定版:4.2.10がインストールされ、A+ と診断されました。

UbuntuサーバにフォトアルバムPiwigoインストール。

概要

メインで使っていたフォトアルバムLycheeの代わりにインストールしてみました。

動作確認環境

  • Ubuntu 20.04
  • MySQL 8
  • Apache 2.4
  • PHP 8.1

で動作を確認しています。

前提

上記が運用されていること

  • ドメインで名前解決できること
  • そのドメインに対する適切なSSL証明書が導入されていること

が条件です。

手順

さっくりとした手順

  1. プログラムを配置します。
  2. DBを設定します。
  3. Apache設定ファイルを追記して反映します。
  4. Web画面でインストールを行います。

Piwigo入手

  • 作業用ディレクトリに移動
cd hoge && pwd
  • Piwigoダウンロード
wget https://piwigo.org/download/dlcounter.php?code=latest -O piwigo-latest.zip
# 最新版のダウンロード
  • zip展開
unzip piwigo-latest.zip
  • アクセス権変更
sudo chown -R www-data:www-data piwigo
  • ディレクトリ配置
sudo mv piwigo /var/www/html/
# 運用に合わせて配置ディレクトリを指定してください
ls- ld /var/www/html/piwigo
# ファイルがあること、所有者がwww-dataを確認します

DB設定

mysql -u root -p
CREATE DATABASE piwigo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'piwigo_user'@'localhost' IDENTIFIED BY 'パスワード';
/* パスワードは任意のものを設定します */
GRANT ALL ON piwigo.* TO 'piwigo_user'@'localhost';
GRANT RELOAD ON *.* TO 'piwigo_user'@'localhost';
/* 後の運用を考えて、dumpが取得できるようにします */
FLUSH PRIVILEGES;
EXIT;

apache設定

バーチャルファイル作成

  • ServerName
  • ドメイン
  • 格納場所(ログ含む)
  • SSL証明書及び秘密鍵格納位置

は自分の環境に合わせてください。

cat <<- __EOF__ | sudo tee -a /etc/apache2/sites-available/piwigo.conf
<VirtualHost _default_:80>
ServerName album.example.com
# 公開するサーバのドメイン名を指定
 RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName album.example.com
    CustomLog /var/log/apache2/piwigo_access.log combined
    ErrorLog /var/log/apache2/piwigo_error.log
# ログの格納先を指定を指定

    DocumentRoot /var/www/html/piwigo
    <Directory /var/www/html/piwigo>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
    </Directory>
# DocumentRootは実際に配置したディレクトリを指定

  SSLEngine on

    Protocols h2 http/1.1
    Header always set Strict-Transport-Security "max-age=63072000"

SSLCertificateFile /etc/certs/example.com.crt
SSLCertificateKeyFile /etc/private/example.com.key
# 証明書と秘密鍵のパスを指定

</VirtualHost>

SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder     off
SSLSessionTickets       off

SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
__EOF__

バーチャルファイル有効化

sudo a2ensite piwigo.conf

設定反映

sudo apache2ctl configtest
# Syntax OKを確認します
sudo systemctl restart apache2.service
systemctl status apache2.service
# active (running)を確認します

表示確認

http://設定したドメイン

にアクセス後、以下が表示されます。

データベース設定

  • ユーザー: DBユーザ名
  • パスワード: 設定したDBのパスワード
  • データベース名:DB名

を入力します。

管理設定

  • ユーザ名:管理者名を入れます。
  • パスワード:管理者のパスワードを入れます。
  • メールアドレス:メールアドレスを入力します。

設定後、以下が表示されると設定完了です。

Redmineプラグイン導入時に起因するエラーの発生原因と対処方法について

こちらの記事を更に詳細にまとめたものとなります。

概要

様々なプラグインにより機能を追加できるのがRedmineの魅力。
しかしながら、そのプラグイン導入の過程によって予期せぬエラーが起きます。

本記事では、エラーの内容と対処、並びにこれが起きないための運用について筆者の経験を元に書き起こしています。

想定としている読者

  • LinuxでRedmineを動かしている
  • その管理をしている / 管理を任されている
  • プラグインインストール時にエラーが発生している

エラーが起きた環境

種別環境1環境2環境3
OSUbuntu 20.04CentOS 7Ubuntu 22.04
Redmine4.23.35.0
DBMySQL 8.3.xMariaDB 5.5.xMySQL 8.3.x
Ruby2.72.33.1

具体的に何が起こったか?

Case 1. エラー画面が表示され、どこにもアクセスできない。

We're sorry, buty something went wrong.
We've been notified about this issue and we'll take a look at it shortly.

この画面は「やってしまったか」感がとても強いです。

Case 1.の原因

経験上、以下の理由で発生しました。

原因1-1:DBマイグレーションをしていない

プラグインインストール時、DBのマイグレーションを行っていない手順ミスはありがちです。

原因1-1の対処:DBマイグレーションを行う。

こちらはrailsとapacheの手順です。自身の環境に合わせて実施してください。

cd /home/www-data/redmine && pwd
# Redmineのルートディレクトリに移動します。自分の環境に合わせます。

sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production
# RedmineのルートディレクトリでDBマイグレーションを実施します

sudo systemctrl restart apache2.service
# Webサービスを再起動します。

原因1-2: プラグイン名とレポジトリが異なる。(バージョン名が付与されている)

view_customizeのように、プラグイン名とレポジトリ名が異なるパターンはあります。

例:
https://github.com/onozaty/redmine-view-customize
と、レポジトリ名はredmine-view-customizeですが、実際のプラグイン名は
view_customizeです。

また、zipを直接入手した場合は、解凍したディレクトリにバージョン名が付与されます。

原因1-2の対処: ディレクトリをリネーム

以下は一例です。

cd /home/www-data/redmine/plugins && pwd
# Redmineのルートディレクトリに移動します。
sudo mv redmine-view-customize view_customize

sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production
# RedmineのルートディレクトリでDBマイグレーションを実施します

sudo systemctrl restart apache2.service
# Webサービスを再起動します。

原因1-3: プラグインとRedmineのバージョンが合ってない。

例として:
https://www.redmine.org/plugins/redmine_custom_workflows

  • Compatible with Redmine 5.0.x, 4.2.x, 4.1.x.

と書かれているように、古いRedmineのバージョンに合ってないプラグインをインストールしたときに起こりがちです。

また、逆に、プラグインが新しいRedmineに対応していない時にも発生します。

原因1-4: 導入済みのプラグインとコンフリクトを起こしている。

ある種、オープンソースの宿命と言えます。
有志/企業が機能を追加しているので、他のプラグインと同じライブラリを用いていたりDBのテーブルが重複するなどで発生します。

以下のように、メンテナが相性が悪いプラグインを認識している場合はそれに注意すればいいのですが、多数あるプラグイン同士の相性をチェックするのは極めて難しい問題です。

https://github.com/ncoders/redmine_local_avatars

As reported in issue #12, the plugin "mega_calendar" ist not compatible with this plugin due to an issue with the provided users_controller_path.rb file.

原因1-3 / 原因1-4の対処: プラグインのアンインストール

こちらも、rails / apacheでの実施です。自分の環境に合わせて実施してください。

cd /home/www-data/redmine && pwd
# 自分の環境に合わせます。

sudo -u www-data bundle exec rake redmine:plugins:migrate NAME=プラグイン名 VERSION=0 RAILS_ENV=production
# プラグイン名は /plugin/配下にあるディレクトリ名です

cd plugins && pwd
# プラグインが配置されているディレクトリに移動します。

sudo rm -rf プラグイン名

ls -ld /home/www-data/redmine/plugins/プラグイン名
# 削除したディレクトリが存在しないことを確認します

sudo systemctl restart apache2.service

上記、プラグインに起因したエラーの大半はDBの再マイグレーションやアンインストールによって解消しますが、これだけで収まらないのがRedmineプラグイン追加/アップデートの恐怖です。

Case 2. 一部の機能が使えない (Internal Error)

Case1.で発生したエラー画面の対処としてDB再マイグレーションやアンインストールを行った後、この事象が起きました。

  1. ログインはできる
  2. あるプラグインにアクセスできる

けれども、

  1. 管理画面に遷移する
  2. チケット一覧を見ようとする
  3. 他のプラグインの画面を見ようとする

等で、

Internal Error
An error occured on the page you were trying to access.
If you continue to experience problems please contact your Redmine administrator for assistance.
If you are the Redmine administrator, check your log files for details about the error.

の無慈悲なメッセージが出てきます。特にRedmineをファイルサーバ化するdmsfプラグイン周りで発生しました。

こうなると、

  • DBの再マイグレーション
  • プラグインアインインストール

でも、今の筆者の知見では修復できませんでした。その場合の対処方法は以下の通りです。

Case 2の対処方法: バックアップしたDBからの切り戻し

この作業は、「エラーを起こす前のDBバックアップデータを持っていないと元に戻すことはできません」

この前提条件がない場合は他の有識者に頼ってください。(少なくとも筆者は持ち合わせていません)

また、以下の環境で復旧を確認しています。

  • MySQL 8.0.3系
  • Redmine 5.0
  • Redmine 4.2

手順

  • プラグインアンインストール(実施済みの方は不要です)
cd /home/www-data/redmine && pwd
# 自分の環境に合わせます。

sudo -u www-data bundle exec rake redmine:plugins:migrate NAME=プラグイン名 VERSION=0 RAILS_ENV=production
# プラグイン名は /plugin/配下にあるディレクトリ名です

cd plugins && pwd
# プラグインが配置されているディレクトリに移動します。

sudo rm -rf プラグイン名

ls -ld /home/www-data/redmine/plugins/プラグイン名
# 削除したディレクトリが存在しないことを確認します

sudo systemctl restart apache2.service
  • バックアップしたDBのレストア
cd /hoge && pwd
# DBデータをバックアップしたディレクトリに移動します。

mysql -h DBホスト -u RedmineのDBユーザ -p RedmineのDB名 < RedmineのDBバックアップ
# 例 mysql -h localhost -u redmine -p redmine < redmine_backup.$(date +%Y%m%d).sql
# この処理で聞かれるパスワードはredmineインストール時に設定したDBユーザのものです

sudo systemctl restart apache2.service

この後、元に戻っていれば作業は完了です。

こうならないために

日々のバックアップを取る

これは必須です。最低限、データベースの定期的なバックアップを取り、障害に備えましょう。

参照(『こうなってしまったため』書き起こしました:)

また、作業前に

cd /hoge && pwd
# 任意のバックアップディレクトリに移動します

mysqldump -h localhost -u redmine -p --no-tablespaces --single-transaction redmine > redmine_backup.$(date +%Y%m%d).sql
# それぞれ -h ホスト名 -u redmine -p ユーザ オプション db名です。
# パスワードはredmineインストール時に設定したDBユーザのものです

等の、DBバックアップも必要です。

システムごとバックアップを取る

仮想サーバで動かしている、AWSのようなクラウドサービスを利用している場合はスナップショットを取得し、OSごとバックアップするのが後腐れありません。

続・MySQLの自動バックアップ。(パスワードによる暗号化付与)

こちらの記事で挙げたRedmineなどのMySQLを実行するスクリプト。

この問題点を修正します。

問題点

  • むきだしのSQLファイルが平文で格納されてしまうのはセキュリティ的によろしくありません。
  • MySQLのバックアップ時に使うアカウントファイルが誰でも読み取れるのも問題です。

そこで、バックアップされたファイルにパスワードをかけることで簡単な防波堤を作ることにします。

前提

上記URLに併せます。

  1. MySQL dumpを行うDBにRELOAD権限があること。
  2. 次の環境で動作を確認しています。
  • Ubuntu 20.04
  • MySQL 8.0.32

実施した手順

さっくりとした手順

  1. バックアップディレクトリを作成します。
  2. DBにアクセスするためのアカウント情報を記したファイルを作成します。
  3. 開封パスワードを格納するディレクトリを作成します。
  4. バックアップスクリプトを作成します。
  5. crontabに登録します。

バックアップディレクトリを作成します。

sudo mkdir -p /home/backup/mysql
# 運用に合わせて指定ください。ファイルサーバや別パーティションにマウントしている方がサーバ事態の障害発生でも冗長化を持たせられます。

sudo chown -R hoge:hoge /home/backup/mysql
# ディレクトリの所有者をログインユーザに修正します

cd /home/backup/mysql && pwd
# 指定したディレクトリに移動します

DBにアクセスするためのアカウントファイルを作成します。

Cronによる自動実行を前提としているため、スクリプト実行時にDBユーザとパスワードを記したファイルを読み込むことでセキュリティのリスクを抑えます。

sudo mkdir -p /home/hoge/db_password
# 運用に合わせて指定ください。

cd /home/hoge/db_password && pwd
# 指定したディレクトリに移動します

以下の内容を教義・信仰に沿ったエディタで作成します。(【】内は取り除き、自分の設定に合わせます)

  • アカウントファイル内容
    • ファイル名:account.txt
[client]
user = 【RedmineのDBユーザ】
password = "【RedmineのDBユーザ用パスワード】"

その後、このファイルの読み取り権限を変更します。

chmod 400 account.txt

ls -l account.txt
# パーミッションが400であることを確認します

アカウントファイルでアクセスできることを確認

mysql --defaults-extra-file=【アカウントファイルを格納したディレクトリ】/account.txt

#MySQLのプロンプトが出れば成功です。exitで抜けます。

スクリプト作成

以下の内容を教義・信仰に沿ったエディタで作成します。

  • スクリプト内容
    • スクリプト名:pw_mysql_daily_backup.sh
#!/bin/bash

## 変数ここから ##
# SQLをバックアップするディレクトリ(保管先)を指定します。運用に合わせて指定ください。
backup_dir="/home/backup/mysql"
# 保持するバックアップの世代を日数で指定します。
keep_days=7
# ファイルに付与する日付/作業ディレクトリ名/バックアップファイル名を指定します。
current_date=$(date +%Y%m%d)
backup_name="redmine_mysql_${current_date}"
zip_file="redmine_mysql.${current_date}.zip"
# アカウントファイルを指定します。運用に合わせて指定ください。
credentials_file="$HOME/redmine/account.txt"
# パスワードを記録するファイル名を指定します。運用に併せてして指定ください。
password_dir="$HOME/restore_redmine"
password_file="${password_dir}/mysql-restore.$current_date.txt"
# redmineのデータベース名を指定します。
database_name=redmine
# バックアップ時に指定するオプションを指定します。
options="--defaults-extra-file=$credentials_file --no-tablespaces --single-transaction"
## 変数ここまで ##

## 処理ここから ##

# 1.アカウントファイルのパーミッションが400かどうかチェックします。
# 400以外は処理そのものを終了します。
permissions=$(stat -c "%a" "$credentials_file")
if [ "$permissions" != "400" ]; then
    echo "アカウントファイルのパーミッションは400である必要があります。"
    exit 1
fi

# 2.一時的なバックアップディレクトリを作成します。
mkdir "${backup_dir}/${backup_name}"

# 3. mysqldumpを実行してデータベースのバックアップを取ります。
mysqldump $options -h localhost $database_name > "${backup_dir}/${backup_name}/${backup_name}.sql"

# 4. パスワードによる暗号化を実施します。
password=$(openssl rand -base64 12)
cd "${backup_dir}/${backup_name}"
zip -r "${backup_dir}/${zip_file}" -P "$password" .
cd -

# 5. 一時的なバックアップディレクトリを削除します。
rm -rf "${backup_dir}/${backup_name}"

# 6. 解凍パスワードを指定ディレクトリに保存します。
echo $password > $password_file

# 7.パスワードの読み取り権限を600に変更します。
chmod 600 $password_file

# 8. 保持期間より古いバックアップファイルを削除します。
find "$backup_dir" -name "redmine_mysql.*.zip"  ! -type f -newermt "${keep_days} days ago" -delete
find "$password_dir" -name "*restore*.txt" ! -type f -newermt "${keep_days} days ago" -delete

## 処理ここまで

前回との修正点

  1. 変数と処理のセクションを明確化しています。
  2. アカウントファイルのパーミッションチェックを行い、400以外は処理を中止します。
  3. opensslで生成したパスワードで暗号化します。(このパスワードはランダムで生成されるので運用者は覚える必要がありません)
  4. 圧縮と同時に暗号化を行うので、gz形式からzip形式に変更しています。
  5. このパスワードを任意のディレクトリに転送します。
  • 実行権限の付与
chmod +x pw_mysql_daily_backup.sh

動作確認

cd 【スクリプトを格納したディレクトリ】 && pwd
bash pw_mysql_daily_backup.sh

以下を確認します。

  1. エラーなく実行できること
  2. バックアップ格納ディレクトリにredmine.sql.実行日付.zip形式でファイルが作成されること
  3. パスワードファイル格納ディレクトリにファイル名.実行日付.txt形式でファイルが作成されること
  4. unzip redmine.sql.実行日付.zipでファイル解凍時にパスワードを確認されること
  5. パスワードファイルで暗号化されたファイルを解凍することができること

Crontab設定

Cron登録

crontab -e

登録内容例

0 0 * * * /home/backup/mysql/pw_mysql_daily_backup.sh
# 実行時刻、頻度などは自分の運用形態に合わせます。
# また、既に平文でのバックアップスクリプトを設定している場合はコメントアウトして処理を外します。

Cron登録確認

sudo tail -20 /var/log/cron.log

操作時刻に

  • BEGIN EDIT
  • REPLACE
  • END EDIT

が表示されれば設定は完了です。

動作確認日

2023/02/18

検証:Ubuntu 20.04にRedmine 5.0のインストールと4.2へのダウングレード。

ふと思い立っての検証です。

あらまし

別サイトに記載しているRedmine4.2のインストール手順。

https://atelier.reisalin.com/projects/zettel/knowledgebase/articles/19

この手順で「Redmine 5.0を設定できるか?」と思い立ち、検証用のまっさらなUbuntu 20.04を用意しました。

前提

以下を設定しています。

  • インターネット回線に接続されていること
  • ドメインで名前解決できること
  • SSH接続が可能なこと

実施手順

上記のリンクの手順に沿いました。異なっている点は、Redmine 5.0をダウンロードするため、

sudo -u www-data svn co https://svn.redmine.org/redmine/branches/5.0-stable /home/www-data/redmine

としただけです。

無事にRedmine5.0が動き、以下の参照どおりにSSLを設定。

https://atelier.reisalin.com/projects/zettel/knowledgebase/articles/20

これで試しにと思いましたが、

プラグインとの兼ね合い

「どうしても使いたいプラグインがRedmine 5.0に対応していない」事情により継続利用は無理だと断念。特に

  • knowlegebase
  • redmine_issue_badge_plugin

の2つが利用できないのは非常に痛い状況でした。

Redmine 5.0→4.2へのダウングレード

そこで、インストールしたばかりのRedmine5.0を4.2に即座に戻すことにします。

注意点

この手順は、データが全く入っていない状況で可能な作業です。「こんな手法を採ったのがいる」程度に参照ください。

前提

  • 上記手順を元にRedmine 5.0がインストールされ
  • なおかつデータが何も入っていない
  • RedmineのDB名は「redmine」
  • apache2設定ファイルは稼働済み

さっくりとした手順

  1. apache2サービスを落とします。
  2. データベースをまるごと削除します。
  3. 同じ名前でDBを再作成します。
  4. プログラムを再配置します。
  5. apache2サービスを起動します。

apache2サービス停止

sudo systemctl stop apache2.service
#これを行わないと後述のDBが消去できません

mysqlでDBを再作成します。

sudo mysql -u root -p
DROP DATABASE redmine;
# DBを削除します

CREATE DATABASE redmine character set utf8mb4;
# DB "redmine" を再作成します

exit

Redmineプログラムを再配置します。

sudo rm -rf /home/www-data/redmine
# Redmineを配置したディレクトリごと削除します

sudo -u www-data svn co https://svn.redmine.org/redmine/branches/4.2-stable /home/www-data/redmine
# 設定したときと同じディレクトリに4.2を再配置します

Redmineのコンフィグを設定します。

sudo cp -pi /home/www-data/redmine/config/database.yml.example /home/www-data/redmine/config/database.yml

sudo vi /home/www-data/redmine/config/database.yml
# 教義・信仰に従ったエディタで編集してください。

database.yml 編集内容

production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  # rootからredmineに変更します
  password: "redmine用のパスワード"
  encoding: utf8mb4
# 本番環境(production)のみ設定を行います

Redmineのマイグレーションを行います。

cd /home/www-data/redmine/ && pwd
# /home/www-data/redmine/ (Redmineを配置したディレクトリ)であることを確認します

sudo -u www-data bundle install --without development test --path vendor/bundle

sudo -u www-data bundle exec rake generate_secret_token

sudo -u www-data RAILS_ENV=production bundle exec rake db:migrate

sudo -u www-data RAILS_ENV=production REDMINE_LANG=ja bundle exec rake redmine:load_default_data

apache2サービスを起動します

すでにapache上でRedmineを動かす手はずは整っており、プログラムの実行ディレクトリも同じ。ならば、設定ファイルは修正せずに済むという判断のもとに実行。

sudo apache2ctl configtest
# Syntax OK を確認します

sudo systemctl restart apache2.service

systemctl status apache2.service

サイトの表示を確認します。

http://設定したRedmineドメイン

でRedmineのトップページが表示されれば成功です。

検証段階だからこそ行えた手荒な手段でした。

MySQLの定期バックアップ、現状の運用に修正。

こちらの記事を2023年2月時点での運用に併せ、以下、修正しました。

概要

Redmineのメンテナンスの中で、「データベースのバックアップ」は非常に重要なものです。

そこで、改めて、シェルスクリプトとCronによるバックアップ手順を整理しました。

動作を確認した環境

  • Ubuntu 20.04 LTS
  • Redmine 4.2
  • MySQL 8.0.32

実施前提

  • MySQLに管理者権限でログインできること。
  • Redmine用のDBとDBユーザ、DBパスワードを把握していること。
  • また、DBサーバはローカルホストです。

確認した手順

  • Redmineが稼働しているUbuntuサーバのターミナル上での操作です。
  • MySQL以外は全て一般権限で実行します。

さっくりとした手順

  1. Redmineのデータベースユーザに権限を付与します。
  2. バックアップディレクトリを作成します。
  3. アカウントファイルを作成します。
  4. バックアップスクリプトを作成します。
  5. crontabに登録します。

データベース設定

管理者権限でMySQLにログインします。

mysql -u root -p

データベースのユーザ権限を変更します。

これを行わないとDump処理ができませんでした。

GRANT RELOAD ON *.* TO '【RedmineのDBユーザ】'@'localhost';
FLUSH PRIVILEGES;
EXIT

ディレクトリとスクリプト作成

バックアップディレクトリ作成

sudo mkdir -p /home/backup/mysql
# 運用に合わせて指定ください。ファイルサーバや別パーティションにマウントしている方がサーバ事態の障害発生でも冗長化を持たせられます。

sudo chown -R hoge:hoge /home/backup/mysql
# ディレクトリの所有者をログインユーザに修正します

cd /home/backup/mysql && pwd
# 指定したディレクトリに移動します

アカウントファイル作成

※このファイルを作成しないと、「安全ではない」とエラーが出ます。

以下の内容を教義・信仰に沿ったエディタで作成します。(【】内は取り除き、自分の設定に合わせます)

  • アカウントファイル内容
  • ファイル名:account.txt
[client]
user = 【RedmineのDBユーザ】
password = "【RedmineのDBユーザ用パスワード】"

アカウントファイルでアクセスできることを確認

mysql --defaults-extra-file=account.txt

MySQLのプロンプトが出れば成功です。exitで抜けます。

スクリプト作成

以下の内容を教義・信仰に沿ったエディタで作成します。

  • スクリプト内容
  • スクリプト名:mysql_daily_backup.sh
#!/bin/bash

# スクリプトの日付形式を定義します
date=$(date +"%Y%m%d")

# バックアップディレクトリを定義します
# 上記手順で示したディレクトリを指定してください
backup_dir="/home/backup/mysql"

# アカウントファイルを指定します
credentials_file="$backup_dir/account.txt"

# バックアップ時に指定するオプションを定義します
options="--defaults-extra-file=$credentials_file --no-tablespaces --single-transaction"

# バックアップファイル名を定義します
backup_file="$backup_dir/redmine.sql.$date.gz"

# バックアップを実行し、.gz形式でバックアップをします
mysqldump $options -h localhost redmine | gzip > $backup_file

# 10世代前の圧縮ファイルを削除します(運用に合わせて指定ください)
find $backup_dir -type f -name "redmine.sql.*.gz" -mtime +10 -delete
  • 実行権限の付与
chmod +x mysql_daily_backup.sh

動作確認

sh mysql_daily_backup.sh

以下を確認します。

  • エラーなく実行できること
  • redmine.sql.実行日付.gz形式でファイルが作成されること
  • gunzip redmine.sql.実行日付.gzでファイルが解凍できること

Crontab設定

Cron登録

crontab -e

登録内容例

0 0 * * * /home/backup/mysql/mysql_daily_backup.sh
# 実行時刻、頻度などは自分の運用形態に合わせます。

Cron登録確認

sudo tail -20 /var/log/cron.log

操作時刻に

  • BEGIN EDIT
  • REPLACE
  • END EDIT

が表示されれば設定は完了です。

動作確認日

2023/02/08

Page 1 of 2

Powered by WordPress & Theme by Anders Norén