code / entrypoint.sh
huanbao's picture
Update entrypoint.sh
5053727 verified
Raw History Blame Contribute Delete
5.2 kB
#!/bin/bash
set -e
# 1. 创建持久化挂载目录
mkdir -p /data/.claude /data/.cloudcli /data/app /data/.taskmaster /data/.codex_data/sessions /data/.codex_data/state
# 2. 软链接常规目录
if [ ! -L "$HOME/.claude" ]; then
rm -rf "$HOME/.claude"
ln -s /data/.claude "$HOME/.claude"
fi
if [ ! -L "$HOME/.claude.json" ]; then
rm -f "$HOME/.claude.json"
ln -s /data/.claude.json "$HOME/.claude.json"
fi
if [ ! -L "$HOME/.cloudcli" ]; then
rm -rf "$HOME/.cloudcli"
ln -s /data/.cloudcli "$HOME/.cloudcli"
fi
if [ ! -L "$HOME/.taskmaster" ]; then
rm -rf "$HOME/.taskmaster"
ln -s /data/.taskmaster "$HOME/.taskmaster"
fi
if [ ! -L "$HOME/app" ]; then
ln -s /data/app "$HOME/app"
fi
# ==================== 针对 .codex 的安全持久化 ====================
# 清理可能存在的旧软链接
[ -L "$HOME/.codex" ] && rm -f "$HOME/.codex"
mkdir -p "$HOME/.codex"
# 1. 软链接 sessions(文本 jsonl 在网络卷完全安全)
[ -d "$HOME/.codex/sessions" ] && [ ! -L "$HOME/.codex/sessions" ] && rm -rf "$HOME/.codex/sessions"
ln -sf /data/.codex_data/sessions "$HOME/.codex/sessions"
# 2. 恢复 SQLite 元数据与索引(从网络卷复制到容器本地磁盘,避免网络锁损坏)
if [ -d "/data/.codex_data/state" ]; then
cp -u /data/.codex_data/state/*.sqlite* "$HOME/.codex/" 2>/dev/null || true
cp -u /data/.codex_data/state/*.jsonl "$HOME/.codex/" 2>/dev/null || true
fi
# 3. 后台定时同步线程:定期将本地生成的 SQLite 和 session_index 备份回 /data
(
while true; do
sleep 60
if [ -d "$HOME/.codex" ]; then
mkdir -p /data/.codex_data/state
# 同步 sqlite 与 index 文件
cp -u "$HOME"/.codex/*.sqlite* /data/.codex_data/state/ 2>/dev/null || true
cp -u "$HOME"/.codex/*.jsonl /data/.codex_data/state/ 2>/dev/null || true
fi
done
) &
# ===================================================================
# 3. 自动生成 Claude Code 配置
mkdir -p "$HOME/.claude"
cat <<EOF > "$HOME/.claude/settings.json"
{
"cleanupPeriodDays": 720,
"env": {
"API_TIMEOUT_MS": "1800000",
"BASH_DEFAULT_TIMEOUT_MS": "1800000",
"BASH_MAX_TIMEOUT_MS": "7200000",
"ANTHROPIC_BASE_URL": "${ANTHROPIC_BASE_URL:-}",
"ANTHROPIC_AUTH_TOKEN": "${ANTHROPIC_AUTH_TOKEN:-}",
"CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"DISABLE_INSTALLATION_CHECKS": "1",
"CLAUDE_CODE_PROXY_RESOLVES_HOSTS": "1",
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1",
"ENABLE_TOOL_SEARCH": "true",
"DISABLE_AUTOUPDATER": "1",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-sonnet-x[1m]",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-sonnet-x[1m]",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-x[1m]",
"ANTHROPIC_MODEL": "claude-sonnet-x[1m]",
"ANTHROPIC_REASONING_MODEL": "claude-sonnet-x[1m]"
},
"permissions": {
"allow": [
"Read",
"Write",
"Edit",
"Bash(*)",
"Glob",
"Grep",
"Agent",
"WebFetch",
"WebSearch",
"NotebookEdit",
"mcp__serper__google_search",
"mcp__tavily__tavily_search",
"mcp__tavily__tavily_research"
],
"deny": [
"Read(.*env*)",
"Read(~/.ssh/*)",
"Bash(rm -rf / *)"
]
},
"skipWebFetchPreflight": true,
"effortLevel": "high",
"autoUpdatesChannel": "latest"
}
EOF
# 4. 自动生成 Codex 配置
CODEX_KEY_RESOLVED="${CODEX_API_KEY:-}"
if [ -z "$CODEX_KEY_RESOLVED" ] && [ -f /data/.codex/gw_token ]; then
CODEX_KEY_RESOLVED="$(head -n 1 /data/.codex/gw_token | tr -d '[:space:]')"
fi
if [ -n "$CODEX_KEY_RESOLVED" ]; then
export OPENAI_API_KEY="$CODEX_KEY_RESOLVED"
fi
cat <<EOF > "$HOME/.codex/config.toml"
cli_auth_credentials_store = "file"
model_provider = "${CODEX_PROVIDER:-custom}"
model = "${CODEX_MODEL:-gpt-5.6-luna}"
sandbox_mode = "danger-full-access"
approval_policy = "never"
[model_providers.custom]
name = "Custom"
base_url = "${CODEX_BASE_URL:-https://cpa.freecode.eu.cc/v1}"
wire_api = "responses"
env_key = "OPENAI_API_KEY"
EOF
cat <<EOF > "$HOME/.codex/auth.json"
{
"OPENAI_API_KEY": "${CODEX_KEY_RESOLVED:-sk-dummy-key}"
}
EOF
# 5. 创建 codex wrapper 兜底(task-master-ai 内置 codex 不在 PATH 中;
# 集成端无环境变量启动时,wrapper 自动从 gw_token 注入凭证)
if [ -w /usr/local/bin ] && [ ! -e /usr/local/bin/codex ] && [ -x /usr/local/lib/node_modules/task-master-ai/node_modules/.bin/codex ]; then
cat <<'WEOF' > /usr/local/bin/codex
#!/bin/bash
if [ -z "$OPENAI_API_KEY" ] && [ -f /data/.codex/gw_token ]; then
export OPENAI_API_KEY="$(head -n 1 /data/.codex/gw_token)"
fi
exec /usr/local/lib/node_modules/task-master-ai/node_modules/.bin/codex "$@"
WEOF
chmod +x /usr/local/bin/codex 2>/dev/null || true
fi
# 6. 全局读写赋权(随后收紧 gw_token 权限,维持 600 保密要求)
chown -R 1000:1000 /data "$HOME" 2>/dev/null || true
chmod -R 777 /data "$HOME" 2>/dev/null || true
[ -f /data/.codex/gw_token ] && chmod 600 /data/.codex/gw_token 2>/dev/null || true
# 7. 切换并启动
mkdir -p /home/node/app 2>/dev/null || true
cd /home/node/app || cd /
exec "$@"