#!/bin/sh set -eu CCR_DATA_DIR="${CCR_DATA_DIR:-/data}" CCR_WEB_HOST="${CCR_WEB_HOST:-127.0.0.1}" CCR_WEB_PORT="${CCR_WEB_PORT:-3459}" CCR_NGINX_PORT="${CCR_NGINX_PORT:-8080}" CCR_GATEWAY_HOST="${CCR_GATEWAY_HOST:-127.0.0.1}" CCR_GATEWAY_PORT="${CCR_GATEWAY_PORT:-3456}" CCR_GATEWAY_CORE_PORT="${CCR_GATEWAY_CORE_PORT:-3457}" CCR_PUBLIC_HOST="${CCR_PUBLIC_HOST:-127.0.0.1}" CCR_PUBLIC_PORT="${CCR_PUBLIC_PORT:-3458}" CCR_PUBLIC_BASE_URL="${CCR_PUBLIC_BASE_URL:-http://${CCR_PUBLIC_HOST}:${CCR_PUBLIC_PORT}}" CCR_NO_GATEWAY="${CCR_NO_GATEWAY:-0}" if [ -z "${CCR_WEB_AUTH_TOKEN:-}" ]; then CCR_WEB_AUTH_TOKEN="$(node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('base64url'))")" fi CCR_WEB_AUTH_TOKEN_QUERY="$(node -e "process.stdout.write(encodeURIComponent(process.argv[1] || ''))" "${CCR_WEB_AUTH_TOKEN}")" export HOME="${CCR_DATA_DIR}" export CCR_DATA_DIR export CCR_GATEWAY_CORE_PORT export CCR_GATEWAY_HOST export CCR_GATEWAY_PORT export CCR_NGINX_PORT export CCR_NO_GATEWAY export CCR_PUBLIC_BASE_URL export CCR_PUBLIC_HOST export CCR_PUBLIC_PORT export CCR_WEB_AUTH_TOKEN export CCR_WEB_AUTH_TOKEN_QUERY export CCR_WEB_HOST export CCR_WEB_PORT CONFIG_DIR="${HOME}/.claude-code-router" CONFIG_FILE="${CONFIG_DIR}/config.json" APP_CONFIG_DB_FILE="${CONFIG_DIR}/config.sqlite" mkdir -p "${CONFIG_DIR}" "${CONFIG_DIR}/app-data" /run/nginx /var/lib/nginx /var/log/nginx if [ "${CCR_DOCKER_INIT_CONFIG:-1}" != "0" ] && [ ! -f "${CONFIG_FILE}" ] && [ ! -f "${APP_CONFIG_DB_FILE}" ]; then node - <<'NODE' const fs = require("node:fs"); const path = require("node:path"); const configDir = path.join(process.env.HOME, ".claude-code-router"); const configFile = path.join(configDir, "config.json"); const gatewayHost = process.env.CCR_GATEWAY_HOST || "0.0.0.0"; const gatewayPort = Number(process.env.CCR_GATEWAY_PORT || "3456"); const gatewayCorePort = Number(process.env.CCR_GATEWAY_CORE_PORT || "3457"); const publicBaseUrl = (process.env.CCR_PUBLIC_BASE_URL || `http://127.0.0.1:${process.env.CCR_PUBLIC_PORT || "3458"}`).replace(/\/+$/, ""); fs.mkdirSync(configDir, { recursive: true, mode: 0o700 }); fs.writeFileSync(configFile, `${JSON.stringify({ HOST: gatewayHost, PORT: gatewayPort, gateway: { coreHost: "127.0.0.1", corePort: gatewayCorePort, enabled: true, host: gatewayHost, port: gatewayPort }, routerEndpoint: publicBaseUrl }, null, 2)}\n`, { mode: 0o600 }); NODE fi if [ "${CCR_DOCKER_SYNC_PUBLIC_ENDPOINT:-1}" != "0" ]; then node - <<'NODE' const fs = require("node:fs"); const path = require("node:path"); const configDir = path.join(process.env.HOME, ".claude-code-router"); const configFile = path.join(configDir, "config.json"); const appConfigDbFile = path.join(configDir, "config.sqlite"); const gatewayHost = process.env.CCR_GATEWAY_HOST || "127.0.0.1"; const gatewayPort = Number(process.env.CCR_GATEWAY_PORT || "3456"); const gatewayCorePort = Number(process.env.CCR_GATEWAY_CORE_PORT || "3457"); const publicBaseUrl = (process.env.CCR_PUBLIC_BASE_URL || `http://127.0.0.1:${process.env.CCR_PUBLIC_PORT || "3458"}`).replace(/\/+$/, ""); function syncConfig(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { return value; } value.HOST = gatewayHost; value.PORT = gatewayPort; value.gateway = { ...(value.gateway && typeof value.gateway === "object" && !Array.isArray(value.gateway) ? value.gateway : {}), coreHost: "127.0.0.1", corePort: gatewayCorePort, enabled: true, host: gatewayHost, port: gatewayPort }; value.routerEndpoint = publicBaseUrl; return value; } function syncJsonFile() { if (!fs.existsSync(configFile)) { return; } const parsed = JSON.parse(fs.readFileSync(configFile, "utf8")); fs.writeFileSync(configFile, `${JSON.stringify(syncConfig(parsed), null, 2)}\n`, { mode: 0o600 }); } function syncSqliteConfig() { if (!fs.existsSync(appConfigDbFile)) { return; } let Database; try { Database = require("better-sqlite3"); } catch { return; } const db = new Database(appConfigDbFile); try { const row = db.prepare("select value_json from app_config where key = ?").get("default"); if (!row?.value_json) { return; } const parsed = JSON.parse(row.value_json); db.prepare("update app_config set value_json = ?, updated_at = ? where key = ?") .run(JSON.stringify(syncConfig(parsed)), new Date().toISOString(), "default"); } finally { db.close(); } } syncJsonFile(); syncSqliteConfig(); NODE fi cat > /etc/nginx/conf.d/default.conf <