Skip to content

実行権限が必要なファイル(php.cgi 等)を git 管理すると、デプロイ中にサイトが 500 になる #11

Description

@naokazuterada

事象

実行権限が必要なファイルを git 管理して rsync で配信すると、デプロイ中に一時的にサイトが 500 になる。

2026-07-28 に branddesigncontest.com のデプロイ中、本番が Internal Server Error になった(デプロイ完了後は自動的に復旧)。

原因

さくらインターネットで PHP バージョンを個別指定しているサイトは、.htaccessphp.cgi を使う。

Action myphp-script /php.cgi
AddHandler myphp-script .php

この php.cgi実行権限が必要(705 や 711)。しかし:

  1. git は実行ビットしか記録できない100644100755 のみ)。該当サイトでは 100644(実行不可)で記録されていた
  2. rsync は --perms 付きで動作するため、転送直後に本番の php.cgi が 644 = 実行不可になる
  3. → PHP ハンドラが動かず、サイト全体が 500
  4. after_syncchmod が走って初めて復旧する

つまり rsync 完了 〜 after_sync 完了の数十秒間、サイトが落ちる

メンテナンス画面では防げない

.maintenance による WordPress のメンテナンス画面は、PHP が動作して初めて表示されるphp.cgi が実行できない状態では PHP 自体が起動しないため、メンテ画面も出せずに 500 が露出する。

.depinc-extra.sh のフックでも防げない

#9 で追加したフック(after_sync_extra)は名前の通り rsync の後にしか実行できない。パーミッションを正すのが「壊れた後」になるため、500 の窓は塞げない。

対策

git に記録するモードを 100755 にする。ファイル自体に実行権限を付けること。

chmod +x php.cgi
git add php.cgi
git commit -m "..."

コミット時に mode change 100644 => 100755 php.cgi と表示されれば成功。

これで rsync 直後から実行可能になり、500 の窓が消える。その後 after_sync_extra が 711 / 705 に絞る流れは変わらない。

一時的に 755(other が読み取り可)になるが、php.cgi の中身は PHP バージョン指定の数十バイトのみで、時間も数秒。500 を出し続けるより安全と判断した。

⚠️ git update-index --chmod=+x は使わないこと。 core.fileMode = true の環境では git がファイル実体の実行ビットを見るため、インデックスだけ書き換えても後続の git 操作で元に戻る。実際、これで2回失敗した(1回目はコミット漏れ、2回目はインデックスがリセットされていた)。

検証結果(2026-07-28)— 対策は有効

対応の前後で、デプロイ中のサイトの挙動が明確に変わった。

対応前 対応後
デプロイ中の表示 500 Internal Server Error WordPress のメンテナンス画面
php.cgi の git モード 100644 100755

branddesigncontest.com / niwa-archives.org の両方で確認済み。

デプロイログでも、フックが意図通り動いていることを確認した。

[DEPLOY] - WP core version -> OK (server: 7.0.2 / repo: 7.0.2)
[DEPLOY] - php.cgi -> chmod 711     # niwa は 705

この結果は2つのことを同時に裏付けている。

  1. 対策が有効である — rsync 直後から php.cgi が実行可能になり、500 の窓が消えた
  2. 「PHP が動かないとメンテナンス画面も出せない」という因果関係 — 対応前にメンテ画面が出なかったのは .maintenance が作られなかったからではなく、PHP 自体が起動できなかったため。対策後は同じ .maintenance が正しく機能している

対象サイト

php.cgi を使っている(=さくらで PHP バージョンを個別指定している)サイト。

  • branddesigncontest.com — 711(対応・検証済み)
  • niwa-archives.org — 705(対応・検証済み)

他にも同じ構成のサイトがあれば同じ罠を踏む。確認方法:

git ls-files -s php.cgi   # 100644 なら要対応

根本的な検討課題

「実行権限が必要なファイルを git 管理して rsync する」構成自体に無理がある。git が 644/755 の2値しか持てない以上、711 や 705 のような細かいパーミッションはデプロイ後に付け直すしかない

代替案:

  • php.cgi を git 管理から外す.gitignore + .depignore)。サーバ側にだけ置き、デプロイで触らない。環境ごとに PHP バージョンが違うので、そもそも git 管理する必然性が薄い
  • rsync に --chmod を渡してファイル種別ごとにパーミッションを指定する
  • .htaccess を最後に転送する(順序制御が必要で複雑)

1つ目が最も素直だと思われる。php.cgi はサーバ固有の設定ファイルであり、コードではない。

関連

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions