Jailhouse Lockシステム技術スタック解説:mod_rewriteによるクローラー誘導作戦。

こちらの記事では、最速のナイフであるmod_aliasと、強力な拳銃であるmod_rewriteの特徴、そして「速度と役割のトレードオフ」についてお話ししました。

ここからは、筆者が実際に運用している atelier.reisalin.com の設定ファイルを元に、この2つの武器をどのように組み合わせ、悪意あるボットや過剰なクローラーを迎撃しているのか。その具体的な防衛システム、名付けて「Jailhouse Lock(ジェイルハウスロック)」の核となるmod_rewriteモジュールについてお話しします。

mod_rewriteとは?

mod_rewriteは、リクエストされたURLをファイルシステム上の特定の場所にマッピング(転送・代替)したり、別のURLへリダイレクトしたりするための、Apacheの拡張モジュールです。(そのため、多くのディストリビューションではインストールと同時に機能が有効化されていないことが多数あります。)

Ubuntu系であれば

sudo a2enmod rewrite
sudo systemctl restart apache2.service

で有効化されます。

再掲:mod_alias との違い

どちらも「URLを操作する」という意味では同じですが、そのアプローチと内部処理の複雑さに大きな違いがあります。

項目mod_aliasmod_rewrite
コンセプト単純なマッピングとリダイレクト強力なURLカスタマイズと書き換え
判定基準単純な前方一致(接頭辞マッチ)正規表現、Cookie、環境変数、時間など
処理速度非常に高速(軽量)やや低速(ルール毎に正規表現エンジンが動く)
設定の難易度簡単(初心者向け)複雑(記述ミスで無限ループが起きやすい)
主な用途フォルダの共通化、単純なサイト引っ越し綺麗に整形されたURL(Smart URL)の実現、複雑な条件分岐

最大の違い:正規表現と条件分岐の有無

mod_aliasは、URLの「先頭が一致しているか」という単純な比較しか行いません。

一方、mod_rewriteは「リクエストがGoogle Chromeから来たら」「平日の昼間なら」「Cookieに特定の文字が含まれていたら」といった、高度な条件分岐(RewriteCond)や、正規表現を使った自由自在なURLの作り替え(RewriteRule)が可能です。

筆者の設定内容抜粋

まずは、実際に稼働している設定の抜粋をご覧ください。

<VirtualHost *:80>
    ServerName atelier.reisalin.com
    RewriteEngine On
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName atelier.reisalin.com

    # ----- ログの選別と抑制 -----
    SetEnvIf Remote_Addr "192.0.2.1" dontlog
    SetEnvIfNoCase User-Agent "Googlebot" dontlog
    SetEnvIfNoCase User-Agent "GoogleOther" dontlog

    # ModSecurity等、WAFで捕獲したエラーはログを肥大化させない
    SetEnvIf MSC_RULE_ID "4009" dontlog
    CustomLog /var/log/apache2/atelier_access.log combined env=!dontlog

    DocumentRoot /home/www-data/atelier/public

    # --------------------------------------------------
    # 第一層:【mod_alias】によるハニーポットへの一撃転送
    # --------------------------------------------------
    <IfModule mod_alias.c>
        # 監獄(Jailhouse)となる隔離ディレクトリを定義
        Alias /__jailhouse_lock /home/www-data/nepenthes

        # 存在しないはずの脆弱性パスへのアクセスを最速でトラップへ
        Alias /wp-login.php   /home/www-data/nepenthes/login.html
        Alias /wp-admin       /home/www-data/nepenthes/login.html
        Alias /.git           /home/www-data/nepenthes/git.html
        Alias /assets-archive /home/www-data/nepenthes/login.html

        <Directory /home/www-data/nepenthes>
            Options -Indexes
            AllowOverride None
            Require all granted
        </Directory>
    </IfModule>

    # --------------------------------------------------
    # 第二層:【mod_rewrite】による動的・精密迎撃
    # --------------------------------------------------
    <Directory /home/www-data/atelier/public>
        Options -MultiViews
        AllowOverride All
        Require all granted

        <IfModule mod_rewrite.c>
            RewriteEngine On

            # 【迎撃フェーズ1】悪質botフラグが立っている通信の隔離
            RewriteCond %{ENV:bad_bot} =1
            RewriteCond %{REQUEST_URI} !^/__jailhouse_lock/
            RewriteRule ^.*$ /__jailhouse_lock/topgear.html [L,E=dontlog:1]

            # 【迎撃フェーズ2】特定の重いコンテンツを狙った過剰クローラー対策
            SetEnvIf Request_URI "^/projects/zettel" is_zettel

            # 大量のカンマ区切り(%2C)や、極端に長い(150文字以上)悪意あるクエリを検知
            SetEnvIf Query_String "tag=.*(%2[cC]|,|%e3%80%81).*(%2[cC]|,|%e3%80%81).*(%2[cC]|,|%e3%80%81)" bad_tag_stacking
            SetEnvIf Query_String "tag=.{150,}" bad_tag_stacking

            # 特定ページ、かつ異常クエリというパズルが揃った瞬間に500エラーで即撃破
            RewriteCond %{ENV:is_zettel} 1
            RewriteCond %{ENV:bad_tag_stacking} 1
            RewriteRule ^ - [E=dontlog:1,R=500,L]
        </IfModule>
    </Directory>
</VirtualHost>

防衛ストーリー:ナイフで受け流し、拳銃で仕留める

この「Jailhouse Lock」システムは、先の記事で述べたmod_alias(ナイフ)とmod_rewrite(拳銃)の特性をコンビネーションとして昇華させたものです。

この言葉は大好きなので何度でも再掲しますが:『MASTERキートン』のプロフェッサーの言葉。

「やめておけ」
「…………」
「拳銃の方が、ナイフよりも速いと思っているんだろう。
 だが、拳銃はデリケートな道具だ。
 弾が出ないかもしれないし、
思い通り的に当たるとは限らん。
おまけに拳銃は、
抜き、構え、引き金を引くまでに三動作(スリーアクション)……
 その点ナイフは、一動作(ワンアクション)で終わる。
この距離なら、絶対に俺が勝つ!!
どうする? それでもやってみるかね?」

これはナイフの方が有利という単純な比較論ではなく、

「この距離ではナイフが有用」だが、「ある程度のアクションや破壊力が必要な場合は拳銃が必要なるケース」というお話と筆者は捉えています。

第一層(mod_alias):無差別スキャンを「無駄なく」いなす

サイトがWordPressで作られていようがいまいが、botは機械的に /wp-login.php/.git を探して叩いてきます。これらはURLの文字列そのものが標的であるため、複雑な条件分岐は不要です。

ここで登場するのがナイフの速度を持つ mod_alias です。

        # 監獄(Jailhouse)となる隔離ディレクトリを定義
        Alias /__jailhouse_lock /home/www-data/nepenthes

        # 存在しないはずの脆弱性パスへのアクセスを最速でトラップへ
        Alias /wp-login.php   /home/www-data/nepenthes/login.html
        Alias /wp-admin       /home/www-data/nepenthes/login.html

この部分。ボット、クローラー、悪意ある攻撃者が挨拶代わりに上記のサイトへのURLに一致した瞬間に、メインアプリケーション(PHPなど)を一切起動させることなく、最速でハニーポット(ダミーのHTML空間 nepenthes)へと受け流します。サーバーのリソースを1ミリも無駄にしない、ナイフならではの「一動作(ワンアクション)」の防御です。

第二層(mod_rewrite):パズルを解き明かし「精密に」射抜く

しかし、中には特定のコンテンツ(例:負荷の重い検索機能など)に対して、URLの引数(クエリ)を巧妙に変えながら何度もクロールしてくる、たちの悪いボットがいます。

URLの文字しか見られない mod_alias では、URLの後ろに付く ?tag=xxx の中身まで検知することはできません。ここで拳銃である mod_rewrite を引き抜きます。

RewriteCond %{ENV:is_zettel} 1
RewriteCond %{ENV:bad_tag_stacking} 1
RewriteRule ^ - [E=dontlog:1,R=500,L]

「特定のコンテンツへのアクセスである(is_zettel)」
「かつ、タグの指定が異常に長い、または大量に詰め込まれている(bad_tag_stacking)」

この複数の条件が上から順にカチリと噛み合った瞬間、mod_rewrite は狙い違わず [R=500,L] という弾丸を放ち、リクエストを強制終了させます。同時に [E=dontlog:1] フラグを立てることで、ボットの嫌がらせによる「ログファイルの肥大化(ディスク容量の圧迫)」という二次災害まで綺麗に防いでみせるのです。

なぜ nginx ではなく、Apache なのか?

近代的なWebサーバーとしてnginxが台頭する中、なぜ筆者がApacheを用いる理由は以下の通り。

Apacheの持つ「上から下に流れる手続き型の思考」が、このような防衛ロジックを組む際に圧倒的に人間にとって直感的だからです。

もし、これと同じ「AかつBの条件を満たした時だけ、500エラーで弾いてログを消す」という処理をnginxで実装しようとすると、事情が変わってきます。nginxには条件を連鎖させる RewriteCond のような仕組みがなく、また if 文の挙動が非常にデリケート(通称:If is Evil)であるため、以下のような不格好な「変数ハック」を強いられます。

例えば、これと同等の機能をnginxでやろうとすると

# nginxで複数の動的条件を重ねる場合の苦肉の策
set $block_trigger "";
if ($is_zettel) { set $block_trigger "Y"; }
if ($bad_tag_stacking) { set $block_trigger "${block_trigger}Y"; }
if ($block_trigger = "YY") {
    return 500;
}

かなりifの入れ子構造が面倒になります。それに対し、Apacheは「この条件を満たし、さらにこの条件も満たしたら、このルールを適用して終了!」と、設計思想をそのまま設定にぶち込む強みがあります。

結び:適材適所の美学

強力な道具は、それ単体で振り回しても真価を発揮しません。

  • 固定の攻撃パスは、システムに最も負荷をかけない mod_alias で門前払いする。
  • 動的なパラメータや環境変数が絡む高度な迎撃は、mod_rewrite の柔軟性を活かしてピンポイントで処理する。

速度のナイフと、射程の拳銃。

この2つのモジュールを「適切なコンテキスト」で併用することで、設定ファイルそのものである程度の防御は出来るというお話です。

余談ではありますが:mod_rewriteは強力ですが、設定を一行誤れば自分自身が500エラーの被害者になります。

「『いい鉄砲は打ち手を選ぶ』ってことわざ知ってるか?
威力のある鉄砲は その分扱いも難しく危険
だから未熟者が使うと打ち手の方がケガをするってことさ」

という『ONE OUTS』で渡久地が言った言葉を持って、本記事を締めくくります。

初夏のご馳走、第二段。

更に美味しい食事を戴く機会がありました。

第一皿:お通し三種盛り

  • 手作り豆腐
    • 大豆の甘みとコクがぎゅっと詰まった、なめらかで濃厚な味わい。
  • 茹で枝豆
    • ぷっくりと実が詰まった、ビタミンB1豊富な疲労回復の定番。
  • アサリと山菜の和え物
    • タウリンや鉄分が豊富な貝類と、食感の良い山菜を合わせた胃腸に優しい小鉢。

第二皿:豪華お刺身盛り合わせ(五種盛り)

  • 本マグロ(赤身)
    • 筋と平行に美しく包丁が入れられた、口当たりなめらかでDHA・EPA豊富な極上品。
  • 生ウニ
    • 一粒一粒がふっくらと自立した、濃厚でビタミンEたっぷりの黄金色の海の恵み。
  • 〆サバ
    • 皮目が銀色に輝く、しっとりとした絶妙な締め具合の青魚。
  • カツオのタタキ
    • 香ばしく炙られた身に、刻みネギとおろし生姜の薬味がベストマッチ。
  • 白身魚(タイまたはヒラメなど)
    • 透明感があり、コリコリとした歯ごたえと上品な甘みが広がる高タンパクな一品。

🦪 第三皿:旬の岩牡蠣(ミディアムレア焼き)

  • 焼き岩牡蠣
    • 「Rのつかない月」に最高潮を迎える夏の贅沢。焼いても殻いっぱいのサイズを保つ圧倒的なボリュームと、亜鉛・タウリンの塊のようなクリーミーな旨味。まさに言葉を失う一品。

🪵 第四皿:メインディッシュ・アイナメの兜煮

  • アイナメの兜煮
    • 初夏に旬を迎える高級白身魚。一切の煮崩れなしに美しく照り映える職人技。目玉、唇、ほお肉、ヒレ肉に詰まった極上のゼラチン質とコラーゲン、そして奥深いタレの融合に目を疑うほどの傑作。

第五皿:もろこし天と脱皮エビ唐揚げ

  • もろこし天(とうもろこしの天ぷら)
    • サクサクの衣の中に、シャキシャキとした歯触りとプッツリ弾ける濃厚な甘みを閉じ込めた初夏の一品。
  • 脱皮エビ(ソフトシェルシュリンプ)の唐揚げ
    • 殻ごと丸ごと香ばしく揚げ、身のプリプリ感を完璧に残した、カルシウムとタウリンがたっぷりの悪魔的揚げ物。

結び:黒蜜きな粉アイスクリーム

  • 和風バニラアイス
    • ひんやり冷たいバニラに、濃厚な黒蜜と香ばしいきな粉(大豆タンパク)が三位一体となった、脳と心を満たす至福のデザート。

と、恐るべきボリュームと量でした。

カレーの戦略。

美味しいお店のメニューの狙いを見るのが好きです。

ある日にいただいたカレーの戦略性をこっちで勝手に推理してみます。

見た目は本当に日本の家のカレー。

  • ジャガイモ
  • にんじん
  • タマネギ

違いがあるとすれば福神漬けの代わりに細切り唐辛子。まずは食べてみます。

「肉」

でした。それも普通にお目にかかれないような圧倒的な牛肉の旨味と歯ごたえ、筋の柔らかさがこれでもかと出てきます。

そして飛び込んでくるほくほくのジャガイモとにんじん、ジャガイモの甘みがご飯と一体化。

そして、やや辛のスパイスが刺激し、全てを平らげてくれます。

この店の狙い、推測

ここで、一つ謎が出てきました。なぜこの店は、この牛肉で勝負ができるカレーを

  • おしゃれなカレーポットに入れず
  • 奇をてらわない平皿盛りで
  • 日本のカレーの見た目にしたのか

です。それは、この「圧倒的な牛肉」を強烈に意識させるためではないかという仮説。

どうしたって人はバイアスに捕らわれます。そこで高級店のカレーのスタイルで出てくれば「さすがは高級店」と、比較対象が別のものになります。

しかし、店のカレーが、こちらのように家庭的な見た目ならば、どうしたって「家のカレーとどう違うのか」の確固たる評価軸が出てきます。

その上で「肉が違う。この肉の出し方は自分には難しい」と思わせる戦略。

正直、普段の手作りカレーが一歩下がるような感覚でした。つまりこれは、味の美味しさで勝負するのはもちろん

「あなたの普段食べているカレーとは素材が違います」

をすり込むための擬態、とも取れそうです。実際問題、もう一度このカレーを食べたいという気持ちにあふれていますので。

『メリー・ポピンズ リターンズ』

Cover is not the book / 心が目に見えないように本も
So open it up and take a look / 表紙の美しさに騙されちゃダメ
'Cause under the covers one discovers / 中身読んだらやさしい王様
That the king may be a crook / 詐欺師だとわかるかも

を地で行くカレーでした。

タマネギ利用の副菜

タマネギを消費する必要が出てきたため、これを活かした副菜を作ってみます。

輪切りにした結果、紫タマネギ。この甘みを活かすため、レンジグリルで5分温め、かき混ぜて更に5分の加熱。

ここに加えるのは

  • ツナ缶
  • 鰹節
  • ポン酢

ツナ缶は油ごと。ポン酢は心持ちたっぷり。鰹節はケチをせずどっさり。

最後に七味で味を調えました。

  • タマネギの甘みとわずかに残るシャキシャキ感
  • ポン酢の鮮烈な酸味
  • 鰹節とツナ缶の旨味

がしっかり加わり、単体でも美味しいものが。

お弁当の付け合わせとしても最高ですし、

サンドイッチと合わせても申し分ないものができあがりました。

2026年6月の差しボードゲームの記録。

友人と1 vs 1でのボドゲの記録です。

リビングフォレスト・デュエル

二戦続けて実施。

  • 1戦目:鬼火を連続で送りつけて勝利。
  • 2戦目:召喚獣全てをこちら側で埋めての勝利。

ナショナルエコノミー完全版(グローリー)

これは完全に実力差が出たという形。100点差を付けての圧勝。

カエサル!

準アブストラクト。私はカエサル担当。史実通りに周辺植民地の支配を得るように奮闘したものの、ポンペイウスがイタリアの実権を握ったという史実通りの敗退。

差しゲーは2人千専用ゲームもできるので好みです。

食事と海鮮。

素晴らしい食事を戴きました。

お作り

季節の盛り合わせ。特にしめさばに感動。

豚の角煮

クリアなあく取りと、しっかりと染みこんだ豚肉、とろけるような脂身。

鮎の塩焼き

この焼き色はもちろん、頭も骨もしっかり食べられて詰まらない絶技です。

厚揚げ

一番感動したのは実はこちら。「その場で揚げた」真に出来たての厚揚げ。なので、普通に口にした瞬間に熱々の豆腐が飛び出てきて火傷寸前でした。

なので、その香ばしさが更に薬味とひき立て合います。

ジャガイモの素揚げ

好物だからと挙げてくれました。バターと塩のみという潔さがジャガイモのほくほく感を引き立てます。

稲庭うどんと野菜点

食事の締め。正義の取り合わせという感じ。

手まり寿司

感動したというしめさばのフィードバックをそのまま手まりにするという技術と心配り。

と、実に素晴らしい食事をいただけました。

『IDEA SPHERE』3つのバイアス

『黄色い顔(シャーロック・ホームズの思い出)』の象徴的な言葉。

「ワトソン」ホームズは言った。「もし僕がちょっと自分の能力に自信過剰になっていると気付いたり、事件に対して必要なだけの努力をしていないようだったら、僕の耳元で『ノーベリ』とささやいてもらえないだろうか。そうすれば僕は大いに君に感謝するだろう」

これ、

  • 探偵とは言え失敗する
  • キャラクター造形の中でのウィークポイントを晒すことで更なる魅力を生む(ギャップ萌え)

だと思っていましたが:まさに、これと同じような状況が起きたので自戒3割、言い訳7割でこのテキストを残します。

起きたこと

私が過去に初期設定を案内してアカウントまで譲渡したWordpressサイトに話は遡ります。

そのサイトの持ち主から「急にWebサイトに繋がらなくなった」というヘルプ要請。「アプリには入れるが更新はできない」ということ。

取り急ぎ「情報を集めるだけ集めて伺う」と返して状況確認です。

初動

  • Webブラウザでの挙動

そのサイトのURLを入力。403エラーが出ます。

  • curlでの挙動
curl -I https://hoge.example.com
HTTP/2 403 
server: nginx 
date: Fri, 19 Jun 2026 05:28:52 GMT

間違いなく403エラーです。

更に

  • index.php
  • /wp-login.php
  • /wp-admin

も同様に403エラーになりました。

考えられる可能性と却下していった理由

料金未払い

これはないと考えていました。なぜなら、クレジットカードの自動更新です。洗い替えなどもあるだろうと真っ先に却下。

それ以上に、そのドメインでWHOIS検索したところ2027年まで有効。しかも、そのネームサーバは仮想サーバを向いています。

ドキュメントルートが読めない。

  • ディレクトリのパーミッション
  • 所有者
  • ドキュメントルートの設定

例えばpublic_htmlが何らかの操作で700になってしまうと、nginxが403を返します。

WAF偽陽性による.htaccessの書き換え。

「アプリを起動したら更新ができなくなった」から来る推察。

であれば、WAFによってアクセスが遮断された。偽陽性です。(筆者も散々経験がありますが)

WAFが下手に.htaccessを書き換えることでアクセス制限を喰らった

つまり、更新の時に何かしらの操作ミスがあって一斉に403を返したのではないか。

だとすれば

  • 仮想サーバの管理画面に入る
  • 下手をすればサイトの再構築

あたりも考慮に入れて、その持ち主のところを訪れます。

原因と復旧

訪れるやいなや、

「料金督促メール来てました!」

という連絡。つまり、「私が最初に斬って捨てた」原因だったのです。

この落とし穴は、ドメインとサーバーの契約期間が異なっていたことでした。

  • ドメイン:
    • 数年単位で契約済み
  • サーバー:
    • 単年契約で更新漏れ

その結果、

  • WHOISは正常
  • DNSも正常
  • ドメインも生きている
  • しかしWebサーバーは契約停止状態のため403を返す

という、一見するとWordPress障害にも見える状況が出来上がっていた次第。そして、決済を確認後、

curl hoge.example.com
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://hoge.example.com/">here</a>.</p>
</body></html>

が返ってきましたし、サイトも完全復旧です。

真っ先に外した「なぜ支払いが行われなかったか」

これも実に単純でした。

「クレジットカードを紛失して再発行した」

という、極めて人間らしいミスでした。この督促メールも

「大量のメールに紛れて見落としていた」

種が分かってしまえば実に単純。これを忘れて

  • htaccess
  • WAF

などを疑ったのが私の技術バイアスであり真の問題は

「サーバー契約は本当に有効か?」

というチェックが抜けていたことでした。そして、その契約切れと自動更新がオフになって苛理由は

クレジットカード再発行

だったという物理的な問題に抜けていました。

  • 「自動更新の設定」
  • 「決済手段が現在も有効か」

は別問題です。ところが、人間は

自動更新 = 更新される

と無意識に補完してしまいます。

実際には、自動更新は「決済に成功すれば更新される」であって、

  • カード期限切れ
  • カード再発行
  • 利用停止
  • 限度額超過

などで、静かに失敗することがあります。

技術スタックの落とし穴

利用者
↓
WordPress
↓
PHP
↓
Apache/nginx
↓
サーバー契約
↓
DNS
↓
ドメイン契約

という技術的な例で解釈をしていましたが、実際の原因は「サーバー契約」というアプリケーションより一段下の状況だったのです。

デブリーフィングという名の言い訳。

今回の一件で唯一良かったと思ったところは、

この事態を重く受け止め、どういう結果でもいの一番に駆けつけるという「速度は誠意」を見せられたこと。

しかし、問題はそれ以前にあります。

バイアス1:技術バイアス

ここのところ私は

  • Webサーバ周りのチューニング
  • AIクローラーとの戦い
  • セキュリティ

といった技術バイアスに溺れていました。ですから、この問題も同じに違いないという利用可能性ヒューリスティック(Availability Heuristic)に捕らわれていたこと。

これが第一の問題。

バイアス2:心理的バイアス

実写版『カイジ 人生逆転ゲーム』での好きな言葉があります。

「利根川‥‥
 俺がヘビに見えたか‥‥‥?」
 「ああ‥‥‥
  ヘビだろうが‥‥‥‥!」
「そうか‥‥‥
 なら お前こそヘビなんだ‥‥‥‥
 こんなふうな物言わぬ心理戦は
 鏡を見るようなもの‥‥‥
 相手の心を読もうと‥‥
 必死に考えるつもりが‥‥‥
 気がつけば自分だったらどうするかと考えている‥‥‥
 つまり俺がヘビに見えたなら‥‥‥
 お前こそヘビなんだ‥‥‥」

つまり、相手の初歩的な設定漏れや状況の変更という前提を忘れ、技術に溺れていました。これが深刻です。

上記でも述べたように、私は「請求忘れ」という一度は正解に導いていたのに「自動更新設定はしているはず」として、真っ先に切り捨てたこと。しかし、よくよく考えれば

  • カードの有効期限切れ(洗い替えをしていなければ)
  • 今回のカードの再発行
  • 残高不足(支払い能力)

というのは容易に起こりえます。こういう人間的な問題を「そんなことはまずないだろう」とした心理的なバイアス。このカイジの言葉で言うのなら「このサーバで何をしたのか」と鏡を見るように考え込み、自分が起こしがちなミス=相手のミスと考えていたこと。

バイアス3:生存バイアス。

最後に、「今までも解決してきた。だからこれもすぐに解決できる」という生存バイアスです。それこそ、私がメモとして利用しているGrowiのトップページの

Those who survive a long time on the battlefield start to think they are invincible.
I bet you do too, buddy.

"不死身のエースってのは戦場に長く居たものの過信だ"
"お前のことだよ相棒"

という、『ACE COMBAT ZERO』の言葉を真に噛みしめた、が今日の結論ですね。

ビタースイートな結末

と、上記、最初に述べたような言い訳の方が多い失敗談となりましたが、

成功体験が積み重なると、人は「今回もきっと高度な技術的原因だ」という思考になりやすいです。そして、そこが一番の慢心の結果です。

そして今回の真相はカード再発行で自動更新が止まっていた。あまりにも「人間的」でした。

余談、と言うか警句

この出来事が起きた日、夢枕に亡父が立ったのです。生前、父は

いかなる敵にも敬意を払え。その上で全力で叩き潰せ

とよく言っていて、没後10年目に夢枕に立ち

この言葉の真意は、「敬意を払わないとどこかに油断・慢心が生まれる。それが敗因に繋がる」という意味だからな

と但し書きをしました。なので、今回の物言わぬ夢枕は

この言葉を理解しているのか?

を問うものだったかと思います。即ち、この、技術的に物事を解決したため、その本質を見失っているぞという警告の予言めいた出来事だったのかな、と改めて思いました。

BookStackにMermaid Viewerを導入する手順

ある種悲願でもあった、「BookStackにmermaid.jsを描画させる」が叶いました。

環境

  • BookStack v26.05.1
  • Apache 2.4
    • 実行ユーザーはwww-data
  • PHP-FPM 8.3
  • MySQL 8
  • Ubuntu 24.04

さっくりとした手順

  1. BookStackのルートディレクトリに移動します。
  2. Mermaid Viewerモジュールをインストールします。
  3. .envの編集をします(ハマった点)
  4. 設定を反映させます。
  5. 動作の確認を行います。

BookStackのルートディレクトリへ移動

cd /home/www-data/BookStack

筆者環境です。お使いの環境に応じてパスは変更してください

Mermaid Viewerモジュールをインストール

sudo -u www-data php artisan bookstack:install-module https://www.bookstackapp.com/hack-modules/mermaid-viewer.zip

途中で

Are you sure you trust this source?

と聞かれるのでyesで返答します。テーマが無い場合は

No active theme folder found...

と表示されるので同様にyesで返答します。

すると

themes/custom/

ディレクトリが作成され、

themes/custom/modules/mermaid-viewer/

ディレクトリへモジュールがインストールされます。

.env にテーマを設定(重要)

ここが今回ハマったポイントです。

.env を編集します。(要管理者/bookstack実行ユーザー権限)

APP_THEME=custom

を追加します。

これを設定しないと、themes/custom以下のディレクトリはは一切読み込まれません。


設定反映

php artisan optimize:clear

または

php artisan cache:clear
php artisan config:clear
php artisan view:clear

でキャッシュをクリアします。

(推奨)PHP/Apacheを再起動

PHP-FPMなら

sudo systemctl restart php8.3-fpm

Mod-PHP環境なら

sudo systemctl restart apache2

で、実行環境を再起動します。

設定反映確認

BookStackにログインして、設定反映されていることを確認します。

エディタの形式をMarkdownなら

```mermaid
flowchart TD
    A --> B
    B --> C
```
flowchart TD A --> B B --> C

保存後、閲覧画面でMermaid図としてレンダリングされます。

※ 編集画面の右ペインには表示されないのでご注意ください。

補足

インストール後のディレクトリは概ね以下のようになります。

BookStack/
└── themes/
    └── custom/
        └── modules/
            └── mermaid-viewer/

今回のポイント

実は一番重要なのはこのメッセージでした。

You will need to set APP_THEME=custom in your BookStack env configuration to enable this theme!

初回インストール時に表示されるのですが、見落としやすい一文です。

筆者も最初は「インストールは成功しているのに表示されない」という状況から別の原因を疑いましたが、このメッセージと APP_THEME の未設定を確認したことで、原因を特定できました。

Apacheモジュール「mod_alias」解説。

筆者がWebサイトの防衛に、そして過剰にクロールをするボットを他の場所へとご案内するために用いているmod_aliasのご紹介です。

というのも、筆者がこれから述べる対クローラー迎撃システム「Jailhouse Lock」には、このモジュールが必要だからです。

1. mod_aliasとは何か?

mod_aliasは、リクエストされたURLをファイルシステム上の特定の場所にマッピング(転送・代替)したり、別のURLへリダイレクトしたりするための、Apacheの標準モジュールです。(そのため、多くのディストリビューションではインストールと同時に機能が有効化されています)

主な役割は以下の2つです。

  • エイリアス(別名)の設定:
    • ドキュメントルート(公開ディレクトリ)の外側にあるフォルダを、あたかも内側にあるかのようにURLに紐付けます。
  • 単純なリダイレクト:
    • 特定のURLに来たアクセスを、別のURL(別ドメインなど)へ転送します。

代表的なディレクティブ

  • Alias /images /var/www/shared/images (URLの/imagesを特定のフォルダに対応付ける)
  • Redirect permanent /old.html http://example.com/new.html (永続的な301リダイレクト)

2. mod_rewrite との違い

どちらも「URLを操作する」という意味では同じですが、そのアプローチと内部処理の複雑さに大きな違いがあります。

項目mod_aliasmod_rewrite
コンセプト単純なマッピングとリダイレクト強力なURLカスタマイズと書き換え
判定基準単純な前方一致(接頭辞マッチ)正規表現、Cookie、環境変数、時間など
処理速度非常に高速(軽量)やや低速(ルール毎に正規表現エンジンが動く)
設定の難易度簡単(初心者向け)複雑(記述ミスで無限ループが起きやすい)
主な用途フォルダの共通化、単純なサイト引っ越し綺麗に整形されたURL(Smart URL)の実現、複雑な条件分岐

最大の違い:正規表現と条件分岐の有無

mod_aliasは、URLの「先頭が一致しているか」という単純な比較しか行いません。

一方、mod_rewriteは「リクエストがGoogle Chromeから来たら」「平日の昼間なら」「Cookieに特定の文字が含まれていたら」といった、高度な条件分岐(RewriteCond)や、正規表現を使った自由自在なURLの作り替え(RewriteRule)が可能です。

3. mod_aliasが「優れているパターン」

「mod_rewriteがあれば、mod_aliasはいらないのでは?」と思われがちですが、Apache公式も「単純なタスクであれば、mod_rewriteではなくmod_aliasを使うべき」と推奨しています。

mod_aliasを選ぶべき(優れている)具体的なパターンは以下の3つです。

① サーバーのパフォーマンス(速度)を最優先したいとき

mod_rewriteは、リクエストが来るたびに複雑な正規表現エンジンを動かすため、CPUリソースを消費します。

大規模サイトやアクセスが集中する環境で、単なるURLの転送やフォルダの紐付けを行う場合、mod_aliasの方が圧倒的に処理が軽く、サーバーの負荷を抑えられます。

② ドメイン全体の引っ越しや、単純なURL変更(リダイレクト)

サイトのリニューアルで、古いページから新しいページへ1対1で転送したい場合や、古いドメインから新ドメインへ丸ごと転送したい場合は、mod_aliasの Redirect で十分対応できます。

  • サイト全体を新ドメインへリダイレクト(mod_alias)
Redirect permanent / https://new-example.com/

これをmod_rewriteで書くと記述が複雑になり、設定ミスのリスク(無限ループなど)が高まります。

③ 複数サイトで画像やアセット用のフォルダを安全に共有したいとき

例えば、サーバー内の /var/www/common_assets/ というフォルダを、複数のWebサイトで /assets というURLで共通利用したい場合です。

  • 安全かつ高速に共通フォルダをマッピング(mod_alias)
Alias /assets /var/www/common_assets

mod_aliasは設定がシンプルなため、ヒューマンエラーによるセキュリティホールの発生(意図しないシステムファイルの公開など)を防ぎやすいというメリットもあります。

それぞれのイメージ

1. mod_alias のシーケンス(単純・高速)

URLの書き換えは行わず、リクエストされたURLの先頭(接頭辞)だけをチェックして、即座にファイルパスへマッピングするか、リダイレクトを返すシンプルな流れです。

sequenceDiagram autonumber participant Client as クライアント (ブラウザ) participant Core as Apache コア (リクエスト受付) participant Alias as mod_alias participant FS as ファイルシステム Client->>Core: HTTPリクエスト (例: /images/logo.png) Core->>Alias: URLの評価を依頼 Note over Alias: URLの先頭(接頭辞)が<br>設定と一致するか単純比較 Alias-->>Core: マッピング先を返却<br>(例: /var/www/shared/images/logo.png) Core->>FS: 指定されたパスのファイルを読み込み FS-->>Core: ファイルデータ Core-->>Client: HTTP 200 OK (レスポンス返却)

2. mod_rewrite のシーケンス(複雑・高機能)

リクエスト受付後、内部でループ(再エントリー)が発生する可能性や、条件判定(RewriteCond)のステップが挟まるため、柔軟ですが処理の工程が多くなります。

sequenceDiagram autonumber participant Client as クライアント (ブラウザ) participant Core as Apache コア (リクエスト受付) participant Rewrite as mod_rewrite participant FS as ファイルシステム Client->>Core: HTTPリクエスト (例: /user/profile) rect rgb(240, 245, 255) Note over Core, Rewrite: [書き換えループの開始] Core->>Rewrite: URLの評価を依頼 Note over Rewrite: 1. 正規表現でURLパターンをマッチング Note over Rewrite: 2. RewriteCondの条件をチェック<br>(Cookie、ブラウザ、環境変数など) Rewrite->>Rewrite: 3. URLの書き換え処理を実行<br>(例: /index.php?mod=user&act=profile) Rewrite-->>Core: 書き換え後の内部URLを返却 end Core->>Core: 内部リダイレクト(新しいURLで再処理) Core->>FS: 最終的なスクリプトやファイルを呼び出し FS-->>Core: 実行結果・データ Core-->>Client: HTTP 200 OK (レスポンス返却)
  • mod_alias(図1):
    • 判定が「前方一致のみ」の一方通行であるため、ステップ数が少なく、非常に高速に処理が終わります。
  • mod_rewrite(図2):
    • 条件チェックのフェーズ(薄い青枠の部分)が多く、さらに書き換えたURLでApache内部で「もう一度リクエストを処理し直す(内部リダイレクト)」という挙動が発生するため、機能性と引き換えに処理が重くなる構造が見て取れます。

まとめ:使い分けの基準

それぞれの使い分けです。

  1. まずは mod_alias で実現できないか考える。(単なる転送、単なるフォルダの紐付けなど)
  2. 「クエリストリング(?id=123など)を判定したい」「特定のブラウザだけ除外したい」「正規表現でURLを激しく書き換えたい」といった複雑な要件が出てきたとき初めて mod_rewrite を導入する。

どちらが優れているか、否かという問題ではなく、これは速度の問題です。

漫画『MASTERキートン』に以下のやりとりがあります。

「やめておけ」
「…………」
「拳銃の方が、ナイフよりも速いと思っているんだろう。
 だが、拳銃はデリケートな道具だ。
 弾が出ないかもしれないし、
思い通り的に当たるとは限らん。
おまけに拳銃は、
抜き、構え、引き金を引くまでに三動作(スリーアクション)……
 その点ナイフは、一動作(ワンアクション)で終わる。
この距離なら、絶対に俺が勝つ!!
どうする? それでもやってみるかね?」

これは「至近距離でのナイフの有用性」を示したものであり、実際にその通りだという説得力があるものです。(調査結果はこの記事です

つまり、mod_alias は「できることが少ないから速い」のではなく、「役割を絞っているから速い」のです。

mod_aliasはナイフの速度。mod_rewriteは拳銃のような強力さがあります。「適切な距離感」でこれらのツールの利用、併用を行いましょうというお話しです。

卵焼きメモ2026年6月版。

一時的に今まで使っていたスープジャー(汁物)の運用を一時的に止めました。

そんな中で美味しい卵が手に入ったので、また卵焼きの熱が高まりました。

今回着目したのはこちら。

チーズです。そもそもチーズオムレツがスタンダードになるぐらい、チーズと卵の相性は抜群です。

醤油系とも相性がいいのは想像に難くないでしょう。

反面、焼くのにコツがいりますが

しっかりきれいに焼けました。

できあがったのはこちら。一段弁当は「これぞ弁当」な見た目になるのもお気に入りです。

Page 1 of 296

Powered by WordPress & Theme by Anders Norén