# CLAUDE.md — WordPress Helm Chart > **共通ルール(要約)** — 詳細は `P:\Claude\CLAUDE.md`(全体共通)と `P:\Claude\HelmChart\CLAUDE.md`(Helm チャート共通: リリースフロー・ワークフロー・クラスタ構成)を参照。 > 作業前に pull / 機能変更時は README 更新 / 作業単位ごとに commit → push まで / コミットに AI クレジットを付けない / pull で入った変更を revert しない / Helm・PHP はローカル実行不可(Python のみ可)。 ## リポジトリ概要 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:-fpm-alpine`)をemptyDirにコピーして使い捨てで起動し、`wp-content`のみPVCで永続化する(bitnami方式)。PHPの実行環境はこのイメージに依存し、本リポジトリにPHPコードは含まれない。 ## 設計上の注意(このチャート固有) - `templates/service.yaml` には annotations のテンプレート化が存在しないため、kube-vip 用アノテーションは Helm 管理外で手動付与する運用になっている(クラスタ全体の事情は組織 CLAUDE.md「実運用クラスタ構成」を参照)。 - 実 IP 取得(`ingress.yaml` / `nginx.forwardRealIP`)は既存機能で対応済み。Cilium Ingress への移行手順は README に記載。 ## チャート改修履歴 ### 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`