116 lines
5.3 KiB
Bash
Executable File
116 lines
5.3 KiB
Bash
Executable File
#!/bin/sh
|
||
set -eu
|
||
|
||
# Public customer bootstrap. Auth is an external service; no Auth image or
|
||
# private source is downloaded by this script.
|
||
REGISTRY="${OVERCOOKED_REGISTRY:-git.leee.xin/overcooked}"
|
||
VERSION="${OVERCOOKED_VERSION:-latest}"
|
||
ROOT="${OVERCOOKED_ROOT:-/opt/overcooked}"
|
||
SERVER_IP="${OVERCOOKED_SERVER_IP:-}"
|
||
ACTIVATION_CODE="${OVERCOOKED_ACTIVATION_CODE:-}"
|
||
AUTH_URL="${OVERCOOKED_AUTH_URL:-}"
|
||
AUTH_PUBLIC_KEYS="${OVERCOOKED_AUTH_PUBLIC_KEYS:-}"
|
||
|
||
die() { echo "overcooked-install: $*" >&2; exit 1; }
|
||
[ "$(id -u)" = 0 ] || die "请使用 sudo/root 执行"
|
||
command -v docker >/dev/null 2>&1 || die "未找到 Docker Engine"
|
||
docker compose version >/dev/null 2>&1 || die "未找到 Docker Compose v2"
|
||
command -v git >/dev/null 2>&1 || die "未找到 git"
|
||
[ -n "$SERVER_IP" ] || SERVER_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||
[ -n "$SERVER_IP" ] || die "无法识别服务器 IP,请设置 OVERCOOKED_SERVER_IP"
|
||
case "$SERVER_IP" in *[!0-9.]*|*[!0-9]*) die "仅支持 IPv4 地址:$SERVER_IP";; esac
|
||
[ -n "$AUTH_URL" ] || die "请设置 OVERCOOKED_AUTH_URL(Auth 服务地址)"
|
||
[ -n "$AUTH_PUBLIC_KEYS" ] || die "请设置 OVERCOOKED_AUTH_PUBLIC_KEYS(Auth 公钥 JSON)"
|
||
[ -n "$ACTIVATION_CODE" ] || printf '请输入授权码: '; [ -n "$ACTIVATION_CODE" ] || read -r ACTIVATION_CODE
|
||
[ -n "$ACTIVATION_CODE" ] || die "授权码不能为空"
|
||
|
||
install -d -m 700 "$ROOT"
|
||
for repo in OverCooked-S Overcooked-E; do
|
||
if [ ! -d "$ROOT/$repo/.git" ]; then
|
||
git clone --depth 1 "https://git.leee.xin/OverCooked/$repo.git" "$ROOT/$repo"
|
||
else
|
||
git -C "$ROOT/$repo" fetch --depth 1 origin && git -C "$ROOT/$repo" reset --hard FETCH_HEAD
|
||
fi
|
||
done
|
||
install -d -m 700 "$ROOT/config"
|
||
command -v openssl >/dev/null 2>&1 || die "未找到 openssl"
|
||
secret() { openssl rand -hex 32; }
|
||
s_db=$(secret); s_valkey=$(secret); internal=$(secret); access=$(secret); setup=$(secret)
|
||
e_db=$(secret); ticket=$(secret); lease=$(secret); storage=$(secret); plugin=$(secret)
|
||
cat >"$ROOT/production.env" <<EOF
|
||
S_CONTROL_IMAGE=$REGISTRY/overcooked-s-control:$VERSION
|
||
S_WEBUI_IMAGE=$REGISTRY/overcooked-s-webui:$VERSION
|
||
S_POSTGRES_PASSWORD=$s_db
|
||
S_VALKEY_PASSWORD=$s_valkey
|
||
S_INTERNAL_KEY_ID=customer-s
|
||
S_INTERNAL_SHARED_SECRET=$internal
|
||
S_ACCESS_TOKEN_SECRET=$access
|
||
S_SETUP_TOKEN=$setup
|
||
S_E_BASE_URL=http://e-server:8096
|
||
S_E_PUBLIC_URL=http://$SERVER_IP:8096
|
||
S_E_KEY_ID=customer-e
|
||
S_E_INTERNAL_SECRET=$internal
|
||
S_E_ALLOW_INSECURE_HTTP=true
|
||
S_AUTH_BASE_URL=$AUTH_URL
|
||
S_AUTH_ALLOW_INSECURE_HTTP=$(case "$AUTH_URL" in http://*) echo true;; *) echo false;; esac)
|
||
S_AUTH_PUBLIC_KEYS=$AUTH_PUBLIC_KEYS
|
||
S_INSTANCE_ID=s-$(hostname | tr -cd '[:alnum:]' | cut -c1-24)
|
||
S_PUBLIC_HOST=$SERVER_IP
|
||
S_PORTAL_SERVER_URL=http://$SERVER_IP:18080
|
||
S_PORTAL_WEB_CLIENT_URL=http://$SERVER_IP:18083/login
|
||
S_API_PORT_MAPPING=0.0.0.0:18080:8080
|
||
S_WEB_PORT_MAPPING=0.0.0.0:18083:3000
|
||
PRODUCT_E_IMAGE=$REGISTRY/overcooked-e:$VERSION
|
||
PRODUCT_E_INSTANCE_ID=e-$(hostname | tr -cd '[:alnum:]' | cut -c1-24)
|
||
PRODUCT_E_DATABASE_URL=postgres://product_e:$e_db@postgres:5432/product_e?sslmode=disable
|
||
PRODUCT_E_POSTGRES_PASSWORD=$e_db
|
||
PRODUCT_E_VALKEY_PASSWORD=$s_valkey
|
||
PRODUCT_E_CONTROL_PLANE_URL=http://s-control:8080
|
||
PRODUCT_E_CONTROL_PLANE_KEY_ID=customer-s
|
||
PRODUCT_E_CONTROL_PLANE_SHARED_SECRET=$internal
|
||
PRODUCT_E_LICENSE_ENABLED=true
|
||
PRODUCT_E_AUTH_URL=$AUTH_URL
|
||
PRODUCT_E_AUTH_ACTIVATION_CODE=$ACTIVATION_CODE
|
||
PRODUCT_E_AUTH_PUBLIC_KEYS=$AUTH_PUBLIC_KEYS
|
||
PRODUCT_E_PLAYBACK_TICKET_KEY_ID=customer-playback
|
||
PRODUCT_E_PLAYBACK_TICKET_SECRET=$ticket
|
||
PRODUCT_E_PLAYBACK_LEASE_KEY=$lease
|
||
PRODUCT_E_STORAGE_CREDENTIAL_KEY_ID=customer-storage
|
||
PRODUCT_E_STORAGE_CREDENTIAL_KEY=$storage
|
||
PRODUCT_E_PLUGIN_SECRET_KEY_ID=customer-plugin
|
||
PRODUCT_E_PLUGIN_SECRET_KEY=$plugin
|
||
PRODUCT_E_PLUGIN_TRUSTED_PUBLISHERS={}
|
||
EOF
|
||
chmod 600 "$ROOT/production.env"
|
||
|
||
cat >"$ROOT/config/e-server.production.yaml" <<EOF
|
||
service:
|
||
environment: production
|
||
server:
|
||
address: 0.0.0.0:8096
|
||
database:
|
||
url: postgres://product_e:$(grep '^PRODUCT_E_POSTGRES_PASSWORD=' "$ROOT/production.env" | cut -d= -f2)@postgres:5432/product_e?sslmode=disable
|
||
valkey:
|
||
address: valkey:6379
|
||
control_plane:
|
||
base_url: http://s-control:8080
|
||
playback:
|
||
node_id: e-$(hostname | tr -cd '[:alnum:]' | cut -c1-24)
|
||
EOF
|
||
chmod 600 "$ROOT/config/e-server.production.yaml"
|
||
cp "$ROOT/config/e-server.production.yaml" "$ROOT/Overcooked-E/deploy/compose/config/e-server.production.yaml"
|
||
cat >"$ROOT/config/e-public.override.yml" <<'EOF'
|
||
services:
|
||
e-server:
|
||
ports:
|
||
- "0.0.0.0:8096:8096"
|
||
EOF
|
||
docker login "${REGISTRY%%/*}"
|
||
docker network inspect overcooked-control >/dev/null 2>&1 || docker network create overcooked-control >/dev/null
|
||
docker compose -p overcooked-e --env-file "$ROOT/production.env" -f "$ROOT/Overcooked-E/deploy/compose/production.yml" run --rm e-server migrate
|
||
docker compose -p overcooked-e --env-file "$ROOT/production.env" -f "$ROOT/Overcooked-E/deploy/compose/production.yml" -f "$ROOT/Overcooked-E/deploy/compose/control-plane-network.yml" -f "$ROOT/config/e-public.override.yml" up -d --no-build
|
||
docker compose -p overcooked-s --env-file "$ROOT/production.env" -f "$ROOT/OverCooked-S/deploy/s/docker-compose.production.yml" up -d --no-build
|
||
echo "配置已写入 $ROOT/production.env"
|
||
echo "现在启动 S/E;首次启动后打开 http://$SERVER_IP:18083/setup 输入授权码和页面显示的 Setup Token。"
|
||
echo "镜像来源:$REGISTRY(不包含 Auth 镜像)"
|