nginx: [emerg] pcre2_compile() failed: missing closing parenthesis in
"^/s/(?<sid>[a-f0-9]" で gateway が CrashLoopBackOff になっていた。
location ~ の正規表現に含まれる {10} の { } を nginx 設定パーサーがブロック
区切りと解釈していた。nginx は { } ; を含む正規表現のクォートを必須とするため、
files/gateway.conf.template の該当 location をダブルクォートで囲んだ。
envsubst の置換は ${...} 6 変数のみで {10} に影響しないことを確認済み。
9.8 KiB
CLAUDE.md — claude-code Helm Chart
共通ルール(要約) — 詳細は
P:\Claude\CLAUDE.md(全体共通)とP:\Claude\HelmChart\CLAUDE.md(Helm チャート共通: リリースフロー・ワークフロー・Gitea Secrets)を参照。 作業前に pull / 機能変更時は README 更新 / 作業単位ごとに commit → push まで / コミットに AI クレジットを付けない / pull で入った変更を revert しない / Helm はローカル実行不可(Python のみ可)。
リポジトリ概要
Alpine Linux ベースの軽量コンテナで Claude Code をリモート実行 するための Helm チャート。 ブラウザ(PC / スマートフォン)からアクセスし、セッションごとに独立した使い捨て Pod で Git リポジトリ(GitHub / Gitea など互換 Git 全般)をチェックアウト・編集・検証・プッシュする。 一定時間アイドルなセッション Pod は自動破棄される。Raspberry Pi などの ARM ベアメタル運用を想定。
- Gitea リポジトリ:
ssh://git@192.168.9.65/helmchart/claude-code - Helm リポジトリ:
https://git.cafepieters.com/api/packages/helmchart/helm - セッションイメージ:
git.cafepieters.com/helmchart/claude-code/session:<appVersion>(CI で publish)
注意: セッション Pod は Gitea からリポジトリ単体を clone するため、
P:\Claudeの上位階層 CLAUDE.md は届かない。各リポジトリの CLAUDE.md 先頭に「共通ルール(要約)」を置く理由はこれ。
アーキテクチャ(要点)
| コンポーネント | 実体 | 役割 |
|---|---|---|
gateway |
nginxinc/nginx-unprivileged:alpine |
単一入口。認証(token/basic/forward)、WebSocket リバースプロキシ、アクティビティ計測 |
manager |
python:3.x-alpine(標準ライブラリのみ) |
セッション CRUD API、Web UI、アイドル/寿命回収ループ。in-cluster SA で K8s API を直接操作 |
session |
Alpine + node + git + ttyd + claude-code | セッションごとに作られる使い捨て Pod。git clone → claude(ttyd) → claude-verify/claude-push |
reaper CronJob |
manager イメージ --reap-once |
manager 障害時の保険となる孤児掃除 |
- 制御プレーンはリリース NS、セッション Pod は専用 NS(
sessionsNamespace.name)に分離。 - manager の RBAC はセッション NS の
pods/servicesに限定した Role のみ(ClusterRole 不使用)。 - セッション Pod は API サーバー到達不可(
automountServiceAccountToken: false)、 非 root /readOnlyRootFilesystem/ drop ALL caps / seccomp RuntimeDefault、 egress は DNS + git ホスト +api.anthropic.comのみ(NetworkPolicy)。 - ファイル実体は
files/(.Files.Getで ConfigMap 化):manager.py/session-entrypoint.sh/gateway.conf.template/gateway-entrypoint.sh/Dockerfile.session。
README 更新時の追加事項
- values の新設キー、挙動変更、セキュリティ影響は README の該当セクションと values リファレンス表へ反映する。
- 手動リリース(
-a等)時は対応するCHANGELOG-<version>.mdを追加し、README の「バージョン履歴」にも 1 行追加する(このリポジトリの慣行)。
リリースフロー(組織ルールとの差分)
- バージョン番号:
Chart.yamlのversion/appVersionは 主アプリ = Claude Code CLI(@anthropic-ai/claude-codeの npm 最新版)と同一にする。 - ワークフロー(3 本)
helm-release.yaml—mainへの push で発火。helm lintの後、Chart.yamlの version が 未リリース(Gitea リリース・Package Registry 双方に存在しない)なら タグ + Gitea リリース + チャート publish。リリース済みなら lint のみで終了(再 publish しない)。image-update-and-release.yaml— 毎週月曜 3:00 JST。npm の Claude Code 最新版と base image(nginx / python)の最新 Alpine タグを確認。Claude Code 更新時はvalues.yaml/Chart.yaml/ README 履歴を更新しコミット → タグ + リリース + publish。 base image のみ更新時はvalues.yamlを更新してコミットのみ(リリースなし)。session-image.yaml—files/Dockerfile.session等の変更、または上記によるChart.yaml更新で発火。セッションイメージをlinux/amd64,linux/arm64でビルドして Gitea Container Registry(helmchart/claude-code/session:<appVersion>+latest)へ push。
- 手動リリース(臨時): 例
2.1.259→2.1.259-a→2.1.259-b。
改修履歴
gateway nginx クラッシュループ修正(location 正規表現のクォート)(2026-09-08, v2.1.263-c)
症状: gateway コンテナが起動直後に
nginx: [emerg] pcre2_compile() failed: missing closing parenthesis in "^/s/(?<sid>[a-f0-9]"
で終了し、CrashLoopBackOff。
原因: files/gateway.conf.template の
location ~ ^/s/(?<sid>[a-f0-9]{10})(?<rest>/.*)?$ { ... } で、正規表現中の {10} の
{ } を nginx の設定パーサーがブロック区切りと解釈し、location の regex が
^/s/(?<sid>[a-f0-9] で切れていた(nginx は { } ; を含む正規表現のクォートを必須とする)。
修正内容: location ~ "^/s/(?<sid>[a-f0-9]{10})(?<rest>/.*)?$" { ... } と
正規表現全体をダブルクォートで囲んだ。envsubst の対象は ${...} の 6 変数のみで
{10} には影響しないことを確認済み。
対象ファイル: files/gateway.conf.template, README.md, Chart.yaml, CHANGELOG-2.1.263-c.md
認証情報の credentials モード + トークン自動リフレッシュ(2026-09-08, v2.1.263-b)
背景: サブスクリプションのアクセストークンは定期的に失効・ローテーションする。単発
トークン注入では失効のたびに helm upgrade が必要だった。
症状: あわせて、一部の Helm バージョンで values.schema.json の
$schema: https://json-schema.org/draft-07/schema# が
no schema with key or ref ... エラーになる不具合。
修正内容:
anthropic.authMode: credentials(新既定):~/.claude/.credentials.json全体を Secret に 格納 →(a)セッション Pod にファイルとしてマウントし$HOME/.claudeへコピー、セッション内claudeがrefreshTokenで自己更新。(b)anthropic.refresherCronJob (files/token-refresher.py、専用 SA +resourceNames限定 Role で該当 Secret の get/patch のみ) がクラスタ内でaccessTokenを定期更新し Secret を書き戻す。tokenUrl/clientIdは Claude Code CLI の非公式値で values 上書き可。manager.pyのbuild_pod: credentials モードはenvFromを使わずファイルマウント +SEED_CREDENTIALS_FILEenv。apiKey/oauth は従来どおりenvFrom。- Secret に
helm.sh/resource-policy: keep(credentials 時)。 values.schema.jsonの$schema行を削除(他チャートと同じ。Helm は draft-07 で検証)。
対象ファイル: values.yaml, values.schema.json, templates/secret-anthropic.yaml,
templates/deployment.yaml, templates/configmap-manager.yaml, templates/token-refresher.yaml(新規),
templates/NOTES.txt, files/manager.py, files/session-entrypoint.sh,
files/token-refresher.py(新規), examples/loadbalancer-oauth.values.yaml, README.md,
Chart.yaml, CHANGELOG-2.1.263-b.md
Service の LoadBalancer 対応 + サブスクリプション認証手順の明文化(2026-09-08, v2.1.263-a)
背景: Ingress を張らずに、ローカルネットワークの LB(kube-vip 等)から払い出した IP で 管理画面へアクセスしたい、という運用要望。あわせて「Claude の API 課金を使わず、ローカルの Claude Code と同様にサブスクリプションで使いたい」という確認があった。
修正内容:
templates/service.yamlを書き換え、service.type: LoadBalancerを既定化。service.annotations(kube-vip のkube-vip.io/loadbalancerIPs/vipHost等)、loadBalancerIP/loadBalancerClass/loadBalancerSourceRanges/externalTrafficPolicy/nodePort/labelsを追加。Ingress 機能は変更なし(併用可)。values.yamlのservice:ブロック拡張、values.schema.jsonに対応プロパティ追加。templates/NOTES.txtに LoadBalancer の EXTERNAL-IP 案内を追加。examples/loadbalancer-oauth.values.yamlを追加(Ingress 無効 + LB + source range +authMode: oauth)。- README に「Claude 認証(API 課金なし / サブスクリプション)」「管理画面へのアクセス
(LoadBalancer / Ingress)」セクションを追加。サブスクリプション認証は
claude setup-token→anthropic.authMode: oauth(CLAUDE_CODE_OAUTH_TOKENを セッション Pod に注入)で、ローカル実行の Claude Code と同一挙動。
対象ファイル: templates/service.yaml, values.yaml, values.schema.json,
templates/NOTES.txt, examples/loadbalancer-oauth.values.yaml, README.md, Chart.yaml,
CHANGELOG-2.1.263-a.md
初版(2026-09-03, v2.1.259)
チャート新規作成。gateway + manager + 使い捨て session Pod + reaper CronJob の構成で、 ブラウザからの Claude Code リモート実行、GitHub/Gitea 両対応、アイドル自動破棄、 NetworkPolicy / RBAC 最小化 / restricted PodSecurity を実装。
対象ファイル: 全ファイル(初期コミット)