Files
wordpress/CLAUDE.md
T
claude 30e377d4ec
Helm Chart Release / release-chart (push) Successful in 5s
fix: Hello Dolly等のデフォルトプラグインが再起動のたびに復活する不具合を修正
wordpress-init initContainerのコアファイルコピー処理(cp -r /usr/src/wordpress/* /var/www/html/)が
wp-contentを除外しておらず、PVC上の既存wp-contentへイメージ同梱のデフォルトファイル
(hello.php、akismet/、デフォルトテーマ)を毎回上書きマージしていた。
コピー対象からwp-contentを除外し、PVC上のwp-contentは新規インストール時以外
一切触れないよう修正。
2026-08-26 11:13:48 +09:00

87 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md — WordPress Helm Chart
## リポジトリ概要
Raspberry Pi などのベアメタルで稼働することを想定した、Kubernetes 上で動作する Alpine Nginx + WordPress (PHP-FPM) の Helm チャート。
- **Gitea リポジトリ**: `ssh://git@192.168.9.65/helmchart/wordpress`
- **Helm リポジトリ**: `https://git.cafepieters.com/api/packages/helmchart/helm`
## 実行環境について
WordPress本体はイメージ内蔵のもの(`docker.io/wordpress:<tag>-fpm-alpine`)をemptyDirにコピーして使い捨てで起動し、`wp-content`のみPVCで永続化する(bitnami方式)。PHPの実行環境はこのイメージに依存し、本リポジトリにPHPコードは含まれない。
## Git コミット情報
| 項目 | 値 |
|------|-----|
| 名前 | Claude |
| メール | claude@cafepieters.com |
| SSH キー | `P:\Claude\.ssh\id_claude` |
## 作業完了のルール(重要)
1. **機能を追加・変更した場合は、必ず README.md を更新すること。** 追加・変更した機能の説明を反映してから作業完了とする。
2. **変更は必ず Git Commit / Push まで行うこと。** 作業単位ごとにコミットし、origin(main) へ push するまでが作業完了。
3. **Commit メッセージに Claude クレジット(Co-Authored-By 等)を追記することは禁止。** `user.name = Claude` でコミットされるため、ユーザー名で判別可能。
4. `git pull` で取り込まれた変更は必ず尊重し、revert して push することは禁止(既存の共通ルールと同じ)。
## クラスタ構成メモ(実運用環境)
- ノード: `cpi11`(control-plane, 192.168.9.9/物理IF)、`wpi21`/`wpi22`/`wpi23`(worker)。全てRaspberry Pi(Ubuntu 25.04)。
- CNI: **Cilium**kube-proxyなし、eBPFベース)。`cilium-envoy` Podが動作しており、Cilium組み込みIngress ControllerEnvoyベース)が利用可能。
- Pod CIDR: `10.0.0.0/8`系、ノードごとに `/24` を割り当て(例: cpi11→`10.0.0.0/24`、wpi22→`10.0.1.0/24`、wpi21→`10.0.2.0/24`、wpi23→`10.0.3.0/24`)。
- 外部公開: **kube-vip**ARP方式、静的Pod `kube-vip-cpi11`)。物理ルーターのグローバルIP配下、`192.168.9.0/24` セグメント内でVIPを払い出す。このセグメントはルーターがLAN機器(スマホ/PC等)にDHCP払い出しする範囲と重複しないよう、ルーター側で範囲を絞って共存させている。**IPが希少なため濫用できない。**
- 各WordPress/PHPFPMリリースは現状、`service.type: ClusterIP` + `kube-vip.io/loadbalancerIPs`/`kube-vip.io/vipHost` アノテーションを**Helm管理外で手動付与**し、リリースごとに個別のVIPを得る運用になっている(本チャートの `templates/service.yaml` にはannotationsのテンプレート化自体が存在しないため)。
- **既知の問題**: この構成では、kube-vipがL2 ARP応答に加えて自前でTCPコネクションをプロキシしてしまうため、`externalTrafficPolicy`LoadBalancer/NodePort専用でありClusterIPには無効という制約とは別に、そもそもkube-vipの時点で)実クライアントIPが失われる。詳細はREADME.mdの「kube-vip等でグローバルIP/VIPが限られている環境での実IP取得(共有Ingress Controller構成)」を参照。
- 今後、実IP取得のためCilium組み込みIngress Controller(またはingress-nginx)へ移行する方針で合意済み(2026-08-08時点、ユーザーが選択)。ただし全リリース(wordpress-nginx系だけでなくphpfpm系も含む)の移行が必要な大掛かりな作業のため、本セッションではWordPressチャート側の対応(`ingress.yaml`/`forwardRealIP`は既存機能で対応済み、README migration手順を追記)のみ実施。実際のCilium Ingress有効化・各リリースのhelm upgradeはユーザー側の作業。
## チャート改修履歴
### Hello Dolly等のデフォルトプラグインが削除しても復活する不具合の修正(2026-08-08, v7.1.0-a
※自動更新ワークフローがこの作業と並行してWordPress 7.1.0への正式リリース(v7.1.0)を実行したため、本修正はそのタグの上に手動リリース `7.1.0-a` として適用した。
**症状**: WP管理画面からHello Dolly`hello.php`)を削除しても、Pod再起動のたびに復活する。
**原因**: `templates/deployment.yaml``wordpress-init` initContainerで、WordPressコアファイルをemptyDirにコピーする処理が `cp -r /usr/src/wordpress/* /var/www/html/` という実装になっており、`wp-content` を除外していなかった。`/var/www/html/wp-content` はPVCマウントの別ボリュームだが、`cp -r` はワイルドカード展開で `wp-content` ディレクトリ自体も対象に含めてしまうため、イメージ同梱のデフォルトwp-content(`hello.php``akismet/`、デフォルトテーマ群)がPod再起動のたびにPVC上の既存wp-contentへ**無条件に上書きマージ**されていた。直後にある「PVCが空の場合のみ初期化する」条件分岐(`if [ ! -d /var/www/html/wp-content/themes ]`)は、この最初の `cp -r` の副作用までは防げていなかった。
**対象**: Hello Dolly`hello.php`)だけでなく、Akismet`wp-content/plugins/akismet/`)も同じ理由で同様に復活する。**本チャート自身が明示的に`wp plugin install`等でプラグインを追加している箇所は存在しない**(該当するのはWordPressコア配布物に同梱されているこの2つのみ)。
**修正内容**: コアファイルのコピーを `/usr/src/wordpress/` 直下を1件ずつ列挙し、`wp-content` をスキップするループに変更。これによりPVC上のwp-contentは、新規インストール時(PVCが空=`wp-content/themes` が存在しない場合)以外は一切触れなくなった。
**対象ファイル**: `templates/deployment.yaml`, `README.md`, `Chart.yaml`
### 実IP取得の修正 + SMTP経由メール送信の追加(2026-08-08, v7.0.2-a
**背景**: ルーター(グローバルIP)配下の 192.168.9.x セグメントにコントロールプレーン/ワーカーノードがあり、その上のPodでWordPressが稼働する構成において、(1) 訪問者の実IPアドレスが正しく取得できない、(2) `wp_mail()` によるメール送信が失敗する、という2つの不具合が報告された。
**(1) 実IPアドレス取得の不具合**
原因は2つ複合していた:
- Service`LoadBalancer`/MetalLB想定)はデフォルトの `externalTrafficPolicy: Cluster` のため、kube-proxyが送信元IPをノード内部IPにSNATしてしまい、Nginxの `$remote_addr` が実IPではなくノードIPになっていた。
- 本チャートの `nginx.forwardRealIP`X-Forwarded-Forを信頼するreal_ipモジュール設定)は、Ingress ControllerやCDNなど**XFFヘッダーを付与するリバースプロキシが前段にある場合**にのみ機能する設計だが、このベアメタル構成ではService直下にPodがぶら下がるだけでXFFを付与する層が存在せず、機能していなかった(`trustedProxies``192.168.0.0/16` が含まれるためSNAT後のノードIPを「信頼済みプロキシ」とみなしてしまうが、そのIPがXFFを付与するわけではないので `$real_ip` は結局SNAT後のIPのままになる)。
さらに、`wp-config.php` 生成テンプレート内でPHP側が生のX-Forwarded-Forヘッダーを無条件に信頼してREMOTE_ADDRを上書きする処理があり、Nginxのreal_ip信頼境界を迂回してクライアントがIPを詐称できる状態だった(副次的なセキュリティ上の問題)。
**修正内容**:
- `values.yaml`: `service.externalTrafficPolicy: Local` をデフォルト追加(SNATを回避し実IPをそのまま透過させる。MetalLB L2モード等と組み合わせる想定。ClusterIPでは無視される)。
- `templates/service.yaml`: `externalTrafficPolicy` を条件付きで出力するよう変更。
- `templates/deployment.yaml`: `wp-config.php` 内のPHP側REMOTE_ADDR再判定処理を削除(NginxのfastcgiパラメータでREMOTE_ADDRは既に正しく渡っているため不要かつ危険だった)。
- `values.yaml`/`README.md`: `nginx.forwardRealIP` は本当にXFFを付与するリバースプロキシが前段にある場合のみ有効化する旨を明記。
**(2) メール送信の不具合**
原因: 使用しているAlpineベースのWordPressイメージには、PHPの `mail()``wp_mail()` が内部的に利用)を実際に配送するMTA(sendmail相当)が同梱されておらず、`sendmail_path` の送信先が存在しなかった。
**修正内容**[helmchart/phpfpm](https://git.cafepieters.com/helmchart/phpfpm) チャートと同一の手法を採用。ユーザー指定によりphpfpmの実装パターンをそのまま踏襲):
- `values.yaml``smtp.*` セクションを追加(`enabled`/`host`/`protocol`/`port`/`auth.*`/`from`/`tls.*`)。
- `templates/configmap-smtp.yaml`(新規): `/etc/msmtprc` を生成するConfigMap。
- `templates/secret-smtp.yaml`(新規): SMTPパスワードを格納するSecret。
- `templates/deployment.yaml`: `smtp.enabled: true` の場合のみ、`wordpress` コンテナの起動コマンドをシェルラッパーに変更し、`apk add msmtp ca-certificates``/etc/msmtprc` 配置(`chmod 644`、www-dataから読めるように) → PHPの `sendmail_path``msmtp -t` に向ける `99-smtp.ini` を生成 → `exec php-fpm` という順で起動する。
- `apk add` にrootが必要なため、SMTP有効時のみ既存の `securityContext: runAsUser/runAsGroup: 82` を外している(PHP-FPMワーカー自体はイメージ標準の `www.conf` によりuid82で動作するため、実際のPHPコード実行権限は変わらない)。`smtp.enabled: false`(デフォルト)では従来どおり非rootで起動する。
- msmtpのパスワードはmsmtprcに直書きせず `passwordeval "cat /etc/smtp-secrets/password"` で別ファイル参照(phpfpmの `CHANGELOG-8.5.6-f/g.md` で判明した「Secret/ConfigMapの権限が0600だとwww-dataから読めない」問題を踏まえ、最初から `0644` で実装済み)。
- WordPress本体は `wp_mail()` が自動的に `mail()`/`sendmail_path` を経由するため、phpfpmと異なりPHPコード側の変更(ヘルパークラスの読み込み等)は不要。
**対象ファイル**: `values.yaml`, `templates/service.yaml`, `templates/deployment.yaml`, `templates/configmap-smtp.yaml`(新規), `templates/secret-smtp.yaml`(新規), `README.md`, `Chart.yaml`