CPA 的一件部屬腳本

週末的狂歡party,奧特曼給了我們的大禮物,這一次我沒跟上,因為一直在折騰CPA,加上又是深夜,忍不住說著了,起床的時候已經人去樓空… 站內有許多大佬給出CPA的詳細部屬的教程,我這邊分享一個奴役AI寫的腳本,把需要的東西放好,一鍵執行,就可以把你的CPA弄好,希望對大家有幫助,如果奧特曼在發免費...
CPA 的一件部屬腳本
CPA 的一件部屬腳本

週末的狂歡party,奧特曼給了我們的大禮物,這一次我沒跟上,因為一直在折騰CPA,加上又是深夜,忍不住說著了,起床的時候已經人去樓空…

站內有許多大佬給出CPA的詳細部屬的教程,我這邊分享一個奴役AI寫的腳本,把需要的東西放好,一鍵執行,就可以把你的CPA弄好,希望對大家有幫助,如果奧特曼在發免費禮物,party狂歡的時候大家也能一同參與

(sh 腳本 改成txt 因為不然不能上船,直接貼出來,上船死活不給)

#!/bin/bash
# ============================================================================
# CLIProxyAPI One-Click Deploy Script
# ============================================================================
# Usage: bash deploy-cpa.sh config.txt
#
# Config file format (one per line):
#   CF_EMAIL=your@email.com
#   CF_API_KEY=your_global_api_key
#   CF_ACCOUNT_ID=your_account_id
#   CF_ZONE_ID=your_zone_id
#   DOMAIN=cpa.yourdomain.com
#   TOKENS_PATH=/path/to/tokens.zip
#   API_KEY=sk-cpa-custom-key          (optional, auto-generated if missing)
#   MGMT_KEY=mgt-cpa-custom-key        (optional, auto-generated if missing)
#   TUNNEL_NAME=cpa-proxy               (optional, defaults to cpa-proxy)
# ============================================================================

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

log()  { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
err()  { echo -e "${RED}[✗]${NC} $1"; exit 1; }
info() { echo -e "${BLUE}[i]${NC} $1"; }

# ============================================================================
# Check arguments
# ============================================================================
if [ -z "$1" ]; then
    echo ""
    echo -e "${CYAN}CLIProxyAPI One-Click Deploy${NC}"
    echo ""
    echo "Usage: bash deploy-cpa.sh <config-file>"
    echo ""
    echo "Create a config file with the following format:"
    echo ""
    echo "  CF_EMAIL=your@email.com"
    echo "  CF_API_KEY=your_global_api_key"
    echo "  CF_ACCOUNT_ID=your_account_id"
    echo "  CF_ZONE_ID=your_zone_id"
    echo "  DOMAIN=cpa.yourdomain.com"
    echo "  TOKENS_PATH=/path/to/tokens.zip"
    echo ""
    echo "Optional:"
    echo "  API_KEY=sk-cpa-custom-key"
    echo "  MGMT_KEY=mgt-cpa-custom-key"
    echo "  TUNNEL_NAME=cpa-proxy"
    echo ""
    exit 1
fi

CONFIG_FILE="$1"
[ ! -f "$CONFIG_FILE" ] && err "Config file not found: $CONFIG_FILE"

# ============================================================================
# Load config
# ============================================================================
info "Loading config from $CONFIG_FILE..."

# Source the config file
set -a
source "$CONFIG_FILE"
set +a

# Validate required fields
[ -z "$CF_EMAIL" ]     && err "CF_EMAIL is required"
[ -z "$CF_API_KEY" ]   && err "CF_API_KEY is required"
[ -z "$CF_ACCOUNT_ID" ] && err "CF_ACCOUNT_ID is required"
[ -z "$CF_ZONE_ID" ]   && err "CF_ZONE_ID is required"
[ -z "$DOMAIN" ]       && err "DOMAIN is required (e.g., cpa.yourdomain.com)"
[ -z "$TOKENS_PATH" ]  && err "TOKENS_PATH is required (path to token zip files)"

# Set defaults
TUNNEL_NAME="${TUNNEL_NAME:-cpa-proxy}"
API_KEY="${API_KEY:-sk-cpa-$(tr -dc 'a-z0-9' </dev/urandom | head -c 32)}"
MGMT_KEY="${MGMT_KEY:-mgt-cpa-$(tr -dc 'a-z0-9' </dev/urandom | head -c 32)}"
INSTALL_DIR="/root/cpa"
AUTH_DIR="/root/.cli-proxy-api"

# Extract subdomain and root domain for DNS
SUBDOMAIN=$(echo "$DOMAIN" | cut -d. -f1)
ROOT_DOMAIN=$(echo "$DOMAIN" | cut -d. -f2-)

log "Config loaded successfully"
info "Domain: $DOMAIN"
info "Tunnel: $TUNNEL_NAME"
info "Tokens: $TOKENS_PATH"

# ============================================================================
# Step 1: System setup
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 1: System Setup ===${NC}"

# Update and install dependencies
apt-get update -qq
apt-get install -y -qq curl unzip python3 jq p7zip-full > /dev/null 2>&1
log "System dependencies installed"

# ============================================================================
# Step 2: Install Docker
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 2: Docker Setup ===${NC}"

if command -v docker &> /dev/null; then
    log "Docker already installed: $(docker --version)"
else
    info "Installing Docker..."
    curl -fsSL https://get.docker.com | sh > /dev/null 2>&1
    log "Docker installed: $(docker --version)"
fi

# ============================================================================
# Step 3: Install cloudflared
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 3: Cloudflared Setup ===${NC}"

if command -v cloudflared &> /dev/null; then
    log "cloudflared already installed: $(cloudflared --version | head -1)"
else
    info "Installing cloudflared..."
    curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
    chmod +x /usr/local/bin/cloudflared
    log "cloudflared installed: $(cloudflared --version | head -1)"
fi

# ============================================================================
# Step 4: Prepare tokens
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 4: Token Import ===${NC}"

mkdir -p "$AUTH_DIR"
mkdir -p "$INSTALL_DIR/auths"

# Handle token files - support zip, json, or directory of zips
if [ -d "$TOKENS_PATH" ]; then
    # Directory - check for JSON files first, then zip files
    JSON_COUNT=$(find "$TOKENS_PATH" -maxdepth 1 -name "*.json" 2>/dev/null | wc -l)
    ZIP_COUNT=$(find "$TOKENS_PATH" -maxdepth 1 -name "*.zip" 2>/dev/null | wc -l)

    if [ "$JSON_COUNT" -gt 0 ]; then
        info "Found $JSON_COUNT JSON files in directory"
        cp "$TOKENS_PATH"/*.json "$INSTALL_DIR/auths/" 2>/dev/null || true
    fi

    if [ "$ZIP_COUNT" -gt 0 ]; then
        info "Found $ZIP_COUNT zip files in directory"
        for zipfile in "$TOKENS_PATH"/*.zip; do
            [ -f "$zipfile" ] && unzip -o "$zipfile" -d "$INSTALL_DIR/auths/" > /dev/null 2>&1
        done
    fi

    # Also check for 7z files
    SEVEN_COUNT=$(find "$TOKENS_PATH" -maxdepth 1 -name "*.7z" 2>/dev/null | wc -l)
    if [ "$SEVEN_COUNT" -gt 0 ]; then
        info "Found $SEVEN_COUNT 7z files in directory"
        for sevenfile in "$TOKENS_PATH"/*.7z; do
            [ -f "$sevenfile" ] && 7z x -y -o"$INSTALL_DIR/auths/" "$sevenfile" > /dev/null 2>&1
        done
    fi

    if [ "$JSON_COUNT" -eq 0 ] && [ "$ZIP_COUNT" -eq 0 ] && [ "$SEVEN_COUNT" -eq 0 ]; then
        err "No .json, .zip, or .7z files found in $TOKENS_PATH"
    fi

elif [ -f "$TOKENS_PATH" ] && [[ "$TOKENS_PATH" == *.zip ]]; then
    # Single zip file
    info "Extracting tokens from zip..."
    unzip -o "$TOKENS_PATH" -d "$INSTALL_DIR/auths/" > /dev/null 2>&1

elif [ -f "$TOKENS_PATH" ] && [[ "$TOKENS_PATH" == *.7z ]]; then
    # Single 7z file
    info "Extracting tokens from 7z..."
    7z x -y -o"$INSTALL_DIR/auths/" "$TOKENS_PATH" > /dev/null 2>&1

elif [ -f "$TOKENS_PATH" ] && [[ "$TOKENS_PATH" == *.json ]]; then
    # Single JSON file
    cp "$TOKENS_PATH" "$INSTALL_DIR/auths/"

else
    err "TOKENS_PATH must be a directory, .zip, .7z, or .json file"
fi

TOKEN_COUNT=$(find "$INSTALL_DIR/auths" -name "*.json" | wc -l)

[ "$TOKEN_COUNT" -eq 0 ] && err "No token files found in $TOKENS_PATH"

# Convert tokens to CLIProxyAPI format
info "Converting $TOKEN_COUNT tokens to CLIProxyAPI format..."

python3 << PYEOF
import json, os, glob, base64, datetime

auth_dir = "$INSTALL_DIR/auths"
files = glob.glob(os.path.join(auth_dir, "*.json"))
converted = 0
errors = 0

for f in files:
    try:
        with open(f) as fh:
            data = json.load(fh)

        # Skip if already in correct format
        if "expired" in data and "last_refresh" in data:
            continue

        # Extract expiry from access_token JWT
        access_token = data.get("access_token", "")
        expire = ""
        account_id = ""

        if access_token and "." in access_token:
            parts = access_token.split(".")
            if len(parts) >= 2:
                payload = parts[1] + "=" * (4 - len(parts[1]) % 4)
                try:
                    claims = json.loads(base64.b64decode(payload))
                    exp_ts = claims.get("exp", 0)
                    if exp_ts:
                        expire = datetime.datetime.fromtimestamp(exp_ts, tz=datetime.timezone.utc).isoformat()
                    auth = claims.get("https://api.openai.com/auth", {})
                    account_id = auth.get("chatgpt_account_id", "")
                except:
                    pass

        # Convert to CLIProxyAPI format
        new_data = {
            "id_token": data.get("id_token", ""),
            "access_token": data.get("access_token", ""),
            "refresh_token": data.get("refresh_token", ""),
            "account_id": account_id,
            "last_refresh": data.get("saved_at", datetime.datetime.now(tz=datetime.timezone.utc).isoformat()),
            "email": data.get("email", ""),
            "type": "codex",
            "expired": expire
        }

        with open(f, 'w') as fh:
            json.dump(new_data, fh)
        converted += 1
    except Exception as e:
        errors += 1

print(f"Converted: {converted}, Errors: {errors}")
PYEOF

log "Token conversion complete: $TOKEN_COUNT tokens ready"

# ============================================================================
# Step 5: Create CLIProxyAPI config
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 5: CLIProxyAPI Configuration ===${NC}"

cat > "$INSTALL_DIR/config.yaml" << EOF
# CLIProxyAPI Configuration - Auto-generated by deploy-cpa.sh
host: "127.0.0.1"
port: 8317

auth-dir: "/root/.cli-proxy-api"

request-retry: 3
max-retry-credentials: 5

quota-exceeded:
  switch-project: true
  switch-preview-model: true

api-keys:
  - "$API_KEY"

remote-management:
  allow-remote: true
  secret-key: "$MGMT_KEY"
  disable-control-panel: false

logging-to-file: true
usage-statistics-enabled: true
logs-max-total-size-mb: 100

# Prevent Cloudflare blocking -> payment_required false positive
disable-cooling: true

# Set Codex CLI User-Agent to bypass Cloudflare
codex-header-defaults:
  user-agent: "codex_cli_rs/0.114.0 (Mac OS 14.2.0; x86_64) vscode/1.111.0"
  beta-features: "multi_agent"

routing:
  strategy: "round-robin"
  session-affinity: true
  session-affinity-ttl: "30m"

ws-auth: false
debug: false
EOF

log "Config created at $INSTALL_DIR/config.yaml"

# ============================================================================
# Step 6: Create docker-compose.yml
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 6: Docker Compose Setup ===${NC}"

cat > "$INSTALL_DIR/docker-compose.yml" << 'EOF'
services:
  cli-proxy-api:
    image: eceasy/cli-proxy-api:latest
    pull_policy: always
    container_name: cli-proxy-api
    network_mode: host
    volumes:
      - ./config.yaml:/CLIProxyAPI/config.yaml
      - ./auths:/root/.cli-proxy-api
      - ./logs:/CLIProxyAPI/logs
    restart: unless-stopped
EOF

log "docker-compose.yml created"

# ============================================================================
# Step 7: Start CLIProxyAPI
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 7: Starting CLIProxyAPI ===${NC}"

cd "$INSTALL_DIR"

# Stop and remove existing container if it exists
docker stop cli-proxy-api 2>/dev/null || true
docker rm cli-proxy-api 2>/dev/null || true

docker compose up -d 2>&1

# Wait for startup
sleep 5

# Verify it's running
if docker ps | grep -q cli-proxy-api; then
    log "CLIProxyAPI is running"
    docker logs cli-proxy-api 2>&1 | tail -3
else
    err "CLIProxyAPI failed to start. Check: docker logs cli-proxy-api"
fi

# ============================================================================
# Step 8: Create Cloudflare Tunnel
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 8: Cloudflare Tunnel Setup ===${NC}"

# Check if tunnel already exists
EXISTING_TUNNEL=$(curl -s "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel?name=${TUNNEL_NAME}" \
  -H "X-Auth-Email: ${CF_EMAIL}" \
  -H "X-Auth-Key: ${CF_API_KEY}" | python3 -c "import sys, json; d=json.load(sys.stdin); t=[x for x in d.get('result',[]) if x['name']=='${TUNNEL_NAME}']; print(t[0]['id'] if t else '')" 2>/dev/null)

if [ -n "$EXISTING_TUNNEL" ]; then
    warn "Tunnel '$TUNNEL_NAME' already exists (ID: $EXISTING_TUNNEL)"
    TUNNEL_ID="$EXISTING_TUNNEL"

    # Get existing token
    TUNNEL_TOKEN=$(curl -s "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/token" \
      -H "X-Auth-Email: ${CF_EMAIL}" \
      -H "X-Auth-Key: ${CF_API_KEY}" | python3 -c "import sys, json; print(json.load(sys.stdin)['result'])" 2>/dev/null)
else
    # Create new tunnel
    info "Creating tunnel '$TUNNEL_NAME'..."
    TUNNEL_RESULT=$(curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel" \
      -H "X-Auth-Email: ${CF_EMAIL}" \
      -H "X-Auth-Key: ${CF_API_KEY}" \
      -H "Content-Type: application/json" \
      -d "{\"name\":\"${TUNNEL_NAME}\"}")

    TUNNEL_ID=$(echo "$TUNNEL_RESULT" | python3 -c "import sys, json; print(json.load(sys.stdin)['result']['id'])" 2>/dev/null)
    TUNNEL_TOKEN=$(echo "$TUNNEL_RESULT" | python3 -c "import sys, json; print(json.load(sys.stdin)['result']['token'])" 2>/dev/null)

    [ -z "$TUNNEL_ID" ] && err "Failed to create tunnel: $TUNNEL_RESULT"
    log "Tunnel created: $TUNNEL_ID"
fi

# Configure tunnel ingress
info "Configuring tunnel routing..."
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/configurations" \
  -H "X-Auth-Email: ${CF_EMAIL}" \
  -H "X-Auth-Key: ${CF_API_KEY}" \
  -H "Content-Type: application/json" \
  -d "{
    \"config\": {
      \"ingress\": [
        {
          \"hostname\": \"${DOMAIN}\",
          \"service\": \"http://localhost:8317\",
          \"originRequest\": { \"noTLSVerify\": true }
        },
        { \"service\": \"http_status:404\" }
      ]
    }
  }" > /dev/null 2>&1

log "Tunnel routing configured"

# ============================================================================
# Step 9: DNS Record
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 9: DNS Record Setup ===${NC}"

# Check if DNS record already exists
EXISTING_DNS=$(curl -s "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records?name=${DOMAIN}" \
  -H "X-Auth-Email: ${CF_EMAIL}" \
  -H "X-Auth-Key: ${CF_API_KEY}" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['result'][0]['id'] if d['result'] else '')" 2>/dev/null)

if [ -n "$EXISTING_DNS" ]; then
    # Update existing record to point to new tunnel
    info "Updating existing DNS record to point to new tunnel..."
    curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records/${EXISTING_DNS}" \
      -H "X-Auth-Email: ${CF_EMAIL}" \
      -H "X-Auth-Key: ${CF_API_KEY}" \
      -H "Content-Type: application/json" \
      -d "{\"content\":\"${TUNNEL_ID}.cfargotunnel.com\"}" > /dev/null 2>&1
    log "DNS record updated: $DOMAIN -> tunnel"
else
    info "Creating CNAME record for $DOMAIN..."
    curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records" \
      -H "X-Auth-Email: ${CF_EMAIL}" \
      -H "X-Auth-Key: ${CF_API_KEY}" \
      -H "Content-Type: application/json" \
      -d "{
        \"type\": \"CNAME\",
        \"name\": \"${SUBDOMAIN}\",
        \"content\": \"${TUNNEL_ID}.cfargotunnel.com\",
        \"proxied\": true,
        \"ttl\": 1
      }" > /dev/null 2>&1
    log "DNS record created: $DOMAIN -> tunnel"
fi

# ============================================================================
# Step 10: WAF Skip Rule
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 10: WAF Configuration ===${NC}"

# Get the firewall custom ruleset
RULESET_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets" \
  -H "X-Auth-Email: ${CF_EMAIL}" \
  -H "X-Auth-Key: ${CF_API_KEY}" | python3 -c "
import sys, json
d = json.load(sys.stdin)
for r in d.get('result', []):
    if r['phase'] == 'http_request_firewall_custom' and r['name'] == 'default':
        print(r['id'])
        break
" 2>/dev/null)

if [ -n "$RULESET_ID" ]; then
    # Get existing rules
    curl -s "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/${RULESET_ID}" \
      -H "X-Auth-Email: ${CF_EMAIL}" \
      -H "X-Auth-Key: ${CF_API_KEY}" > /tmp/cf_ruleset.json

    # Check if rule already exists
    if grep -q "CPA API" /tmp/cf_ruleset.json 2>/dev/null; then
        warn "WAF skip rule already exists"
    else
        # Add skip rule
        python3 << PYEOF
import json
with open('/tmp/cf_ruleset.json') as f:
    data = json.load(f)
rules = data.get('result', {}).get('rules', [])
rules.append({
    'expression': 'starts_with(http.request.uri.path, "/v1/")',
    'description': 'CPA API - Skip WAF',
    'action': 'skip',
    'action_parameters': {'ruleset': 'current'},
    'enabled': True
})
with open('/tmp/cf_update.json', 'w') as f:
    json.dump({'rules': rules}, f)
PYEOF

        curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/${RULESET_ID}" \
          -H "X-Auth-Email: ${CF_EMAIL}" \
          -H "X-Auth-Key: ${CF_API_KEY}" \
          -H "Content-Type: application/json" \
          -d @/tmp/cf_update.json > /dev/null 2>&1
        log "WAF skip rule added for /v1/* paths"
    fi
else
    warn "Could not find WAF ruleset, skipping (you may need to add manually)"
fi

# ============================================================================
# Step 11: Install cloudflared service
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 11: Cloudflared Service ===${NC}"

# Stop existing service if running
systemctl stop cloudflared 2>/dev/null || true

# Uninstall existing service if needed
cloudflared service uninstall 2>/dev/null || true

# Install with token
cloudflared service install "$TUNNEL_TOKEN" 2>&1
systemctl daemon-reload
systemctl start cloudflared
sleep 3

if systemctl is-active --quiet cloudflared; then
    log "cloudflared service is running"
else
    err "cloudflared failed to start. Check: journalctl -u cloudflared"
fi

# ============================================================================
# Step 12: Verify deployment
# ============================================================================
echo ""
echo -e "${CYAN}=== Step 12: Verification ===${NC}"

# Wait for tunnel to connect
sleep 5

# Test local endpoint
LOCAL_TEST=$(curl -s --max-time 10 http://127.0.0.1:8317/v1/models \
  -H "Authorization: Bearer $API_KEY" 2>/dev/null | python3 -c "import sys, json; d=json.load(sys.stdin); print(len(d.get('data',[])))" 2>/dev/null)

if [ "$LOCAL_TEST" -gt 0 ] 2>/dev/null; then
    log "Local API working: $LOCAL_TEST models available"
else
    warn "Local API test failed - tokens may need time to load"
fi

# Test tunnel endpoint
sleep 3
TUNNEL_TEST=$(curl -s --max-time 15 "https://${DOMAIN}/v1/models" \
  -H "Authorization: Bearer $API_KEY" 2>/dev/null | python3 -c "import sys, json; d=json.load(sys.stdin); print(len(d.get('data',[])))" 2>/dev/null)

if [ "$TUNNEL_TEST" -gt 0 ] 2>/dev/null; then
    log "Tunnel API working: $TUNNEL_TEST models available"
else
    warn "Tunnel test failed - DNS may need time to propagate"
fi

# ============================================================================
# Print Summary
# ============================================================================
echo ""
echo ""
echo -e "${GREEN}============================================================================${NC}"
echo -e "${GREEN}                    CLIProxyAPI Deploy Complete!${NC}"
echo -e "${GREEN}============================================================================${NC}"
echo ""
echo -e "${CYAN}API Endpoint:${NC}   https://${DOMAIN}"
echo -e "${CYAN}API Key:${NC}        ${API_KEY}"
echo -e "${CYAN}Management:${NC}     https://${DOMAIN}/management.html"
echo -e "${CYAN}Mgmt Key:${NC}       ${MGMT_KEY}"
echo ""
echo -e "${CYAN}Token Count:${NC}    ${TOKEN_COUNT}"
echo -e "${CYAN}Models:${NC}         gpt-5.4, gpt-5.4-mini, gpt-5.5, codex-auto-review, gpt-image-2"
echo ""
echo -e "${CYAN}Install Dir:${NC}    ${INSTALL_DIR}"
echo -e "${CYAN}Auth Dir:${NC}       ${INSTALL_DIR}/auths"
echo -e "${CYAN}Logs:${NC}           ${INSTALL_DIR}/logs"
echo ""
echo -e "${YELLOW}Test Commands:${NC}"
echo "  curl https://${DOMAIN}/v1/models -H 'Authorization: Bearer ${API_KEY}'"
echo "  curl https://${DOMAIN}/v1/chat/completions -H 'Authorization: Bearer ${API_KEY}' -H 'Content-Type: application/json' -d '{\"model\":\"gpt-5.5\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"max_tokens\":10}'"
echo ""
echo -e "${YELLOW}Management Commands:${NC}"
echo "  docker logs -f cli-proxy-api     # View logs"
echo "  docker restart cli-proxy-api     # Restart"
echo "  cd ${INSTALL_DIR} && docker compose up -d --pull always  # Update"
echo ""
echo -e "${GREEN}============================================================================${NC}"

# Save credentials to file
cat > "$INSTALL_DIR/credentials.txt" << EOF
CLIProxyAPI Credentials
Generated: $(date)

API Endpoint: https://${DOMAIN}
API Key: ${API_KEY}
Management: https://${DOMAIN}/management.html
Management Key: ${MGMT_KEY}

Tunnel ID: ${TUNNEL_ID}
Tunnel Name: ${TUNNEL_NAME}

Install Dir: ${INSTALL_DIR}
Auth Dir: ${INSTALL_DIR}/auths
EOF

log "Credentials saved to $INSTALL_DIR/credentials.txt"

準備工作

  1. Cloudflare 帳號(免費即可)
  2. 一個域名托管在 Cloudflare 上
  3. ChatGPT Token 文件(.zip / .7z / .json)

使用步驟

1. 複製模板

cp cpa-config-template.txt my-config.txt

2. 填入你的資訊(5 個必填項)

nano my-config.txt

3. 一鍵部署

bash deploy-cpa.sh my-config.txt

必填的 5 個欄位

┌───────────────┬─────────────────────┬───────────────────────────────┐
│ 欄位 │ 說明 │ 在哪裡找 │
├───────────────┼─────────────────────┼───────────────────────────────┤
│ CF_EMAIL │ Cloudflare 登錄郵箱 │ 你的帳號 │
├───────────────┼─────────────────────┼───────────────────────────────┤
│ CF_API_KEY │ Global API Key │ CF後台 → 個人資料 → API Token │
├───────────────┼─────────────────────┼───────────────────────────────┤
│ CF_ACCOUNT_ID │ 帳號 ID │ 任意域名首頁右側欄 │
├───────────────┼─────────────────────┼───────────────────────────────┤
│ CF_ZONE_ID │ 域名 Zone ID │ 具體域名首頁右側欄 │
├───────────────┼─────────────────────┼───────────────────────────────┤
│ DOMAIN │ 要用的子域名 │ 例如 cpa.你的域名.com
├───────────────┼─────────────────────┼───────────────────────────────┤
│ TOKENS_PATH │ Token 文件路徑 │ 支持 .zip/.7z/.json/目錄 │
└───────────────┴─────────────────────┴───────────────────────────────┘

部署完成後

腳本會顯示:

把 API 地址和 Key 填進 Cherry Studio 等客戶端即可使用。

4 个帖子 - 4 位参与者

阅读完整话题

来源: LinuxDo 最新话题查看原文