カテゴリー: Linux Page 2 of 50

gitによるmod-securrity core rule setのアップデート。

概要

こちらの方法で導入したMod-Security(WAF)。

この防御ルールであるOWASP Core Rule Setの更新を行います。

環境

  • Ubuntu 24.04
  • Apache 2.4
    • バーチャルサイトで個別設定
    • aptでインストールしているため
    • 設定ファイルは/etc/apache2/sites-available配下の.confファイル
    • サービス実行ユーザはwww-data
  • Mod Security ver.2系

注意点

アップデートにより

  • 追加されたルール
  • 削除されたルール
  • 変更された挙動

などがあるため、今までと同じ作業をしていたのにWAFがブロックした(あるいは今までブロックされていたアクセスがスルーした)などは可能性としてあります。

なので、

  1. ModSecurityを検知モードにして作業を実施する
  2. しばらく様子を見て有効化に戻す

という作業を取ります。そのため、WAFの防御が一度無効化される時間が発生します。

環境や予算が許すなら、インターネットに公開された別環境で試してからの方が良いでしょう。

→ テストが済んでいる状態であれば、本番環境で「ModSecurityをオフにする」の作業は不要になります。

さっくりとした手順

  1. 【事前準備】ModSecurityを検知モードにします。
  2. 【事前準備】ルールセットディレクトリのバックアップを行います。
  3. gitで最新リリースを確認します。
  4. OWASP Core Rule Setのアップデートを行います。
  5. Webサービスの再起動でアップデートを反映させます。
  6. 【事後作業】ModSecurityを有効化します。

【事前準備】ModSecurityを検知モードにします。

  • ディレクトリ移動
cd /etc/apache2/sites-available && pwd
  • .confファイルのバックアップ
sudo cp -pi hoge.conf /path/to/backup/directory/hoge.conf.yyyymmdd
  1. 設定ファイル(.conf)は自分の環境に合わせます。
  2. 任意のバックアップディレクトリを指定します。
  • .confファイルのバックアップ確認
diff -u /path/to/backup/directory/hoge.conf.yyyymmdd hoge.conf

差分が無いことを確認します。

通常、筆者は$(date +%Y%m%d)変数を用いてバックアップを行いますが、「検知モードでの試験」は日をまたぐこともあるため、この形式にしています。

  • .confファイルの編集

hoge.confファイルを管理者権限で修正。

SecRuleEngine On

から

SecRuleEngine DetectionOnly

に変更し、保存します。

  • ファイル修正確認
diff -u /path/to/backup/directory/hoge.conf.$(date +%Y%m%d) hoge.conf

以下の差分を確認します。

- SecRuleEngine On
+ SecRuleEngine DetectionOnly
  • 設定ファイル構文確認
sudo apache2ctl configtest

Syntax OKを確認します。

  • Webサービス再起動前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service

※設定ファイルの修正のみのためreloadで十分ですが、念を入れてrestartにしています。(以下同じ)

  • Webサービス再起動後確認
systemctl status apache2.service

active(running)を確認します。

【事前準備】ルールセットディレクトリのバックアップを行います。

cd /usr/share/modsecurity-crs && pwd

これは、上記のリンク先で示した通り、ルールセットを/usr/share/modsecurity-crs/corerulesetに配置していた場合のディレクトリです。

必要に応じて自分の環境に合わせます。

  • ルールセットのディレクトリコピー
sudo cp -pir coreruleset /path/to/backup/directory/coreruleset.$(date +%Y%m%d)

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

  • ディレクトリコピー確認
ls -l /path/to/backup/directory/coreruleset.$(date +%Y%m%d)

ディレクトリ一式があることを確認します。

OWASP Core Rule Setのアップデート

  • ディレクトリ移動
cd /usr/share/modsecurity-crs/coreruleset && pwd
  • リモートリポジトリの確認
sudo git fetch origin
  • 最新バージョンとの差分確認
sudo git status

筆者環境で、以下のように表示されました。

ブランチ main

このブランチは 'origin/main' に比べて172コミット遅れています。fast-forwardすることができます。

  (use "git pull" to update your local branch)


Changes not staged for commit:

  (use "git add/rm <file>..." to update what will be committed)

  (use "git restore <file>..." to discard changes in working directory)

        deleted:    crs-setup.conf.example


no changes added to commit (use "git add" and/or "git commit -a") 

コミット内容が大幅に変わっているので、上述した「検知モードで様子見にする」が活きてきます。

  • gitによるアップデート
sudo git pull

これで、OWASP Core Rule Setが最新版に変更されました。

Webサービスの再起動でアップデートを反映させます。

  • Webサービス再起動前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service
  • Webサービス再起動後確認
systemctl status apache2.service

active(running)を確認します。

その後、既存のWebシステムに問題が無いかを確認します。

tail -f /var/log/hoge/hoge_error.log

等として、通常の作業を行い

  1. 既存のサービスに異常は無いか?
  2. 新たな偽陽性は発生していないか?

等を確認し、それに応じて新たな偽陽性の除外などを行っていきます。

【事後作業】ModSecurityを有効化します。

アップデートの影響で既存サービスに問題が無いことが判明したら、再びModSecurityを有効化します。この例では、バックアップから.confファイルを切り戻します。

  • バーチャルサイト(.conf)ファイルのディレクトリに移動
cd /etc/apache2/sites-available && pwd
  • バックアップから切り戻し
sudo cp -pi /path/to/backup/directory/hoge.conf.$(date +%Y%m%d) hoge.conf
  • Webサービス再起動前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service
  • Webサービス再起動後確認
systemctl status apache2.service

active(running)を確認します。

その後、既存のWebシステムに問題が無いかを確認します。

有効化前に既存.confファイルを修正した場合

新たに偽陽性を追加した、既存のファイルを削除した、またはそれに伴う設定変更を行ったことにより、バックアップ前と.confファイルが異なるケースはあります。

その場合は、.confファイルの

SecRuleEngine DetectionOnly

SecRuleEngine On

と修正した後で以下の作業を行います。

  • 設定ファイル構文確認
sudo apache2ctl configtest

Syntax OKを確認します。

  • Webサービス再起動前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service
  • Webサービス再起動後確認
systemctl status apache2.service

active(running)を確認します。

update-motdでのメモリ監視。

UbuntuのWebサーバで、スワップの使いすぎによる再起動の判断を行うためのスクリプトを仕込みました。

スクリプト内容

#!/bin/bash
#
# メモリとSWAPの使用量を表示し、閾値を超えた場合に再起動を促す
#

# --- 設定 ---
# 再起動を促す警告を表示する閾値
# 両方の条件を満たした場合に警告が表示されます
readonly MEM_THRESHOLD=75  # 実メモリ使用率 (%)
readonly SWAP_THRESHOLD=10 # SWAP使用率 (%)

# --- 処理 ---

# freeコマンドの出力を取得 (-m オプションでMB単位)
free_output=$(free -m)

# メモリ情報を抽出・計算 (GB単位に変換して保持)
read mem_total_gb mem_used_gb mem_percent <<< $(echo "$free_output" | awk '
/^Mem:/ {
    total=$2;
    used=$3;
    if (total > 0) {
        percent=(used/total)*100;
    } else {
        percent=0;
    }
    printf "%.1f %.1f %.0f", total/1024, used/1024, percent;
}')

# SWAP情報を抽出・計算 (GB単位に変換して保持)
# SWAP領域が存在しない場合も考慮
if echo "$free_output" | grep -q '^Swap:'; then
    has_swap=true
    read swap_total_gb swap_used_gb swap_percent <<< $(echo "$free_output" | awk '
    /^Swap:/ {
        total=$2;
        used=$3;
        if (total > 0) {
            percent=(used/total)*100;
        } else {
            percent=0;
        }
        printf "%.1f %.1f %.0f", total/1024, used/1024, percent;
    }')
else
    has_swap=false
    swap_total_gb=0
    swap_used_gb=0
    swap_percent=0
fi


# --- 表示 ---

echo ""
# メモリとSWAPの使用率を整形して表示
# printfのフォーマットで表示幅を揃え、見やすくしています
printf "メモリ: %5.1f GB 中 %5.1f GB 使用 (%d%%)\n" "$mem_total_gb" "$mem_used_gb" "$mem_percent"

# SWAPの合計が0より大きい場合のみ表示
if (( $(echo "$swap_total_gb > 0" | bc -l) )); then
    printf "SWAP  : %5.1f GB 中 %5.1f GB 使用 (%d%%)\n" "$swap_total_gb" "$swap_used_gb" "$swap_percent"
fi

# 閾値を超えているかチェックし、条件を満たせば警告を表示
if [ "$has_swap" = true ] && [ "$mem_percent" -ge "$MEM_THRESHOLD" ] && [ "$swap_percent" -ge "$SWAP_THRESHOLD" ]; then
    echo ""
    echo "############################################################"
    echo "#  メモリ量の枯渇                                            #"
    echo "#  パフォーマンス低下を避けるため、再起動を検討してください。#"
    echo "############################################################"
fi

このスクリプトを

sudo chmod +x 

`/etc/update-motd.d/50-memory-check`

として仕込みます。

起動時にメモリ量やスワップ量を検査。

警告が出れば、再起動の検討やプロセスの見直しなどを行うことができます。

Redmine5.1.4→Redmine5.1.8へのアップデート手順。

公開用Redmine

https://atelier.reisalin.com

のバージョンを5.1.4→5.1.8にアップデートしたときのメモです。

環境

  • Ubuntu 24.04
  • 動かしていたRedmine:5.1.4
  • アップデートしたRedmie:5.1.8
  • Apache 2.4 / mod-passangerでRubyアプリを使用(Ruby 3.2系)
  • MySQL 8.0.3

作業に備えての前提

  • Webサービスを止めるため、ユーザアクセスができない状況が発生します。
  • 利害関係者への事前周知・作業時間の確保は十分に行ってください。(慣れれば20分程度で完了しますが、1時間は取っておいた方が無難です)
  • また、筆者環境はfiles配下をクラウドストレージにマウントしています。手順は自身の環境に合わせてください。

さっくりとはいかない手順

  1. (強く推奨)システム全体のバックアップ
  2. DBのバックアップ
  3. redmineのディレクトリを一度mvでリネームしてバックアップ。
  4. apache停止
  5. ディレクトリを再作成し、新しい空のRedmineを作る。
  6. themesとpluginを再配置。filesのシンボリックリンクを貼り替える。
  7. themesとpluginを再配置した状態でDBマイグレーション。
  8. apache再開
  9. バージョンアップ確認

システム全体のバックアップ(スナップショット)

  • AWS
  • 仮想サーバ

などで動かしている場合は、この段階でシステム全体のバックアップ(スナップショット)を取ることを強く推奨します。

mysqlによるDBバックアップ

  • バックアップディレクトリに移動
cd /hoge && pwd

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

  • mysqldump
mysqldump -h localhost -u redmine -p --no-tablespaces --single-transaction redmine > redmine_backup.$(date +%Y%m%d).sql

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

  • mysqldump確認
view redmine_backup.$(date +%Y%m%d).sql

DBが平文で読めることを確認します。

データ退避

  • ディレクトリ移動
cd /var/lib && pwd

Redmineが格納されているディレクトリの親ディレクトリに移動します。(筆者環境は/home/www-data)

  • Redmine全体ディレクトリ確認
ls -ld redmine

退避対象のディレクトリがあることを確認します。ディレクトリ名は自分の環境に合わせます。

  • Redmine待避
sudo mv redmine redmine_$(date +%Y%m%d)
  • Redmine待避確認
ls -ld redmine_$(date +%Y%m%d)

ディレクトリがあることを確認します。

apache停止

念のため、apacheを停止します。

  • apache停止前確認
systemctl status apache2.service

active(running)を確認します。

  • apache停止
sudo systemctl stop apache2.service
  • apache停止確認
systemctl status apache2.service

inactive(dead)を確認します。

Redmineプログラムの配置

  • Redmineのディレクトリ作成
sudo mkdir /var/lib/redmine
  • Redmineディレクトリの権限変更
sudo chown -R www-data:www-data /var/lib/redmine
  • Redmineディレクトリの作成確認
ls -ld redmine

ディレクトリがあることと、所有者がwww-dataであることを確認します。

  • ソースダウンロード
sudo -u www-data svn co https://svn.redmine.org/redmine/branches/5.1-stable /var/lib/redmine

5.1系の最新安定版をダウンロードします。

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

  • database.ymlコピー
sudo -u www-data cp -pi /var/lib/redmine_$(date +%Y%m%d)/config/database.yml /var/lib/redmine/config/database.yml
  • database.ymlコピー確認 
cat /var/lib/redmine/config/database.yml

待避したファイルの内容であることを確認します。

  • configuration.yml コピー
sudo -u www-data cp -pi /var/lib/redmine_$(date +%Y%m%d)/config/configuration.yml /var/lib/redmine/config/configuration.yml
  • configuration.ymlコピー確認
cat /var/lib/redmine/config/configuration.yml

待避したファイルの内容であることを確認します。

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

  • プラグイン一式のコピー
sudo -u www-data cp -pir  /var/lib/redmine_$(date +%Y%m%d)/plugins/* /var/lib/redmine/plugins/

移行元・移行先は自分の環境に合わせます。

  • テーマ一式のコピー
sudo -u www-data cp -pir /var/lib/redmine_$(date +%Y%m%d)/public/themes/* /var/lib/redmine/public/themes/

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

これは筆者の環境がlogディレクトリとfilesディレクトリを別の場所(wasabiクラウドストレージ)にリンクを張っているための措置です。
それ以外の場合は上述した /var/lib/redmine_$(date +%Y%m%d)からfilesやlogをコピーして下さい。

  • Redmineルートディレクトリに移動
cd /var/lib/redmine && pwd

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

  • filesディレクトリ削除
sudo rm -rf files
  • ログディレクトリ削除
sudo rm -rf log
  • filesディレクトリにシンボリックリンクを張る
sudo ln -sf /mnt/wasabi/redmine/files files

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

  • filesシンボリックリンクの所有者変更
sudo chown -h www-data:www-data files
  • filesシンボリックリンク確認
ls -l files
  1. filesがシンボリックリンクになっていること
  2. 所有者がwww-dataであること

を確認します。

  • logディレクトリにシンボリックリンクを張る
sudo ln -sf /var/log/redmine log
  • logシンボリックリンクの所有者変更
sudo chown -h www-data:www-data log
  • logシンボリックリンク確認
ls -l log
  1. logがシンボリックリンクになっていること
  2. 所有者がwww-dataであること

を確認します。

DBマイグレーション

  • Redmineルートディレクトリに移動
cd /var/lib/redmine

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

  • bundle インストール
sudo -u www-data bundle install --without development test --path vendor/bundle
  • シークレットトークン発行
sudo -u www-data bundle exec rake generate_secret_token
  • DBマイグレーション(本体)
sudo -u www-data RAILS_ENV=production bundle exec rake db:migrate
  • DBマイグレーション(プラグイン)
sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production
  • キャッシュクリア
sudo -u www-data RAILS_ENV=production bundle exec rake tmp:cache:clear
  • セッションクリア
sudo -u www-data RAILS_ENV=production bundle exec rake tmp:sessions:clear

apache再起動

  • apache再起動前確認
systemctl status apache2.service

inactive(dead)を確認します。

  • apache再起動
sudo systemctl start apache2.service
  • apache再起動確認
systemctl status apache2.service

active(running)を確認します。

動作確認

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

  • テーマ
  • 添付ファイル
  • プラグイン
  • チケット一覧

などが有効に動いていて、正常に稼働します。

バージョンアップ後の作業

  • 待避したファイルの削除/バックアップ

/var/lib/redmine_$(date +%Y%m%d)一式を削除、または任意の方法でバックアップします。

トラブルシューティング

bundle install が終わらない

Installing... の表示で止まっているように見えても、実際にはCPUを消費して動作していることがある(ネイティブ拡張機能のコンパイル)。topコマンドでcc1plusなどのプロセスが動いていないか確認する。

"Something went wrong" エラー

Redmineのアプリケーション起動エラー。原因はログに記録されている。

  1. まず /var/lib/redmine/log/production.log を確認する。
  2. 上記にログがなければ、/var/log/apache2/error.log を確認する。

ログから見る主な原因の例

  • プラグインの非互換: Redmine本体の機能とプラグインが競合している場合がある (Overwriting existing method 警告など)。
  • gemのバージョン競合: Ruby本体に付属のgemと、プラグインが要求するgemのバージョンが異なると起動に失敗することがある (base64の競合など)。この場合は、Gemfileでバージョンを明示的に指定するなどの対策が必要。

Redmineにfavicon(サイトアイコン)を設定。

概要

こちらのように、サイトアイコン(favicon)をRedmineに設定するメモです。

環境

  • Ubuntu 24.04
  • Redmine 5.1
  • Apache 2.4
    • サービス実行ユーザはデフォルトのwww-data

で実施しています。(Redmine 6.xはディレクトリ構造が異なります)

準備

  1. ファイルfavicon.pngfavicon.icoを用意します。
  2. このファイルをRedmineサーバに転送します。
  3. ファイルの所有者をRedmine実行ユーザに変更します。sudo chown www-data:www-data favicon.png など

手順

faviconファイルの配置

  • faviconディレクトリの作成
cd /path/to/redmine/root/directory/public/theme/theme_name && pwd

ルートディレクトリやテーマディレクトリは自分の環境に合わせます。 (筆者環境/home/www-data/redmine/public/themes/redmine_theme_kodomo)

sudo -u www-data mkdir favicon && cd favicon && pwd

faviconディレクトリにいることを確認します。

  • 転送したファイルの配置
sudo -u cp -pi /hoge/favicon.png ./

上記、転送した際のディレクトリを指定します。

Redmineサイトの設定

  1. Redmineのサイトに管理者権限でログインします。
  2. 管理>設定>表示に移動します。
    3.「Gravatarのアイコンを使用する」にチェックを入れて保存します。

この後、ブラウザをリロードしてアイコンが変わっていることを確認できれば設定完了です。

アクセスログを圧迫するクローラーへの対処。(Apache 2.4と外部ファイル連携によるクローラーのアクセス遮断とログ軽減)

はじめに

Webサイトを外部に公開していると、非常に厄介なクローラーがアクセスログに蓄積。これらは

  • 超高速
  • 超高頻度

で行われるため、本当に必要なアクセスログ(どの検索サイトから来たか、攻撃の兆候となる不審な点はないか)がつかみにくくなっています。

これを解決するため、以下の措置を執りました。

  1. クローラーや悪質なボットのアクセス拒否
  2. それらをアクセスログにすら残さず、きちんとしたアクセスログを追いやすくする

(※こちらの記事を更に強力に推し進めたものです)

環境

  • Ubuntu 24.04
  • Apache 2.4
    • setenvifモジュール
    • authz_core モジュール
    • (特段の理由がない限り、上記2つは標準で組み込まれていることが多いです。)
    • ない場合はsudo a2enmod setenvif等とした後、sudo systemctl restart apache2.serviceとしてモジュールを組み込みます。
  • また、バーチャルサイトによる複数ドメインにも対応しています。

さっくりとした手順

  1. クローラーのリストファイルを作成します。
  2. Apacheバーチャルサイトの.confファイルを修正します。
  3. 設定を反映後、状況を確認します。

クローラーのリストファイルを作成

  • /etc/apache2/sites-enabled/il-vento-d-oro.txt

としてファイルを作成。(ファイル名や格納場所は自分の環境に合わせてください)

SetEnvIfNoCase User-Agent "facebookexternalhit/1\.1" bad_bot dontlog
SetEnvIfNoCase User-Agent "SemrushBot/7~bl" bad_bot dontlog
SetEnvIfNoCase User-Agent "AhrefsBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "MJ12bot" bad_bot dontlog
SetEnvIfNoCase User-Agent "DotBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "Baiduspider" bad_bot dontlog
SetEnvIfNoCase User-Agent "YandexBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "Sogou web spider" bad_bot dontlog
SetEnvIfNoCase User-Agent "Exabot" bad_bot dontlog
SetEnvIfNoCase User-Agent "MegaIndex\.ru" bad_bot dontlog
SetEnvIfNoCase User-Agent "SeznamBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "BLEXBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "Bytespider" bad_bot dontlog
SetEnvIfNoCase User-Agent "DataForSeoBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "serpstatbot" bad_bot dontlog
SetEnvIfNoCase User-Agent "SeekportBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "index\.community crawler" bad_bot dontlog
SetEnvIfNoCase User-Agent "PetalBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "BacklinksExtendedBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "meta-externalagent/1\.1" bad_bot dontlog
SetEnvIfNoCase User-Agent "ICC-Crawler" bad_bot dontlog
SetEnvIfNoCase User-Agent "bingbot" bad_bot dontlog
SetEnvIfNoCase User-Agent "msnbot" bad_bot dontlog
SetEnvIfNoCase User-Agent "Applebot" bad_bot dontlog
SetEnvIfNoCase User-Agent "DuckDuckBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "Majestic-SEO" bad_bot dontlog
SetEnvIfNoCase User-Agent "cognitiveSEO" bad_bot dontlog
SetEnvIfNoCase User-Agent "archive\.org_bot" bad_bot dontlog
SetEnvIfNoCase User-Agent "CCBot" bad_bot dontlog
SetEnvIfNoCase User-Agent "^$" bad_bot dontlog
SetEnvIfNoCase User-Agent "Custom-AsyncHttpClient" bad_bot dontlog
SetEnvIfNoCase User-Agent "ImagesiftBot" bad_bot dontlog

上記は、サイトを運営していく中で

  • robots.txtを無視し
  • あらゆるページにアクセスし
  • 下手をすれば帯域を阻害する

ものを集めています。"^$"は、エージェントを偽装するスクレイピングへの措置です。

この、

  • SetEnvIfNoCase User-Agent "エージェント名"
  • bad_bot
  • dontlog

と、続けて書くことで、厄介なボットへの対処とアクセスログへの無視を決めます。

もちろん、これらのbotが必要というのであれば省いていきます。

apacheの設定ファイルを編集

  • 設定ファイルのバックアップ
sudo cp -pi /etc/apache2/sites-available/hoge.conf /path/to/backup/directory/hoge.conf.$(date +%Y%m%d)

設定ファイルは自分の環境に合わせます。
任意のバックアップディレクトリを指定します。

  • diffによるバックアップ確認
diff -u /path/to/backup/directory/hoge.conf.$(date +%Y%m%d) etc/apache2/sites-available/hoge.conf

差分(エラー)が無いことを確認します。

  • ファイルの修正

以下のように修正していきます。(要管理者権限)

例)

<VirtualHost *:443>
    # ServerName、ErrorLogは自分の環境に合わせます
    ServerName hoge.example.com
    ErrorLog /var/log/apache2/hoge/error.log
    # 1)Robots.txtをすり抜ける悪質なbotのリスト(先ほど作成したリストファイルのパスをフルパスで指定) 
    Include /etc/apache2/sites-enabled/il-vento-d-oro.txt
    # dontlogを付与したエージェントはアクセスログに記録させません
    # CustomLogは自分の環境に合わせます
    CustomLog /var/log/apache2/hoge/access.log combined env=!dontlog

# DocumentRootは自分の環境に合わせます。
DocumentRoot /var/www/html/hoge

# Directoryディレクティブは自分の環境に合わせます。
    <Directory /var/www/html/hoge>
        Options -MultiViews
        AllowOverride All
     <RequireAll>
      # 上記リストに従い、"bad_bot"変数がセットされているクローラーのアクセスを拒否します
      Require not env bad_bot
      # それ以外は許可
      Require all granted
     </RequireAll>
    </Directory>

# Require notでForbiddenにすると、クローラーは「拒否されただけで本体はある」と判断し、Webアクセスを繰り返すパターンがあるため、403に404を返す設定を付け加えます
# Directory
ErrorDocument 403 "Not Found"
  • 差分確認
diff -u /path/to/backup/directory/hoge.conf.$(date +%Y%m%d) etc/apache2/sites-available/hoge.conf
  • 上記、加えた設定が+になっていること
  • ディレクティブの重複や閉じ忘れがないこと

を改めて確認します。

設定反映と確認

  • 別のセッションでアクセスログを確認
tail -f /var/log/apache2/hoge/access.log

※この段階ではクローラーからのアクセスが多々来ています

  • 構文確認
sudo apache2ctl configtest

Syntax Okを確認します

  • Apache再起動前確認
systemctl status apache2.service

active(running)を確認します

  • Apache再起動
sudo systemctl restart apache2.service
  • Apache再起動後確認
systemctl status apache2.service

active(running)を確認します

この段階で、上記、

tail -f /var/log/apache2/hoge/access.log

が止まっていれば設定は成功です。

  • 今までと同じようにアクセスができること
  • 既存のWebサイトに異常が無いこと
  • その場合のアクセスログが表示されること

を確認し、作業は成功です。

作業を切り戻す場合

何か不具合が起きた場合は、バックアップしていた.confを切り戻します。

  • 差分確認
sudo cp -pi /path/to/backup/directory/hoge.conf.$(date +%Y%m%d) etc/apache2/sites-available/hoge.conf

作業時に指定したバックアップディレクトリです。

  • 差分確認
diff -u /path/to/backup/directory/hoge.conf.$(date +%Y%m%d) etc/apache2/sites-available/hoge.conf

差分が ない ことを確認します。

  • 構文確認
sudo apache2ctl configtest

Syntax Okを確認します

  • Apache再起動前確認
systemctl status apache2.service

active(running)を確認します

  • Apache再起動
sudo systemctl restart apache2.service
  • Apache再起動後確認
systemctl status apache2.service

active(running)を確認します

設定前になっていることを確認します。

Nextcloud、アップロードしたファイルを一定期間保持後に削除する方法。

ファイルサーバとしても使えるNextcloud。

しかし、サーバの容量によっては無制限にファイルを増やせるわけではありません。

今回、個人用に外部環境に構築したNextcloudは

「Talk機能によるスマートフォンからの高速メモ」

という尖った運用を行うために、ファイルサーバの利用は限定的として

  • アップロードしたファイルは猶予期間を設ける
  • 猶予期間を過ぎたら問答無用でファイルを削除する

設定を行いました。

環境

  • Ubuntu 24.04
  • Nextcloud 31.0.5
  • Apache 2.4
  • MySQL 8.3
  • PHP 8.3

構築については以下の通りです。

https://barrel.reisalin.com/books/nextcloud/page/ubuntu-2404nextcloud

準備

以下のプラグイン(アプリ)をそれぞれインストールします。Nextcloud 31.0.5で動くことを確認しています。

手順

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

付与するタグを作成します。

管理者設定>基本設定に進みます。

「タグの作成または編集」の項目があるので、

  • コラボレーションタグ
  • タグの名前:任意(30日で消去など、分かりやすい名前にします)
  • タグのレベル:不可視

にして、「作成」をクリックします。

ファイルアップロード時にタグを付与するようにします。

管理者設定>Flowに進みます。

上の方にある緑のボタン「自動タグ付け」の「新しいフローを追加」をクリックします。

以下のように設定します。

  • いつ
  • ファイルが変更されています(これは変更不可)
  • かつ
  • 「ファイルシステムタグ」
  • 「に次のタグがついていない」
  • 先ほど設定したタグ(30日で消去)

設定後、作成→アクティブ化。

一定期間が過ぎたらファイルが消去されるように設定します。

管理者設定>Flowの

「ファイル保持と自動削除」で以下のように設定します。

  • タグを選択
  • 先ほど設定した「30日で消去」を選択。
  • 保持期間(時間単位)
    • 30日
  • いつから
    • 作成日から

として作成。

タグ付け確認

Nextcloudのファイルアップロードで、任意のファイルをアップロードします。(要管理者権限)

ファイルの項目に、自動的に「30日で消去」が付与されていたら設定は完了です。

Nextcloudインストール時のロケールエラーに対処

エラー内容

Nextcloudインストール中、Webでのセットアップ時、

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

にアクセスすると

ロケールを en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8 に設定できませんでした
これらのロケールのうちいずれかをシステムにインストールし、Webサーバーを再起動してください。

というエラーが出たので、これに対処します。

環境

  • Ubuntu 24.04
  • Apache 2.4
  • MySQL 8
  • Nextcloud 31.0.4

プログラムを配置し、Apacheのバーチャルサイトに記した直後の出来事です。

手順

ファイルのバックアップを行います。

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

自分の環境に合わせ、任意のバックアップディレクトリを指定します。

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

差分が無いことを確認します。

設定ファイルの編集を行います。

以下の差分になるように管理者権限で /etc/apache2/envvars ファイルを修正します。

  • 差分
@@ -23,7 +23,9 @@
 export APACHE_LOG_DIR=/var/log/apache2$SUFFIX

 ## The locale used by some modules like mod_dav
-export LANG=C
+#export LANG=C
+export LANG=ja_JP.UTF-8
+export LC_ALL=ja_JP.UTF-8
 ## Uncomment the following line to use the system default locale instead:
 #. /etc/default/locale
  • 差分確認
diff -u /path/to/backup/directory/envars.$(date +%Y%m%d)  /etc/apache2/envvars

で、上記の差分になっていればOKです。日本語環境以外に合わせたい方は、それに従ってください。

設定の反映を確認します。

  • 設定ファイルのコンフィグ確認
sudo apache2ctl configtest

Syntax OKを確認します

  • Apache再起動
sudo systemctl restart apache2.service

再びNextcloudの

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

にアクセスし、エラーがなくセットアップ画面が出てくればOKです。

Redmine Knowledgebase プラグイン (v5.0.0) on Redmine 5.1 (Ruby 3.2+, Rails 6.1+) インストール・マイグレーション手順

自分にとってのキラープラグインと言えるRedmine Knowledgebase。

これをRedmine 5.1に導入する際に恐ろしくハマったので、解決したときのメモです。

なお、本件の解決にはGoogle Gemini Advanced(2.5 Pro preview)の助けが必要でした。

環境

  • Ubuntu 24.04
  • Redmine 5.1.x
  • Apache 2.4で稼働
  • Ruby 3.2.x (本手順は Ruby 3.2.3 で確認)
  • Rails 6.1.x (本手順は Rails 6.1.7.10 で確認)
  • データベース: MySQL 8.0 (他のデータベースでも同様の問題が発生する可能性があります)
  • プラグインソース: alexbevi/redmine_knowledgebase

盛大にハマった結果で得た手順

  1. DBのバックアップを取得します。
  2. プラグインのインストールを行います。
  3. マイグレーションエラーに対応します。
  4. マイグレーションの成功を確認します。
  5. Redmine(Webサービス)を再起動します。
  6. プラグインのインストールと動作確認を行います。

バックアップを取得します。

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

任意のバックアップディレクトリに移動します

  • mysqldumpによるバックアップ
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ユーザのものです。

環境が許すなら、VPSのスナップショットのようにシステム全体のバックアップを取ることを強く推奨します。

プラグインのインストール

  • Redmineのプラグインディレクトリに移動
cd /path/to/redmine/root/directory/plugins && pwd

筆者環境/home/www-data/redmine/plugins

  • git clone
sudo -u www-data git clone https://github.com/alexbevi/redmine_knowledgebase

Redmineの実行ユーザでgit cloneとした方が、後にsudo chownする手間が省けます。

  • clone確認
ls -l redmine_knowledgebase

ファイル一式があることと、ファイル群の所有者がwww-data(Redmineの実行ユーザ)であることを確認します。

  • Redmineのルートディレクトリに戻ります。
cd /path/to/redmine/root/directory/plugins && pwd

筆者環境/home/www-data/redmine/

  • (必要に応じて)依存関係をインストールします。
sudo -u www-data bundle install

初回マイグレーション実行 (エラー発生との対処)

以下のコマンドでプラグインのマイグレーションを実行します。このとき、壮大にハマったので、AIの力を借りて(というよりもほぼその指示に従って)解決しました。

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

マイグレーションエラーの修正

エラーが発生した場合は、以下の手順で関連ファイルを修正し、その都度上記 redmine:plugins:migrate コマンドを再実行してください。

修正箇所1: 20121205100143_add_versioning.rb ファイルの対応

このマイグレーションでは、以下の2つのエラーが連続して発生する可能性があります。

  • Mysql2::Error: Duplicate column name 'version_comments' (in kb_articles table)
  • ArgumentError: wrong number of arguments (given 2, expected 1) (in KbArticle.create_versioned_table 内部の create_table 呼び出し)

対象ファイルA: plugins/redmine_knowledgebase/db/migrate/20121205100143_add_versioning.rb

以下に従って修正していきます。

  • 修正前の class AddVersioning ... end の内容(主要部分):
  class AddVersioning < ActiveRecord::Migration
    def self.up
      KbArticle.create_versioned_table
      add_column :kb_articles, :version_comments, :string, :limit => 255, :default => ""
    end

    def self.down
      remove_column :kb_articles, :version_comments
      KbArticle.drop_versioned_table
    end
  end
  • 修正後の class AddVersioning ... end の内容:
  class AddVersioning < ActiveRecord::Migration[6.1] # Rails 6.1 互換にする
    def self.up
      # kb_article_versions テーブルが存在しない場合のみ作成
      unless ActiveRecord::Base.connection.table_exists?(:kb_article_versions)
        if defined?(KbArticle) && KbArticle.respond_to?(:create_versioned_table)
          KbArticle.create_versioned_table # この呼び出しは次の acts/versioned.rb の修正が必要
        else
          # このエラーは通常発生しないはずだが、念のため
          raise "Cannot create kb_article_versions: KbArticle model or create_versioned_table method is not available."
        end
      end

      # kb_articles テーブルに version_comments カラムが存在しない場合のみ追加
      unless column_exists?(:kb_articles, :version_comments)
        add_column :kb_articles, :version_comments, :string, :limit => 255, :default => ""
      end
    end

    def self.down
      if column_exists?(:kb_articles, :version_comments)
        remove_column :kb_articles, :version_comments
      end
      if ActiveRecord::Base.connection.table_exists?(:kb_article_versions)
        if defined?(KbArticle) && KbArticle.respond_to?(:drop_versioned_table)
          KbArticle.drop_versioned_table
        end
      end
    end
  end

対象ファイルB: plugins/redmine_knowledgebase/lib/active_record/acts/versioned.rb

KbArticle.create_versioned_table が内部で呼び出す create_tableArgumentError が発生します。このファイルを修正します。

  • 修正対象箇所 (ファイル内の create_versioned_table メソッドの中、通常503行目あたり):
  # 修正前
            self.connection.create_table(versioned_table_name, create_table_options) do |t|

Ruby

  # 修正後 (create_table_options の前に ** を追加)
            self.connection.create_table(versioned_table_name, **create_table_options) do |t|

上記AとBの両ファイルを修正後、再度以下を実行しましたが、エラーが発生しました。

sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production --trace
修正箇所2: 20150326093122_add_taggings_counter_cache_to_tags.rb ファイルの対応

次のエラーとして NameError: uninitialized constant ...::RedmineCrm が発生する可能性があります。

対象ファイル: plugins/redmine_knowledgebase/db/migrate/20150326093122_add_taggings_counter_cache_to_tags.rb

  • 修正前の class AddTaggingsCounterCacheToTags ... end の内容(主要部分):
  class AddTaggingsCounterCacheToTags < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] # 古い形式
    def self.up
      RedmineCrm::Tag.reset_column_information
      # ... (RedmineCrm::Tag を参照するコードが続く) ...
    end
    def self.down
      # ... (関連する可能性のある remove_column など) ...
    end
  end
  • 修正後の class AddTaggingsCounterCacheToTags ... end の内容:

(Redmine Crmプラグインを使用していない場合、関連処理をスキップします)

  class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[6.1] # Rails 6.1 互換にする
    def self.up
      puts "INFO: Skipping 'up' method in 20150326093122_add_taggings_counter_cache_to_tags.rb due to missing RedmineCrm module or intentional skip."
      # 元の RedmineCrm::Tag に関連する処理は全てコメントアウトまたは削除
    end

    def self.down
      puts "INFO: Skipping 'down' method in 20150326093122_add_taggings_counter_cache_to_tags.rb."
      # 元の remove_column 処理なども、up で対応する処理を行わないためコメントアウトまたは削除
    end
  end

上記ファイルを修正後、更に以下を実行します。

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

これらの手順で、ようやく、

  • コンソールにエラーメッセージが出ないこと
  • db:schema:dumpがログに出力されること

を確認しました。

マイグレーション完了の確認

念のため、

mysql -u root -p

としてMySQLコンソールにログイン。

USE DATABASE redmine;

(自分が使っているRedmineのDBを指定します)

  • kb_article_versionsテーブルの確認
SHOW TABLES LIKE 'kb_article_versions';
DESCRIBE kb_article_versions;
DESCRIBE kb_articles;

それぞれ、テーブルが作成されていること、kb_articles テーブルに version_comments カラムが存在すること、および content カラムの型が変更されていること(ChangeColumnArticleToLongText マイグレーションによる)を確認します。

Redmineの再起動

ここではWebサービス(Apache)の再起動を前提とします。

  • 稼働前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service
  • 稼働後確認
systemctl status apache2.service

active(running)を確認します。

プラグインの動作確認

Redmineにログインし、ナレッジベースプラグインの各機能

  • 記事の作成
  • 編集
  • 表示
  • バージョン管理
  • ファイル添付

などが正常に動作するか確認してください。

注意点:

  • 上記の手順は、特定のバージョンの組み合わせで発生した問題への対処法です。プラグインやRedmineのバージョンが異なる場合は、別の問題が発生したり、異なる修正が必要になる場合があります。
  • 途中でマイグレーションが認識されなくなるなどの不可解な問題が発生した場合は、一度プラグインディレクトリを削除し、データベースをリストア(または関連テーブルを手動削除)、再度GitHubからクリーンにクローンし直してから上記手順を開始すると、問題が解消されることがあります。

おまけ:切り戻し手順

この手順で成功したとはいえ、失敗はつきものです。そのため、以下に切り戻し手順を記します。

通常の切り戻し

ディレクトリ移動

  • Redmineのルートディレクトリに戻ります。
cd /path/to/redmine/root/directory/plugins && pwd

筆者環境/home/www-data/redmine/

プラグインアンインストール

sudo -u www-data bundle exec rake redmine:plugins:migrate NAME=redmine_knowledgebase VERSION=0 RAILS_ENV=production

ディレクトリ削除

sudo rm plugins/redmine_knowledgebase -Rf

Webサービス再起動

  • 稼働前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service
  • 稼働後確認
systemctl status apache2.service

active(running)を確認します。

それでもダメだった切り戻し(DBリストア)

  • DBをバックアップしたディレクトリに移動
cd /hoge && pwd
  • DBリストア
mysql -h localhost -u redmine -p redmine < redmine_backup.$(date +%Y%m%d).sql

パスワードはredmineインストール時に設定したDBユーザのものです

  • 稼働前確認
systemctl status apache2.service

active(running)を確認します。

  • Webサービス再起動
sudo systemctl restart apache2.service
  • 稼働後確認
systemctl status apache2.service

active(running)を確認します。

再起動後、復旧しているかを確認します。

Let’s Encrypt仕様変更によるSSL Staplingの無効化

新たなSSL証明書を導入したサーバにて、以下のエラーを確認。こちらの解決のメモです。

前提

  • Ubuntu 24.04
  • Apache 2.4
  • Let's Encryptによるワイルドカード証明書を発行

エラー内容

サイトのエラーログに以下を発見しました。

[Thu May 22 14:03:51.270340 2025] [ssl:error] [pid 929:tid 929] AH02218: ssl_stapling_init_cert: no OCSP URI in certificate and no SSLStaplingForceURL set [subject: CN=*.ryza.jp / issuer: CN=E6,O=Let's Encrypt,C=US / serial: 058A8F3B6C32F08B41E5E56BEAD92451D34A / notbefore: May 21 12:08:57 2025 GMT / notafter: Aug 19 12:08:56 2025 GMT]
[Thu May 22 14:03:51.270358 2025] [ssl:error] [pid 929:tid 929] AH02604: Unable to configure certificate atelier.ryza.jp:443:0 for stapling 
  • 意味:
  • ApacheがSSL証明書 (CN=*.ryza.jp) のOCSP Staplingを初期化しようとしましたが、証明書内にOCSPレスポンダのURI(OCSP URI)が見つかりませんでした。また、Apacheの設定で SSLStaplingForceURL も指定されていません。
  • OCSP Staplingとは:
  • SSL証明書の失効状態を効率的に確認するための仕組みです。ウェブサーバーが事前にCA(認証局)に問い合わせて証明書の有効性を確認し、その応答(OCSPレスポンス)を証明書と一緒にクライアントに提供することで、クライアント側の確認負荷を軽減し、表示速度を向上させます。

なお、Apacheの.confファイルには以下の項目があります。

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

つまり、ApacheでSSL Stapling設定されているにもかかわらず、OCSPレスポンスが働いていないことを意味します。

状況確認

現行の証明書の状況

openssl x509 -in /path/to/your/certificate.pem -noout -ocsp_uri

結果は何もなし。証明書内にこれがないことで、先のエラーが発生したようです。

過去にLet's Encryptで発行した証明書の状況

2024年9月に発行したLet's Encryptの証明書で

openssl x509 -in /path/to/your/certificate.pem.202409 -noout -ocsp_uri

を実施したところ、http://e6.o.lencr.orgと返ってきました。

導き出される状況

  • 証明書発行時に何らかのエラーが発生して、このURIが欠落した
  • 筆者は他に複数のドメインを利用し、いずれもLet's Encryptで証明書を発行しています。1つだけならいざ知らず、現行全てのドメインでの証明書でこのURLが欠落しているのは一時的なエラーではないと考えました。

そこで、もう一つの可能性として「Let's Encryptの仕様が変わったのでは?」と情報を探していきます。

答えを発見

Removing OCSP URLs from Certificates from Let's Encrypt

Let’s Encrypt will be removing OCSP URLs from certificates on May 7, 2025 as part of our plan to drop OCSP support and instead support certificate revocation information exclusively via CRLs.
Let's Encryptは、2025年5月7日にOCSPのサポートを停止し、代わりにCRLを介してのみ証明書の失効情報をサポートする計画の一環として、証明書からOCSP URLを削除します。

状況そのもののアナウンスを見つけました。この、OCSPのURLが消えた証明書は、いずれも、2025年5月18日以降に発行したものです。完全に時期的に一致。

対処

ここが分かれば、後は設定変更です。Ubuntuサーバで設定を変更します。

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

設定ファイルは自分の環境に合わせます。任意のバックアップディレクトリを指定します。

  • ファイルバックアップ確認
diff -u /path/to/backup/directory/virutal.conf.$(date +%Y%m%d) /etc/apache2/sites-available/virutal.conf

差分がなければバックアップ完了です。

  • ファイル編集

任意の方法で(要管理者権限)以下のように編集します。

# 2025年5月のLet's Encryptの方針によりOCSPが廃止されたため
SSLUseStapling Off
#SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
  • 編集確認
diff -u /path/to/backup/directory/virutal.conf.$(date +%Y%m%d) /etc/apache2/sites-available/virutal.conf
-SSLUseStapling On
-SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
+# 2025年5月のLet's Encryptの方針によりOCSPが廃止されたため
+SSLUseStapling Off
+#SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
  • 整合性確認
sudo apache2ctl configtest

Syntax OKを確認します。

  • Apache再起動前確認
systemctl status apache2.service

active(running)を確認します。

  • Apache再起動
sudo systemctl restart apache2.service

※reloadより確実なrestartを採用しています

  • Apache再起動後確認
systemctl status apache2.service

active(running)を確認します。

修正確認

設定を反映させたサイトを適当に閲覧し、エラーログにて、冒頭のエラーがないことを確認しました。

Redmineのマルチドメインのメモ。

公開用Redmine等で取得しているreisalin.com。今回、新たに「ryza.jp」を取得しました。

そこで、「1つのRedmineサイトに対して、別のドメインからアクセス可能にする」方法を取ったのでメモに残します。

やったこと

の両方からアクセスできるようにする。

環境

  • Ubuntu 24.04
  • Apache 2.4
  • Redmine 5.1
  • (DB等は割愛)

以下のように設定しています。

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

準備

  1. DNS設定で、両方のドメインから同一のIPが引けるように設定を行いました。
  2. ワイルドカード証明書を取得しました。

実施手順

ディレクトリ移動

cd /etc/apache2/sites-available && pwd

ファイルコピー

sudo cp -pi atelier.conf atelier_ryza.jp.conf

ファイル編集

  • 主な編集
-servername atelier.reisalin.com
+servername atelier.ryza.jp
  RewriteEngine On
         RewriteCond %{HTTPS} off
         RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

-    CustomLog /var/log/atelier/atelier_access.log combined env=!dontlog
+    CustomLog /var/log/atelier_ryza/atelier_access.log combined env=!dontlog

-SSLCertificateFile /etc/certs/reisalin.com.crt
-SSLCertificateKeyFile /etc/private/reisalin.com.key
+SSLCertificateFile /etc/certs/ryza.jp.crt
+SSLCertificateKeyFile /etc/private/ryza.jp.key

かなり単純な編集です。すなわち、コピーした後で

  • servernameを変える
  • ログの出力先を必要に応じて追加する
  • 証明書と秘密鍵をドメインに応じたものに変える

.conf有効化と反映

  • .conf有効化
sudo a2ensite atelier_ryza.jp.conf
  • 整合性確認
sudo apache2ctl configtest

Syntax OKを確認します。

Webサービス再起動

  • サービス再起動前確認
systemctl status apache2.service

active(running)を確認します。

  • サービス再起動
sudo systemctl restart apache2.service && $?

0を確認します。

  • サービス再起動後確認
systemctl status apache2.service

active(running)を確認します。

確認

以下、両方のサイトにアクセスします。

それぞれで同じコンテンツが見えればOKです。

備考

なぜ、このマルチドメインがうまくいったか?

Redmineのプログラムが、内部処理としてURLを参照しないというある種のおおらかさに救われました。また、リンクの参照なども(明示しない限りは)相対パスで記述されるため、混乱も少なかったと思います。

これが、他の(特にLalavelフレームワークのようなPHP環境)だとAPP_URLが関係するため、両立は今回のように上手くいきません。別途、リバースプロキシーを立てるなどの配慮が必要です。

Page 2 of 50

Powered by WordPress & Theme by Anders Norén