gateway(nginx) + manager(python 標準ライブラリ) + セッションごとの使い捨て Pod + reaper CronJob の構成。ブラウザ(PC/スマホ)からアクセスし、セッション単位で 独立した Alpine コンテナに Git リポジトリ(GitHub/Gitea など)をチェックアウトして 編集・検証・プッシュする。無操作が続いたセッションは Pod ごと自動破棄。 - セキュリティ: セッション NS 分離 / restricted PodSecurity / RBAC はセッション NS の pods,services のみの Role / セッション Pod は SA トークン非マウント・非 root・ readOnlyRootFilesystem・drop ALL caps・seccomp / NetworkPolicy で egress を DNS+HTTPS+SSH に限定 / Git ホスト allow-list / ResourceQuota+LimitRange - ライフサイクル: idleTimeout(Pod 内ウォッチドッグ + manager 回収) / maxLifetime (activeDeadlineSeconds) / maxSessions / 予備の孤児掃除 CronJob - 認証: token(既定) / basic / forward(外部SSO) / none。WebSocket は Cookie トークン - Claude 認証: ANTHROPIC_API_KEY または CLAUDE_CODE_OAUTH_TOKEN - CI: helm-release.yaml(未リリース版のみ tag+release+publish) / image-update-and-release.yaml(週次 npm 追従) / session-image.yaml(multi-arch build) - files/ 実体を .Files.Get で ConfigMap 化。helm lint / template 検証済み
69 lines
2.3 KiB
Bash
69 lines
2.3 KiB
Bash
#!/bin/sh
|
||
# claude-code gateway 起動スクリプト
|
||
# - /etc/resolv.conf から nginx 用 resolver を導出
|
||
# - auth.mode に応じて認証インクルードを生成
|
||
# - envsubst で nginx.conf を展開して起動
|
||
set -eu
|
||
|
||
TPL="/etc/gateway/gateway.conf.template"
|
||
OUT_DIR="/tmp/nginx"
|
||
mkdir -p "$OUT_DIR/body" "$OUT_DIR/proxy" "$OUT_DIR/fastcgi" "$OUT_DIR/uwsgi" "$OUT_DIR/scgi"
|
||
|
||
: "${GATEWAY_PORT:=8080}"
|
||
: "${MANAGER_PORT:=8081}"
|
||
: "${TTYD_PORT:=7681}"
|
||
: "${SESSIONS_NS:=default}"
|
||
: "${AUTH_MODE:=token}"
|
||
: "${NGINX_ERROR_LEVEL:=warn}"
|
||
|
||
# ---- resolver(CoreDNS)を resolv.conf から取得 ----
|
||
NGINX_RESOLVER="$(awk '/^nameserver/ { print $2; exit }' /etc/resolv.conf 2>/dev/null || true)"
|
||
[ -n "$NGINX_RESOLVER" ] || NGINX_RESOLVER="kube-dns.kube-system.svc.cluster.local"
|
||
export NGINX_RESOLVER
|
||
|
||
export GATEWAY_PORT MANAGER_PORT TTYD_PORT SESSIONS_NS NGINX_ERROR_LEVEL
|
||
|
||
# ---- 認証インクルードの生成 ----
|
||
: > "$OUT_DIR/auth_basic.conf"
|
||
: > "$OUT_DIR/auth_request.conf"
|
||
: > "$OUT_DIR/auth_backend.conf"
|
||
|
||
case "$AUTH_MODE" in
|
||
token)
|
||
echo 'auth_request /_auth;' > "$OUT_DIR/auth_request.conf"
|
||
echo "proxy_pass http://127.0.0.1:${MANAGER_PORT}/auth;" > "$OUT_DIR/auth_backend.conf"
|
||
;;
|
||
forward)
|
||
if [ -z "${AUTH_FORWARD_URL:-}" ]; then
|
||
echo "AUTH_MODE=forward だが AUTH_FORWARD_URL が空です" >&2; exit 1
|
||
fi
|
||
echo 'auth_request /_auth;' > "$OUT_DIR/auth_request.conf"
|
||
{
|
||
echo "proxy_pass ${AUTH_FORWARD_URL};"
|
||
echo 'proxy_set_header X-Original-URL $scheme://$http_host$request_uri;'
|
||
} > "$OUT_DIR/auth_backend.conf"
|
||
;;
|
||
basic)
|
||
if [ ! -r /etc/gateway-secret/htpasswd ]; then
|
||
echo "AUTH_MODE=basic だが htpasswd がマウントされていません" >&2; exit 1
|
||
fi
|
||
{
|
||
echo 'auth_basic "claude-code";'
|
||
echo 'auth_basic_user_file /etc/gateway-secret/htpasswd;'
|
||
} > "$OUT_DIR/auth_basic.conf"
|
||
;;
|
||
none)
|
||
echo "WARNING: AUTH_MODE=none — 認証なしで公開されます" >&2
|
||
;;
|
||
*)
|
||
echo "未知の AUTH_MODE: $AUTH_MODE" >&2; exit 1
|
||
;;
|
||
esac
|
||
|
||
# ---- nginx.conf 展開 ----
|
||
envsubst '${GATEWAY_PORT} ${MANAGER_PORT} ${TTYD_PORT} ${SESSIONS_NS} ${NGINX_RESOLVER} ${NGINX_ERROR_LEVEL}' \
|
||
< "$TPL" > "$OUT_DIR/nginx.conf"
|
||
|
||
echo "[gateway] auth_mode=$AUTH_MODE resolver=$NGINX_RESOLVER sessions_ns=$SESSIONS_NS"
|
||
exec nginx -c "$OUT_DIR/nginx.conf" -g 'daemon off;'
|