タグ: Ubuntu Page 2 of 21

XServer VPS切り替え後のトラブル。(ログの肥大化によるサービス停止と対応・恒久的対応策)

概要

2025/08/12 朝、管理しているWebサーバーにSSHで接続できなくなり、Webサイトも全て閲覧できなくなる障害が発生しました。本記事は、その原因究明から、応急処置、そして恒久対策までの一連の流れを記録したものです。

障害発生時の状況

  • Webサイトにアクセスすると、タイムアウトエラーになる。
  • SSHでログインしようとしても、接続ができない。
  • VPSの管理コンソールから再起動をかけると、redis-serverの停止処理(DBの保存)でタイムアウトし、正常にシャットダウンできない。
  • 強制再起動後、一時的に復旧するものの、しばらくすると再び応答がなくなる。

止まっていたサービス

  • mongod
  • redis-server
  • elasticsearch
  • growi

原因の特定手順

切り分け中に原因判明

障害の切り分け中、Wasabiクラウドストレージをマウントしようとした際に、以下のエラーが発生しました。

  • クラウドストレージのマウントを実行
sudo mount -a
mount.s3fs: unable to access MOUNTPOINT /mnt/wasabi: No space left on device

No space left on device(デバイスに空き領域がありません)」というこのエラーメッセージ。150GBもディスク容量があるのになぜ……? 思いつつ調査を行います。

ディスク使用率の確認

上記のエラーを受け、ディスクの空き容量を確認しました。

df -h

実行結果:

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       145G  145G     0 100% /

この結果から、**ルートディレクトリ(/)のディスク使用率が100%**になり、空き容量がゼロになっていることが、数値的にも裏付けられました。

容量を圧迫しているディレクトリの調査

次に、どのディレクトリが容量を使い果たしているのかを調査しました。

sudo du -h -d 1 /

実行結果(抜粋):

125G    /var

/varディレクトリが125GBを占めていることが分かりました。さらに詳細に調査を進めます。

sudo du -h -d 1 /var/log

実行結果(抜粋):

122G    /var/log/apache2

/var/log/apache2が122GBという、異常なサイズになっていることが特定できました。

肥大化したログファイルの特定

その後、/var/log/apache2ディレクトリの中身を確認しました。

ls -lh /var/log/apache2

実行結果(抜粋):

-rw-r-----  1 root adm   61G  8月 12 08:09 modsec_audit.log
-rw-r-----  1 root adm   59G  8月 11 00:15 modsec_audit.log.1

**ModSecurityの監査ログ(modsec_audit.log)**が、わずか2日間で120GB以上にまで肥大化していたことが、直接の原因であると確定しました。

ここまで分かれば対処はもうすぐです。

対処手順

ステップ1:応急処置(空き容量の確保)

まず、サーバーを正常に動作させるため、巨大化した監査ログを削除し、空き容量を確保します。

  • 巨大なログファイルを削除
sudo rm /var/log/apache2/modsec_audit.log*
  • Apacheを再起動して、ファイルハンドルを解放
sudo systemctl restart apache2.service

ステップ2:恒久対策(監査ログの無効化)

modsec_audit.logは、攻撃の詳細な分析やデバッグには役立ちますが、今回のようにログがディスクを圧迫し、サーバーダウンを引き起こしますため、この設定をオフにします。

  1. ModSecurityのメイン設定ファイルを開きます。 sudo nano /etc/modsecurity/modsecurity.conf
  2. SecAuditEngineの値をOffに変更します。 修正前: SecAuditEngine RelevantOnly 修正後: SecAuditEngine Off
  3. Apacheをリロードして設定を反映させます。 sudo systemctl reload apache2.service

その後、念のためサーバそのものを

```bash
sudo reboot
```

で、状況が元に戻っていることを確認しました。

まとめ

今回の障害は、ModSecurityの監査ログが有効になったまま放置され、そのログがログローテーションの対象になっていなかったために、ディスク容量を100%使い果たしたことが原因でした。

前述したとおり、よりよいスペックのサーバに引っ越した後の出来事だけに、かなりの冷や汗ものでした。

VPSをWebArena→XServerへと切り替えたときのメモ。

2024年9月から利用してきた WebARENA VPS を XServer VPS に切り替えました。
理由は大きく分けて以下の3点です。

1. 物理的リソースの逼迫

旧環境では、以下のアプリが同時稼働していました。

この構成ではメモリ使用量が常に高止まりし、スワップ発生も頻繁。
安定運用のためには、より余裕のある環境が必要でした。

2. キャンペーン終了によるコスト増

WebARENA VPS の 4GB プランはキャンペーン中であれば 月額約980円 と魅力的でしたが、
終了後は 月額約1,600円 に上昇。コスト面の優位性が失われました。

3. XServer VPS を選んだ理由

  • 既にこの WordPress をホストしている会社で信頼性が高い
  • 同価格帯でも メモリ6GB と余裕がある
  • NVMe SSD 搭載でストレージ速度が段違い
  • 年額契約でキャンペーン終了後も料金安定
  • 最終的にWebARENA 4GB プランより安くなる

サーバ移行のタイムライン

  • 8/03 : 契約、初期設定(UFW / fail2ban)
  • 8/04 : 負荷試験を兼ねて Growi 導入(Apache / MongoDB / Elasticsearch / Node)
  • 8/05 : MySQL 導入
  • 8/06 : ModSecurity 導入
  • 8/07 : PHP-FPM 導入、Wasabi 接続、Nextcloud・BookStack・Laravel アプリ移行
    • この時点で「Growiを削除しなくてもいける」と確信
  • 8/08 : Redmine 6.0 新規構築に挑戦 → DB移行でエラー
    • 方針転換し Redmine 5.1 を移植(公開用)
  • 8/09 : 残りの Redmine 2件も移行完了、DNS 切替、WebARENA 解約

結果: 7日間で全サービス移行完了。Growi 常駐のまま全サイトを載せられたのは想定外というか、嬉しすぎる誤算でした。

スペック比較

項目WebARENA(旧)XServer(新)変化
CPUXeon E3-12xx (2011年)AMD EPYC Milan (2021年)大幅性能向上
vCPUコア数4コア4コア同等
メモリ4GB6GB1.5倍
ストレージ80GB SSD150GB NVMe SSD約1.9倍+高速化
ネットワーク500Mbps100Mbps低下
月額料金約1,630円(終了後)1,439円(年額換算)安価

新環境のメモリ状況

free -h
               total        used        free      shared  buff/cache   available
Mem:           5.8Gi       2.1Gi       1.6Gi       121Mi       2.5Gi       3.6Gi
Swap:          2.0Gi       623Mi       1.4Gi

Growi(MongoDB + Elasticsearch + Node)常駐のままで 3.6GiB available
旧環境より明確に余裕があり、スワップも軽減。

感想と今後

  • 前払いの安心感:年額払いで価格変動リスクなし
  • サービス統合効果:VPSとレンタルサーバを同社で一元管理
  • 展望:Redmine 6.0 アップデート挑戦、または5.1での堅牢運用

個人的に、NWの転送速度をサーバのリソースで解決するパワープレイができたのが安心です。

公開用Redmineのサーバ移行。

一般公開しているRedmine「クーケン島観光ガイド」、新規VPS、XServerへの移行に伴いデータの移設を行いました。

の構成はそのまま。コンテンツもそのまま移植しています。

ここに至るまで盛大にハマりましたが、なんとかなりました。

この時の記事は改めて記載します。

Apache全般のログローテーション設定。

サーバの移設中なので、ログに関しての記録を残しています。

概要

Webサーバ全般のメンテナンスで特に必要なのは

「ログを適切に管理する」

です。

  • 不審なアクセスの兆候
  • 自分のやらかし

を目の当たりにできる手段だからです。(特に後者に助けられたことは幾度となくあります)

そのため、Webサーバ上のログのローテーションを行い、履歴を追いやすくし、更にサーバの容量も削減するログローテーションを行います。

ログローテーションとは

ログファイルが肥大化するのを防ぐために、古いログを一定のルールに基づいて新しいログに切り替えたり、削除したりする仕組みのことです。

hogeサイトのアクセス記録である/var/log/access.logというファイルは、何も設定していないとログが記録され続けます。これによって以下の問題が起きます。

  • ログの肥大化によるサーバ容量の圧迫
    • テキストファイルぐらいと思う方がいるかも知れませんが、昨今の不正アクセスやAIサイトのクローラーのアクセス頻度は異常です。個人サイト程度でも一日数十MBはよくあります。
    • RedmineのようなWebアプリの場合、そのログは数百MBになります。
    • → このため、指定した期間でログを新しいログに差し替え、古いものは削除していくという仕組みを取ります。
  • ログの追記によるサーバのリソース増加
    • 追記自体の負荷は小さいですが、そのログをgrepなどで分析・検索する際に、巨大な単一ファイルだと非常に多くのメモリとCPUを消費します。
    • → ログを適切に分割(ローテーション)しておくことで、日々のログ分析が高速かつ軽量に行えるようになります。

これを行うべきタイミング

「Webサーバに新たなWebサイトやサービスを立ち上げたとき」 です。
試験運用などでもログは問題が起きたときのヒントとなるからです。

環境

  • Ubuntu 24.04
  • Apache 2.4
    • apt(aptitude)によるパッケージ管理でインストールしているため、Apacheの実行ユーザはwww-dataです。

備考

ディストリビューションが違ってもこの手順は有効ですが、RockyやAlma等のRHEL系のApacheの実行ユーザは通常はapacheであることに注意しましょう。

さっくりとした手順

  1. (念のため)設定を行うサイトのログをwww-dataに変えます。
  2. ログローテーションのファイルを作成します。
  3. ログローテートの設定が有効かを確認します。

ここでは、hogeサイト(/var/log/hoge)のログをローテーションする方法です。

サイトのログの実行ユーザの変更(所有者変更)

これは、Redmineのlogプラグインのように、Webインタフェース上からログを閲覧できるプラグインがある場合、Apacheを実行しているサービス自体が参照できるようにするためです。

  • chownによる所有者変更
sudo chown -R www-data:www-data /var/log/hoge

ログ一式の所有者を変えます。ログファイルの形式は自分の環境に合わせます。

  • 所有者変更確認
ls -l /var/log/hoge

ログファイルの所有者とグループがwww-dataであることを確認します。

ログローテーションファイルの作成

ファイル名やログのパスは自分の環境に合わせます。 ここを間違えると元も子もありません。

cat <<- __EOF__ | sudo tee -a /etc/logrotate.d/hoge
/var/log/hoge/*.log {
    daily
    missingok
    rotate 10
    compress
    copytruncate
    notifempty 
    su www-data www-data
__EOF__

これは、以下を行います。

  • daiy
    • 1日ごとにローテーション
  • missingok
    • ログファイルが存在しなくてもエラーにしない
  • rotate 10
    • 10世代分の古いログファイルを保持する(それ以降は破棄)
  • compress
    • 古いログファイルをgzipで圧縮する
  • copytruncate
    • ログをコピーしてから元のファイルを空にする(サービス無停止でログ切替)
  • notifempty
    • ログファイルが空の場合はローテーションしない
  • su www-data www-data
    • ローテーション後のファイルの所有者を指定

他、週ごとやログのファイル形式(日付形式)などを設定できます。こちらは運用に合わせてください。

ログローテーションの確認

  • 設定確認
sudo logrotate -dv /etc/logrotate.d/hoge

※先ほど作成したファイル名に合わせます。

ここでエラーがなければログローテーションはできています。

  • ログローテーションの即時実行

すぐにローテーションを確かめる場合は以下を実行します。強制的にログローテーションを行うコマンドです。

sudo logrotate -f /etc/logrotate.d/hoge

このコマンドを実行後、/var/log/hoge/ディレクトリ内にaccess.log.1.gzのようなファイルが作成され、元のaccess.logが空になっていれば、設定は完璧です。

CPUとメモリ情報を表示するワンライナー。

概要

サーバスペックの要となる

  • CPU
  • コア数
  • メモリ量
  • スワップ量

を一度に表示するワンライナーです。

ワンライナー内容

awk 'BEGIN {FS=":"; OFS="\t"} /^model name/ && !cpu_model {cpu_model=$2; gsub(/^ */, "", cpu_model)} /^processor/ {cores++} /^MemTotal/ {mem_total=$2} /^MemAvailable/ {mem_avail=$2} /^SwapTotal/ {swap_total=$2} END {printf "CPUモデル\t: %s\n", cpu_model; printf "CPUコア数\t: %s\n", cores; printf "合計メモリ\t: %.2f GiB\n", mem_total/1024/1024; printf "利用可能メモリ\t: %.2f GiB\n", mem_avail/1024/1024; printf "合計スワップ\t: %.2f GiB\n", swap_total/1024/1024}' /proc/cpuinfo /proc/meminfo

実行結果

CPUモデル       : AMD EPYC-Milan Processor
CPUコア数       : 4
合計メモリ      : 5.78 GiB
利用可能メモリ  : 5.34 GiB
合計スワップ    : 2.00 GiB

と、分かりやすい表示で一気に表示してくれます。

Ubuntuでhistoryの履歴を追いやすくするシェルスクリプト並びにコマンド化。

概要

設定変更時、過去のコマンド履歴を確認するため

history | grep command

として過去の履歴を確認します。これをシェルスクリプトの力で解決します。(スクリプト作成にはGemini pro 2.5を利用)

スクリプト

  • histgrep.sh
#!/bin/bash

# スクリプトに引数が渡されたかどうかで処理を分岐
if [ "$#" -gt 0 ]; then
  # 引数が存在する場合、その値を検索文字列として使用
  SEARCH_TERM="$1"
else
  # 引数がない場合、対話式でユーザーに入力を促す
  read -p "探したいコマンドを入力してください: " SEARCH_TERM
fi

# 検索文字列が空の場合はエラーメッセージを出して終了
if [ -z "${SEARCH_TERM}" ]; then
  echo "検索文字列が入力されていません。"
  exit 1
fi

# historyコマンドの代わりに、履歴ファイルを検索する
HISTFILE_PATH="${HISTFILE:-$HOME/.bash_history}"

echo "実行履歴から「${SEARCH_TERM}」を含むコマンドは以下の通りです。"
grep "${SEARCH_TERM}" "${HISTFILE_PATH}"

これを保存して、

chmod +x histgrep.sh

で実行権限をつけます。

コマンド実行例

引数無しの対話型

./histgrep.sh
探したいコマンドを入力してください: bundle
実行履歴から「bundle」を含むコマンドは以下の通りです。
sudo -u www-data bundle install --without development test --path vendor/bundle
sudo -u www-data bundle install
sudo -u www-data bundle install --without development test --path vendor/bundle
sudo -u www-data bundle exec gem install rake
sudo -u www-data bundle install --without development test --path vendor/bundle
sudo -u www-data bundle install --without development test --path vendor/bundle
sudo bundle install

と、探したい文字列を含む履歴をhistory(正確には履歴ファイル)から参照します。

引数型

./histgrep.sh configtest
実行履歴から「configtest」を含むコマンドは以下の通りです。
sudo apache2ctl configtest

このように、探したい文字列を引数とすることで、そのコマンドを探せます。

コマンド化

これをコマンド化します。

sudo ln -sf /path/to/script/directory/histgrep.sh /usr/local/bin/histgrep

/path/to/script/directory/histgrep.shはフルパスで、スクリプトがある場所を指定します。

which histgrep

で、/usr/local/bin/histgrepを確認。

後は、作業中でも

histgrep tar

などとすれば、過去に実行したコマンドの履歴を容易に参照することができます。

U01b_VPS(XServer)でUbuntu 24.04を立ち上げたときの手順(アカウントの設定→SSH接続確認)

概要

VPSサービスなどで、最初にrootアカウントとWebコンソールのみが提供される環境を想定し、安全な運用を行うための初期設定手順を解説します。

この手順のゴール

  • rootアカウントでの直接ログインを禁止する。
  • 日常的な管理作業は、sudo権限を持つ一般ユーザーで行うようにする。
  • パスワード認証を無効化し、より安全な「公開鍵認証」でのみSSHログインできるようにする。

最大の注意点:サーバーからの締め出し

この設定作業は、手順を一つでも誤ると、二度とサーバーにログインできなくなる危険性を伴います。特に、SSH接続を唯一のアクセス手段としている場合は、細心の注意が必要です。この記事では、Webコンソールを「ライフライン」として使い、安全に設定を完了させる手順を示します。

スタート地点(前提)

今回のケースは、XServer VPSで、Ubuntu 24.04を立ち上げたばかりの設定です。

※Webのシリアルコンソールは最初しか使わないため、この時のサーバではsshd秘密鍵は作成しません。(後で作成します)

DNS設定を行い、名前解決ができるようにしておくと便利です。

ややさっくりとしない手順

  1. 【root】 メンテナンス用ユーザーを作成する。
  2. 【Webコンソール】 作成したユーザーでパスワードログインできることを確認する。(←安全の確保)
  3. 【root】 作成したユーザーにsudo権限を付与する。
  4. 【メンテナンス用ユーザ】 sudo権限が有効になったことを確認し、rootアカウントをロックする。
  5. 【メンテナンス用ユーザ】 SSHをインストールし、公開鍵認証の設定を行う。
  6. 【自分のPC】 SSHで鍵認証ログインできることを確認する。
  7. 【メンテナンス用ユーザ】 最後に、SSHのパスワード認証を無効化する。

メンテナンス用のユーザ作成(root)

  • ユーザ作成
adduser [メンテナンス用ユーザ]

[メンテナンス用ユーザ]は英数字です。その後、パスワード設定などを対話式で求められるので、指示に従って入力します。

  • ログイン確認
exit

Webシリアルコンソールから抜けます。

メンテナンス用のユーザ作成確認(メンテナンス用のユーザ)

  • 作成したユーザでログイン確認

Webコンソールで、作成したユーザ名とパスワードでログインできることを確認。

whoami

で、設定したアカウントであることを確認します。

  • rootに昇格できないことを確認
sudo su -

としても、rootに昇格することはできません。なので、一度

exit

でコンソールを抜け、rootでログインし直します。

メンテナンス用のユーザのroot昇格設定(root)

  • メンテナンス用のユーザにsudoを追加

rootでログイン後、

usermod -aG sudo [メンテナンス用ユーザ]

で、sudoグループにこのユーザを加えます。

  • sudo追加確認
id -a [メンテナンス用ユーザ]

で、以下のように表示されることを確認します。

uid=1000(hoge) gid=1000(hoge) groups=1000(hoge),27(sudo),100(users)

修正したユーザのグループに、27(sudo)と表示されることがポイントです。

確認後、

exit

で更にrootを抜け、今度はメンテナンス用のユーザでログインします。

rootのロック (メンテナンス用のユーザ)

  • root昇格

メンテナンス用のユーザでログイン後、

sudo su -

で、rootに昇格できることを確認します。(※できない場合は前段の作業をやり直してください)

whoami

root表示されることも確認します。

  • rootロック
passwd -l root

として、rootそのものをロックします。

  • rootのロック確認
exit

を2回行い、Webコンソールから抜けます。

rootロック確認

  • メンテナンス用のユーザ→Webコンソールでログイン可能
  • root→Webコンソールでログイン不可能を確認します。

これ以降はメンテナンス用のユーザで作業を行います。

SSH設定

Ubuntu Desktop系と違い、Ubuntu Serverではsshdがデフォルトでインストールされていない場合があります。

sudo apt install ssh

で、sshdをインストールします。

インストール後、

ssh -V

でバージョンが表示されることを確認し、

systemctl status ssh.service

で、runningenabledを確認します。

SSH鍵ペア作成

鍵認証でログインできるようにします。

ssh-keygen -t ed25519
  • 鍵の格納場所は空Enter。(/home/hoge/.ssh/
  • パスワードを設定します。

SSH鍵ペア作成確認

  • 鍵格納ディレクトリに移動
cd .ssh
  • ファイルの内容確認
ls -l

以下のファイルを確認します。

  1. id_ed25519
  2. id_ed25519.pub ※これらのファイルはscp等で自分のクライアントにコピーします。

鍵の設定変更

公開鍵をauthorized_keysに変更し、パーミッションを厳密にします。

  • ファイル名変更
cat id_ed25519.pub >> authorized_keys
  • パーミッション設定
chmod 600 authorized_keys

秘密鍵の保存

この秘密鍵(id_ed25519)は、サーバー全体のアクセス権を持つ、言葉通りの意味でのマスターキーです。

この秘密鍵を奪われることは、サーバーの全権限を奪われることと同義です。 そのため、管理は厳密に、そして自分だけがアクセスできる安全な手段(パスワードマネージャーや暗号化されたストレージなど)で、必ずバックアップをこの段階で行ってください。

ファイアウォール(パケットフィルタリング)設定

SSHで外部から接続する前に、VPS事業者が提供するファイアウォール機能で、SSHのポート(22/tcp)が開放されていることを確認します。

  • 名称: 「ファイアウォール」「アクセスコントロール」「パケットフィルター」など、事業者によって名称は異なります。(Xserver VPSでは「パケットフィルター」)
  • 設定内容:
  • サービス/ポート: SSH または 22
  • プロトコル: TCP
  • 許可する送信元IP: まずは「全て許可」で設定し、SSH接続できることを確認します。後で、ご自身のIPアドレスに限定すると、さらに安全性が高まります。

ターミナルクライアントでの接続設定確認

任意のターミナルクライアントで接続を行います。(筆者が愛用しているのはRLoginです)

  • 名前解決できるようにしたホスト名
  • ユーザー名
  • 秘密鍵

を指定して、SSHログインできることを確認します。

SSHのパスワード認証を禁止

  • SSH設定ファイルバックアップ
sudo cp -pi /etc/ssh/sshd_config /path/to/backup/directory/sshd_config.$(date +%Y%m%d)

任意のバックアップディレクトリを指定します。(筆者の場合は/etc/conf_backup)

  • バックアップ確認
diff -u /path/to/backup/directory/sshd_config.$(date +%Y%m%d) /etc/ssh/sshd_config

エラーがない(差分がない)ことでバックアップを確認します。

  • ファイル書き換え
sudo sed -i -e 's/^#PasswordAuthentication yes/PasswordAuthentication no/' -e 's/^#PermitEmptyPasswords no/PermitEmptyPasswords no/' /etc/ssh/sshd_config
  • 差分確認
diff -u /path/to/backup/directory/sshd_config.$(date +%Y%m%d) /etc/ssh/sshd_config
  • 差分
-#PasswordAuthentication yes
-#PermitEmptyPasswords no
+PasswordAuthentication no
+PermitEmptyPasswords no
  • SSH再起動
sudo systemctl restart ssh.service 

SSH設定反映確認

  1. 新しくターミナルを起動します。
  2. パスワードでSSHログインできないことを確認します。
  3. 事前に転送しておいた秘密鍵でログインできることを確認します。

最初のアップデートとアップグレード

パッケージ全体のアップグレードを行います。

sudo apt update && sudo apt upgrade

アップグレード後、再起動を行います。

sudo reboot

ホスト名を設定する。

個人的に重要な作業です。「どういうサーバに育てていくか」はその名前にかかっているというのが持論です。

sudo hostnamectl set-hostname hoge.example.com

等として、自分のサーバを命名しましょう。

設定後、

uname -n

で、サーバ名を確認します。

この時、

sudo reboot

後、再起動後も名前が変わらないことを確認します。

プロンプト設定

最初期のプロンプトは

hoge@hoge$

になっているので、好みに沿って設定していきます。

  • 一般ユーザの.bashrc設定
cat << ___EOF___ | tee -a ~/.bashrc
PS1="[\u@\H \W]\\$ "

# 一般ユーザ向けのプロンプト設定
if [ "\$PS1" ]; then
  if [ "\$(id -u)" -eq 0 ]; then # rootユーザの場合
    PS1='\[\e[0;31m\][\u@\H \W]#\[\e[0m\] '
  else # 一般ユーザの場合
    PS1='\[\e[0;32m\][\u@\H \W]\$\[\e[0m\] '
  fi
fi
___EOF___
  • root

Ubuntu系は.bashrcが統一されないので、やむなくこの方法をとります。

sudo su -
cat << ___EOF___ | tee -a ~/.bashrc
PS1="[\u@\H \W]\\$ "

# 一般ユーザ向けのプロンプト設定
if [ "\$PS1" ]; then
  if [ "\$(id -u)" -eq 0 ]; then # rootユーザの場合
    PS1='\[\e[0;31m\][\u@\H \W]#\[\e[0m\] '
  else # 一般ユーザの場合
    PS1='\[\e[0;32m\][\u@\H \W]\$\[\e[0m\] '
  fi
fi
___EOF___

設定後、SSHセッションを開き直します。以下を確認します。

  1. 緑文字で[hoge\@hoge.example.com~]$のように表示される。(一般ユーザー)
  2. 赤文字で[root\@hoge.example.com~]#のように表示される。(root)

aptitudeインストール

これは完全に筆者の好みです。パッケージ管理をaptではなくaptitudeに変えます。

sudo apt install aptitude

Redmine_View_Customizeでチケットのステータスにラジオボタンを追加する

やりたいこと

Redmineのステータス一覧のドロップダウンリストにラジオボタンを追加し、ステータスの遷移を行いやすくします。

前提

  • Redmine View Customize がインストールされていること。
  • Redmine 5.1で動作を確認しています。

手順

画面移動

  1. Redmineに管理者権限でログインします。
  2. 管理>表示のカスタマイズに移動します。

カスタマイズ作成:JavaScript

表示のカスタマイズに移動後、「新しい表示のカスタマイズ」をクリックします。

以下の通りに入力します。

  • パスのパターン
  • /issues/[0-9]+
  • プロジェクトのパターン
  • 空白
  • 挿入位置
  • 全ページのヘッダ
  • 種別
  • JavaScript

コード

$(function() {
  const $select = $('#issue_status_id');
  if ($select.length === 0) return;

  const currentVal = $select.val();

  // ラジオボタンを入れるコンテナ
  const $radioContainer = $('<div class="status-radio-container"></div>');

  $select.find('option').each(function() {
    const val = $(this).val();
    const label = $(this).text();

    if (!val) return; // 空value(プレースホルダなど)はスキップ

    const id = 'status_radio_' + val;

    const $radio = $('<input type="radio">').attr({
      id,
      name: 'issue_status_radio',
      value: val
    });

    if (val === currentVal) {
      $radio.prop('checked', true);
    }

    const $label = $('<label>').attr('for', id).text(label);
    const $wrapper = $('<div class="radio-wrapper"></div>').append($radio, $label);

    $radioContainer.append($wrapper);
  });

  // ドロップダウンを非表示にし、ラジオボタンを挿入
  $select.hide().after($radioContainer);

  // ラジオ選択時に元のselectを更新
  $radioContainer.on('change', 'input[type=radio]', function() {
    $select.val($(this).val());
  });
});
  • コメント
  • 任意「チケットステータスにラジオボタンを追加する-JavaScript-」など
  • 有効
  • チェック
  • プライベート
  • チェックを外す

設定後、保存をクリックします。

カスタマイズ作成:CSS

表示のカスタマイズに移動後、「新しい表示のカスタマイズ」をクリックします。

以下の通りに入力します。

  • パスのパターン
  • /issues/[0-9]+
  • プロジェクトのパターン
  • 空白
  • 挿入位置
  • 全ページのヘッダ
  • 種別
  • CSS

コード

.status-radio-container {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  margin-top: 5px;
}

.radio-wrapper {
  display: flex;
  align-items: center;
  width: 220px; /* カラム幅は調整可能 */
}

.radio-wrapper label {
  margin-left: 6px;
  cursor: pointer;
}
  • コメント
  • 任意「チケットステータスにラジオボタンを追加する-CSS-」など
  • 有効
  • チェック
  • プライベート
  • チェックを外す

設定後、保存をクリックします。

動作を確認します。

任意のチケット編集画面をクリックします。

ステータス変更画面がドロップダウンリストからラジオボタンに変わっていれば成功です。

Google Geminiによるコード修正。(SSL証明書の有効期限確認)

このスクリプトの改善案をGoogle Geminiに言ったところ、更に完成度が上がりました。

概要

Web運用において、「サーバのSSL証明書更新」をチェックすることは大切です。

適切に更新されていない/更新が遅れたまま放置すると

  • ブラウザで「危険なサイト」と認識される
  • それによるレピュテーションリスク
  • HSTSを厳密に設定した場合はサイトそのものへのアクセス不可

など、リスクは甚大です。

そこで、

  • OpenSSLコマンドでドメインに設定されている証明書の期限
  • 並びに残り何日か

を表示するRubyスクリプトを準備しました。

スクリプト内容

  • ssl_checker.rb
#!/usr/bin/env ruby

require 'openssl'
require 'socket'
require 'date'
require 'uri'
require 'timeout'

# 色付け用の定数
COLOR_RED = "\e[31m"
COLOR_YELLOW = "\e[33m"
COLOR_GREEN = "\e[32m"
COLOR_RESET = "\e[0m"

# URLの最終的な到達先を取得するメソッド
def get_effective_url(url)
  # curlを使ってリダイレクトを追いかけ、最終的なURLを取得する
  # -s: サイレント, -L: リダイレクト追従, -I: ヘッダのみ, -o /dev/null: ボディ破棄, -w '%{url_effective}': 最終URLを出力
  effective_url = `curl -sLI -o /dev/null -w '%{url_effective}' "#{url}"`
  effective_url.empty? ? nil : effective_url
end

# 証明書の有効期限を取得するメソッド
def get_certificate_expiry_date(url)
  uri = URI.parse(url)
  hostname = uri.host
  port = uri.port || 443 # ポートがなければ443を使う
  ssl_socket = nil
  tcp_client = nil

  begin
    Timeout.timeout(5) do
      tcp_client = TCPSocket.new(hostname, port)
      ssl_context = OpenSSL::SSL::SSLContext.new
      ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_client, ssl_context)
      ssl_socket.hostname = hostname
      ssl_socket.connect

      cert = ssl_socket.peer_cert
      expiration_date = DateTime.parse(cert.not_after.to_s)
      days_remaining = (expiration_date - DateTime.now).to_i

      return expiration_date, days_remaining
    end
  rescue Timeout::Error
    return nil, "サーバーへの接続がタイムアウトしました。"
  rescue => e
    return nil, e.to_s
  ensure
    ssl_socket&.close
    tcp_client&.close
  end
end

# 結果を表示するメソッド
def print_result(url, expiration_date, days_remaining)
  if expiration_date
    formatted_date = expiration_date.strftime("%Y/%m/%d")
    
    # 残り日数に応じて色を選択
    color = if days_remaining < 14
              COLOR_RED
            elsif days_remaining < 30
              COLOR_YELLOW
            else
              COLOR_GREEN
            end

    puts "サイト #{url} の有効期限は #{formatted_date} です。#{color}残り #{days_remaining} 日です。#{COLOR_RESET}"
  else
    puts "#{COLOR_RED}サイト #{url} の証明書取得に失敗しました: #{days_remaining}#{COLOR_RESET}"
  end
end

# メイン処理
def main
  # コマンドライン引数があるかどうかで処理を分岐
  domains_to_check = if ARGV.empty?
                       # 引数がない場合は、対話式で入力を受け付ける
                       print "チェックしたいサイトのドメインを入力してください(例: example.com): "
                       [gets.chomp]
                     else
                       # 引数がある場合は、それらを全てチェック対象とする
                       ARGV
                     end

  # 各ドメインをチェック
  domains_to_check.each do |domain|
    # 対話モードで空エンターされた場合などをスキップ
    next if domain.nil? || domain.strip.empty?
    
    # http/httpsから始まらない場合はhttpsを付与
    initial_url = domain.start_with?('http') ? domain : "https://#{domain}"
    
    puts "Checking: #{initial_url} ..."
    final_url = get_effective_url(initial_url)

    if final_url.nil?
      puts "#{COLOR_RED}サイト #{initial_url} にアクセスできませんでした。#{COLOR_RESET}"
      next
    end
    
    expiration_date, days_remaining = get_certificate_expiry_date(final_url)
    print_result(final_url, expiration_date, days_remaining)
  end
end

# メイン処理を呼び出し
main

スクリプト実行例

ruby ssl_checker.rb

※Rubyで動かすためスクリプトに実行権は持たせる必要はありません

  1. 対話式でドメインを入力する
  2. 証明書の有効期限と残り期日を表示する
  3. ruby script.rb www.hoge.comなど、ドメインを引数にしても同様の効果が得られる
  4. 更新が近づくと
    • 30日以内:黄色
    • 15日以内:赤

とアラートも出してくれるようにしています。

  • 対話式
ruby ssl_checker.rb 
チェックしたいサイトのドメインを入力してください(例: example.com): www.yahoo.co.jp
Checking: https://www.yahoo.co.jp ...
サイト https://www.yahoo.co.jp/ の有効期限は 2026/05/14 です。残り 310 日です。
  • 引数にした場合
ruby ssl_checker.rb yahoo.co.jp www.msn.com
Checking: https://yahoo.co.jp ...
サイト https://www.yahoo.co.jp:443/ の有効期限は 2026/05/14 です。残り 310 日です。
Checking: https://www.msn.com ...
サイト https://www.msn.com/ の有効期限は 2025/10/05 です。残り 89 日です。

スクリプト使用例

筆者は/etc/update-motd配下に

ruby /path/to/script/ruby/ssl_checker.rb ryza.jp

と記入することで、ログインのたびに

Checking: https://atelier.reisalin.com ...
サイト https://atelier.reisalin.com/ の有効期限は 2025/08/15 です。残り 37 日です。

と次の更新のタイミングを読みやすくしています。

レポジトリを追加してのpassengerアップグレード。

概要

Redmineとの連携でmod_passangerを用いています。これのアップグレードメモです。

環境

  • Ubuntu 24.04
  • Apache 2.4
  • Ruby 3.2
  • mod_passenger 6.0.17 (アップグレード前)→6.0.27(アップグレード後)

バージョンアップの推奨メッセージ

var/log/apache2/error.logを確認したところ、

 [ E 2025-07-04 15:08:31.6489 116405/T5 age/Cor/SecurityUpdateChecker.h:521 ]: A security update is available for your version (6.0.17) of Phusion Passenger(R). We strongly recommend upgrading to version 6.0.27. 

と出たのでバージョンアップを行います。

  • バージョンアップ前確認
passenger-config --version

Phusion Passenger(R) 6.0.17

を確認。

対処1:aptitudeによるアップグレード → 更新されず

※筆者の好みでaptitudeを用いています。好みに応じてaptに変更してください。

sudo aptitude install passenger

を行いましたが、インストール・削除・更新されるパッケージがありません。と出たので、レポジトリの追加に伴うアップグレードを行いました。

対処2:レポジトリ追加後にaptitudeによるアップグレード → 更新OK

レポジトリ追加

  • 必要なツールのインストール

※導入済みであれば不要です。

sudo aptitude install dirmngr gnupg apt-transport-https ca-certificates curl
  • GPG鍵追加
curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null

これは、これから追加するリポジトリがPhusion社による本物であることを保証するための電子署名キーです。

  • Phusionのリポジトリ追加
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger $(lsb_release -sc) main > /etc/apt/sources.list.d/passenger.list'

改めてaptitudeによるアップグレード

  • パッケージ更新
sudo aptitude update
  • mod_passanger更新
sudo aptitude install passenger

一式を

今度はアップグレードされました。

設定反映

  • Webサービス再起動

Ubuntu24.04はneedrestartにより、サービス再起動が必要なパッケージ更新が走った後は再起動してくれますが、念のため

sudo systemctl restart apache2.service

を行います。

バージョンアップ確認

passenger-config --version

Phusion Passenger(R) 6.0.27

と、アップグレードされていました。

Page 2 of 21

Powered by WordPress & Theme by Anders Norén