#!/bin/bash set -euo pipefail # ================================================================= # Baron SSO 인스턴스 자동 생성 스크립트 (전체 인프라 포함) # ================================================================= if [ "$#" -ne 2 ]; then echo "❌ Usage: $0 [INSTANCE_NAME] [PORT_PREFIX]" exit 1 fi INSTANCE_NAME=$1 PORT_PREFIX=$2 BASE_DIR=$(cd $(dirname $0); pwd) REPO_ROOT=$(cd "${BASE_DIR}/.." && pwd) TARGET_DIR="${TARGET_DIR:-${BASE_DIR}/../instances/${INSTANCE_NAME}}" echo "🚀 Creating instance: ${INSTANCE_NAME} (Port Prefix: ${PORT_PREFIX}xxx)" # 1. 폴더 구조 생성 mkdir -p "${TARGET_DIR}/gateway" mkdir -p "${TARGET_DIR}/config/.generated" mkdir -p "${TARGET_DIR}/ory/init-db" mkdir -p "${TARGET_DIR}/ory/templates/kratos" mkdir -p "${TARGET_DIR}/ory/templates/hydra" mkdir -p "${TARGET_DIR}/ory/templates/keto" mkdir -p "${TARGET_DIR}/ory/templates/oathkeeper" mkdir -p "${TARGET_DIR}/userfront" mkdir -p "${TARGET_DIR}/adminfront" mkdir -p "${TARGET_DIR}/devfront" mkdir -p "${TARGET_DIR}/orgfront" # 2. .env 생성 및 변수 로드 sed "s/{{INSTANCE_NAME}}/${INSTANCE_NAME}/g; s/{{PORT_PREFIX}}/${PORT_PREFIX}/g" \ "${BASE_DIR}/templates/.env.template" > "${TARGET_DIR}/.env" SOURCE_ROOT_ESCAPED=$(printf '%s\n' "$REPO_ROOT" | sed 's/[\/&]/\\&/g') sed -i "s/^SOURCE_ROOT=.*/SOURCE_ROOT=${SOURCE_ROOT_ESCAPED}/" "${TARGET_DIR}/.env" # 생성된 compose 파일을 실행하기 전에 Traefik public network가 있어야 합니다. TRAEFIK_PUBLIC_NETWORK=$(grep "^TRAEFIK_PUBLIC_NETWORK=" "${TARGET_DIR}/.env" | cut -d'=' -f2 | tr -d '\r') TRAEFIK_PUBLIC_NETWORK=${TRAEFIK_PUBLIC_NETWORK:-traefik-public} if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then if ! docker network inspect "$TRAEFIK_PUBLIC_NETWORK" >/dev/null 2>&1; then echo "Creating Docker network ${TRAEFIK_PUBLIC_NETWORK}..." docker network create "$TRAEFIK_PUBLIC_NETWORK" else echo "Docker network ${TRAEFIK_PUBLIC_NETWORK} already exists." fi else echo "⚠️ docker command is unavailable or not accessible; skipping Traefik public network check." fi # 포트 계산 (단순 치환) BACKEND_PORT="${PORT_PREFIX}000" USERFRONT_PORT="${PORT_PREFIX}500" DOMAIN_SUFFIX=$(grep "DOMAIN_SUFFIX=" "${TARGET_DIR}/.env" | cut -d'=' -f2 | tr -d '\r') ADMINFRONT_DOMAIN="${INSTANCE_NAME}-admin.${DOMAIN_SUFFIX}" DEVFRONT_DOMAIN="${INSTANCE_NAME}-dev.${DOMAIN_SUFFIX}" ORGFRONT_DOMAIN="${INSTANCE_NAME}-org.${DOMAIN_SUFFIX}" # 3. Docker Compose & Config 복사 및 치환 cp "${BASE_DIR}/templates/docker-compose.yaml" "${TARGET_DIR}/" # Gateway 및 UserFront Nginx sed "s/{{BACKEND_PORT}}/${BACKEND_PORT}/g" "${BASE_DIR}/templates/gateway/nginx.conf" > "${TARGET_DIR}/gateway/nginx.conf" sed "s/{{BACKEND_PORT}}/${BACKEND_PORT}/g" "${BASE_DIR}/templates/userfront/nginx.conf" > "${TARGET_DIR}/userfront/nginx.conf" # Oathkeeper 규칙 템플릿 sed "s/{{BACKEND_PORT}}/${BACKEND_PORT}/g" "${BASE_DIR}/templates/ory/oathkeeper/rules.json" > "${TARGET_DIR}/ory/templates/oathkeeper/rules.json" cp "${TARGET_DIR}/ory/templates/oathkeeper/rules.json" "${TARGET_DIR}/ory/templates/oathkeeper/rules.stage.json" cp "${TARGET_DIR}/ory/templates/oathkeeper/rules.json" "${TARGET_DIR}/ory/templates/oathkeeper/rules.prod.json" cp "${TARGET_DIR}/ory/templates/oathkeeper/rules.json" "${TARGET_DIR}/ory/templates/oathkeeper/rules.active.json" # Kratos 설정 템플릿 sed "s/{{BACKEND_PORT}}/${BACKEND_PORT}/g; s/{{USERFRONT_PORT}}/${USERFRONT_PORT}/g" \ "${BASE_DIR}/templates/ory/kratos/kratos.yml.template" > "${TARGET_DIR}/ory/templates/kratos/kratos.yml.template" # Vite 설정 sed "s/{{ADMINFRONT_DOMAIN}}/${ADMINFRONT_DOMAIN}/g; s/{{BACKEND_PORT}}/${BACKEND_PORT}/g" \ "${BASE_DIR}/templates/adminfront/vite.config.ts" > "${TARGET_DIR}/adminfront/vite.config.ts" sed "s/{{DEVFRONT_DOMAIN}}/${DEVFRONT_DOMAIN}/g; s/{{BACKEND_PORT}}/${BACKEND_PORT}/g" \ "${BASE_DIR}/templates/devfront/vite.config.ts" > "${TARGET_DIR}/devfront/vite.config.ts" sed "s/{{ORGFRONT_DOMAIN}}/${ORGFRONT_DOMAIN}/g; s/{{BACKEND_PORT}}/${BACKEND_PORT}/g" \ "${BASE_DIR}/templates/orgfront/vite.config.ts" > "${TARGET_DIR}/orgfront/vite.config.ts" # 4. 프론트엔드 auth.ts 주입 (하드코딩된 포트 해결) sed "s/{{USERFRONT_PORT}}/${USERFRONT_PORT}/g; s/{{CLIENT_ID}}/adminfront/g" \ "${BASE_DIR}/templates/auth.template.ts" > "${TARGET_DIR}/adminfront/auth.ts" sed "s/{{USERFRONT_PORT}}/${USERFRONT_PORT}/g; s/{{CLIENT_ID}}/devfront/g" \ "${BASE_DIR}/templates/auth.template.ts" > "${TARGET_DIR}/devfront/auth.ts" sed "s/{{USERFRONT_PORT}}/${USERFRONT_PORT}/g" \ "${BASE_DIR}/templates/orgfront/auth.ts" > "${TARGET_DIR}/orgfront/auth.ts" # 5. Ory template 복사 및 완성 config 렌더링 if [ -d "${BASE_DIR}/../docker/ory/init-db" ]; then cp -n "${BASE_DIR}/../docker/ory/init-db/"* "${TARGET_DIR}/ory/init-db/" 2>/dev/null || true; fi if [ -d "${BASE_DIR}/../docker/ory/kratos" ]; then cp -n "${BASE_DIR}/../docker/ory/kratos/"* "${TARGET_DIR}/ory/templates/kratos/" 2>/dev/null || true; fi if [ -d "${BASE_DIR}/../docker/ory/kratos/courier-templates" ]; then cp -a "${BASE_DIR}/../docker/ory/kratos/courier-templates" "${TARGET_DIR}/ory/templates/kratos/" 2>/dev/null || true; fi if [ -d "${BASE_DIR}/../docker/ory/hydra" ]; then cp -n "${BASE_DIR}/../docker/ory/hydra/"* "${TARGET_DIR}/ory/templates/hydra/" 2>/dev/null || true; fi if [ -d "${BASE_DIR}/../docker/ory/keto" ]; then cp -n "${BASE_DIR}/../docker/ory/keto/"* "${TARGET_DIR}/ory/templates/keto/" 2>/dev/null || true; fi if [ -d "${BASE_DIR}/../docker/ory/oathkeeper" ]; then cp -n "${BASE_DIR}/../docker/ory/oathkeeper/"* "${TARGET_DIR}/ory/templates/oathkeeper/" 2>/dev/null || true; fi ORY_CONFIG_ENV_FILES="${TARGET_DIR}/.env" \ ORY_CONFIG_TEMPLATE_ROOT="${TARGET_DIR}/ory/templates" \ ORY_CONFIG_OUTPUT_DIR="${TARGET_DIR}/config/.generated/ory" \ bash "${BASE_DIR}/../scripts/render_ory_config.sh" # 6. 마무리 chmod 600 "${TARGET_DIR}/.env" echo "--------------------------------------------------" echo "✅ Success! ALL files (Infra/Ory/Apps/FrontConfigs) are ready." echo "📂 Location: ${TARGET_DIR}" echo "🚀 Run: cd ${TARGET_DIR} && docker compose up -d" echo "--------------------------------------------------"