diff --git a/README.md b/README.md index f5894b7..a086c79 100644 --- a/README.md +++ b/README.md @@ -203,20 +203,21 @@ Use this workflow to build locally, then push the same stack to a remote host: ``` (Answer “y” to the rebuild prompt in `setup.sh`, or run the rebuild manually.) -2. **Migrate via SSH** +2. **Package & Push for Remote Deploy** ```bash - ./scripts/migrate-stack.sh \ - --host docker-server \ - --project-dir /home/sam/src/acore-compose + ./deploy.sh --yes \ + --remote-host docker-server \ + --remote-user sam \ + --remote-project-dir /home/sam/src/acore-compose ``` - Adjust `--project-dir` (and `--identity`) to match your environment. The script copies the repo, `storage/`, and the `uprightbass360/...:modules-latest` images to the remote machine. + Add `--remote-identity ~/.ssh/id_ed25519` if you need a non-default SSH key, or `--remote-skip-storage` to avoid syncing the `storage/` directory. 3. **Deploy Remotely** ```bash - ssh docker-server ' - cd /home/sam/src/acore-compose && - ./deploy.sh --skip-rebuild --no-watch - ' +ssh docker-server ' + cd /home/sam/src/acore-compose && + ./deploy.sh --yes --no-watch +' ``` Because the `.env` now points the modules profile at the `uprightbass360/...:modules-latest` tags, the remote compose run uses the build you just migrated—no additional rebuild required. @@ -234,18 +235,18 @@ Use this workflow to build locally, then push the same stack to a remote host: ``` 2. **Migrate Stack to Remote** ```bash - ./scripts/migrate-stack.sh \ - --host docker-server \ - --user sam \ - --project-dir /home/sam/src/acore-compose + ./deploy.sh --yes \ + --remote-host docker-server \ + --remote-user sam \ + --remote-project-dir /home/sam/src/acore-compose ``` - (Exports rebuilt images to `local-storage/images/acore-modules-images.tar`, bundling the `uprightbass360/...:modules-latest` and `uprightbass360/...:Playerbot` tags, then syncs `storage/` unless `--skip-storage` is provided.) + (Under the hood this wraps `scripts/migrate-stack.sh`, exporting module images to `local-storage/images/acore-modules-images.tar` and syncing `storage/` unless `--remote-skip-storage` is provided.) 3. **Deploy on Remote Host** ```bash - ssh docker-server ' - cd /home/sam/src/acore-compose && - ./deploy.sh --skip-rebuild --no-watch - ' +ssh docker-server ' + cd /home/sam/src/acore-compose && + ./deploy.sh --yes --no-watch +' ``` 4. **Verify Services** ```bash @@ -576,6 +577,7 @@ Automated post-deployment tasks including module configuration, service verifica #### `scripts/migrate-stack.sh` - Remote Deployment Migration Migrates locally built images and configuration to remote hosts. +You can call this directly, or use `./deploy.sh --remote-host --remote-user ` which wraps the same workflow. ```bash ./scripts/migrate-stack.sh \ diff --git a/build.sh b/build.sh index 6fe921f..f72ae2b 100755 --- a/build.sh +++ b/build.sh @@ -12,13 +12,6 @@ ASSUME_YES=0 FORCE_REBUILD=0 SKIP_SOURCE_SETUP=0 CUSTOM_SOURCE_PATH="" -MIGRATE_HOST="" -MIGRATE_USER="" -MIGRATE_PORT="22" -MIGRATE_IDENTITY="" -MIGRATE_PROJECT_DIR="" -MIGRATE_SKIP_STORAGE=0 - BLUE='\033[0;34m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m' info(){ printf '%b\n' "${BLUE}ℹ️ $*${NC}"; } ok(){ printf '%b\n' "${GREEN}✅ $*${NC}"; } @@ -42,12 +35,6 @@ Options: --force Force rebuild even if no changes detected --source-path PATH Custom source repository path --skip-source-setup Skip automatic source repository setup - --migrate-host HOST Migrate built images to remote host after build - --migrate-user USER SSH username for remote migration - --migrate-port PORT SSH port for remote migration (default: 22) - --migrate-identity PATH SSH private key for remote migration - --migrate-project-dir DIR Remote project directory (default: auto-detect) - --migrate-skip-storage Skip storage sync during migration -h, --help Show this help This script handles: @@ -56,15 +43,11 @@ This script handles: • AzerothCore compilation with enabled modules • Docker image building and tagging • Build state management -• Optional remote migration Examples: ./build.sh Interactive build ./build.sh --yes Auto-confirm build ./build.sh --force Force rebuild regardless of state - ./build.sh --yes \\ - --migrate-host prod-server \\ - --migrate-user deploy Build and migrate to remote server EOF } @@ -74,12 +57,6 @@ while [[ $# -gt 0 ]]; do --force) FORCE_REBUILD=1; shift;; --source-path) CUSTOM_SOURCE_PATH="$2"; shift 2;; --skip-source-setup) SKIP_SOURCE_SETUP=1; shift;; - --migrate-host) MIGRATE_HOST="$2"; shift 2;; - --migrate-user) MIGRATE_USER="$2"; shift 2;; - --migrate-port) MIGRATE_PORT="$2"; shift 2;; - --migrate-identity) MIGRATE_IDENTITY="$2"; shift 2;; - --migrate-project-dir) MIGRATE_PROJECT_DIR="$2"; shift 2;; - --migrate-skip-storage) MIGRATE_SKIP_STORAGE=1; shift;; -h|--help) usage; exit 0;; *) err "Unknown option: $1"; usage; exit 1;; esac @@ -91,23 +68,6 @@ require_cmd(){ require_cmd docker -# Validate migration parameters if any are provided -if [ -n "$MIGRATE_HOST" ] || [ -n "$MIGRATE_USER" ]; then - if [ -z "$MIGRATE_HOST" ]; then - err "Migration requires --migrate-host to be specified" - exit 1 - fi - if [ -z "$MIGRATE_USER" ]; then - err "Migration requires --migrate-user to be specified" - exit 1 - fi - # Check that migrate-stack.sh exists - if [ ! -f "$ROOT_DIR/scripts/migrate-stack.sh" ]; then - err "Migration script not found: $ROOT_DIR/scripts/migrate-stack.sh" - exit 1 - fi -fi - read_env(){ local key="$1" default="${2:-}" local value="" @@ -494,58 +454,10 @@ tag_module_images(){ fi } -run_migration(){ - if [ -z "$MIGRATE_HOST" ] || [ -z "$MIGRATE_USER" ]; then - return 0 # No migration requested - fi - - info "Starting remote migration to $MIGRATE_USER@$MIGRATE_HOST" - - # Build migrate-stack.sh arguments - local migrate_args=( - --host "$MIGRATE_HOST" - --user "$MIGRATE_USER" - ) - - if [ "$MIGRATE_PORT" != "22" ]; then - migrate_args+=(--port "$MIGRATE_PORT") - fi - - if [ -n "$MIGRATE_IDENTITY" ]; then - migrate_args+=(--identity "$MIGRATE_IDENTITY") - fi - - if [ -n "$MIGRATE_PROJECT_DIR" ]; then - migrate_args+=(--project-dir "$MIGRATE_PROJECT_DIR") - fi - - if [ "$MIGRATE_SKIP_STORAGE" = "1" ]; then - migrate_args+=(--skip-storage) - fi - - if [ "$ASSUME_YES" = "1" ]; then - migrate_args+=(--yes) - fi - - if (cd "$ROOT_DIR" && ./scripts/migrate-stack.sh "${migrate_args[@]}"); then - ok "Migration completed successfully" - echo - info "Remote deployment ready! Run on $MIGRATE_HOST:" - printf ' %bcd %s && ./deploy.sh --no-watch%b\n' "$YELLOW" "${MIGRATE_PROJECT_DIR:-~/acore-compose}" "$NC" - else - warn "Migration failed, but build completed successfully" - return 1 - fi -} - show_build_complete(){ printf '\n%b\n' "${GREEN}🔨 Build Complete! 🔨${NC}" printf '%b\n' "${GREEN}⚒️ Your custom AzerothCore images are ready${NC}" - if [ -n "$MIGRATE_HOST" ]; then - printf '%b\n\n' "${GREEN}🌐 Remote migration completed${NC}" - else - printf '%b\n\n' "${GREEN}🚀 Ready for deployment with ./deploy.sh${NC}" - fi + printf '%b\n\n' "${GREEN}🚀 Ready for deployment with ./deploy.sh${NC}" } main(){ @@ -554,10 +466,10 @@ main(){ local src_dir local rebuild_reasons - info "Step 1/7: Setting up source repository" + info "Step 1/6: Setting up source repository" src_dir="$(ensure_source_repo)" - info "Step 2/7: Detecting build requirements" + info "Step 2/6: Detecting build requirements" readarray -t rebuild_reasons < <(detect_rebuild_reasons) if ! confirm_build "${rebuild_reasons[@]}"; then @@ -565,16 +477,16 @@ main(){ exit 0 fi - info "Step 3/7: Syncing modules to container storage" + info "Step 3/6: Syncing modules to container storage" sync_modules - info "Step 4/7: Staging modules to source directory" + info "Step 4/6: Staging modules to source directory" stage_modules "$src_dir" - info "Step 5/7: Building AzerothCore with modules" + info "Step 5/6: Building AzerothCore with modules" execute_build "$src_dir" - info "Step 6/7: Tagging images for deployment" + info "Step 6/6: Tagging images for deployment" tag_module_images # Clear build sentinel after successful build @@ -588,13 +500,6 @@ main(){ local sentinel="$storage_path/modules/.requires_rebuild" rm -f "$sentinel" 2>/dev/null || true - # Run remote migration if requested - if [ -n "$MIGRATE_HOST" ]; then - echo - info "Step 7/7: Migrating images to remote host" - run_migration - fi - show_build_complete } diff --git a/deploy.sh b/deploy.sh index 5d9328a..6407fe8 100755 --- a/deploy.sh +++ b/deploy.sh @@ -17,6 +17,14 @@ KEEP_RUNNING=0 WORLD_LOG_SINCE="" ASSUME_YES=0 +REMOTE_MODE=0 +REMOTE_HOST="" +REMOTE_USER="" +REMOTE_PORT="22" +REMOTE_IDENTITY="" +REMOTE_PROJECT_DIR="" +REMOTE_SKIP_STORAGE=0 + COMPILE_MODULE_VARS=( MODULE_AOE_LOOT MODULE_LEARN_SPELLS MODULE_FIREWORKS MODULE_INDIVIDUAL_PROGRESSION MODULE_AHBOT MODULE_AUTOBALANCE MODULE_TRANSMOG MODULE_NPC_BUFFER MODULE_DYNAMIC_XP MODULE_SOLO_LFG MODULE_1V1_ARENA MODULE_PHASED_DUELS @@ -62,6 +70,13 @@ Options: --watch-logs Tail worldserver logs even if --no-watch was set earlier --log-tail LINES Override WORLD_LOG_TAIL (number of log lines to show) --once Run status checks once (alias for --no-watch) + --remote Package deployment artifacts for a remote host + --remote-host HOST Remote hostname or IP for migration + --remote-user USER SSH username for remote migration + --remote-port PORT SSH port for remote migration (default: 22) + --remote-identity PATH SSH private key for remote migration + --remote-project-dir DIR Remote project directory (default: ~/acore-compose) + --remote-skip-storage Skip syncing the storage directory during migration -h, --help Show this help This command automates deployment: sync modules, stage the correct compose profile, @@ -80,6 +95,13 @@ while [[ $# -gt 0 ]]; do --no-watch) WATCH_LOGS=0; shift;; --keep-running) KEEP_RUNNING=1; shift;; --yes|-y) ASSUME_YES=1; shift;; + --remote) REMOTE_MODE=1; shift;; + --remote-host) REMOTE_HOST="$2"; REMOTE_MODE=1; shift 2;; + --remote-user) REMOTE_USER="$2"; REMOTE_MODE=1; shift 2;; + --remote-port) REMOTE_PORT="$2"; REMOTE_MODE=1; shift 2;; + --remote-identity) REMOTE_IDENTITY="$2"; REMOTE_MODE=1; shift 2;; + --remote-project-dir) REMOTE_PROJECT_DIR="$2"; REMOTE_MODE=1; shift 2;; + --remote-skip-storage) REMOTE_SKIP_STORAGE=1; REMOTE_MODE=1; shift;; -h|--help) usage; exit 0;; *) err "Unknown option: $1"; usage; exit 1;; esac @@ -91,6 +113,28 @@ require_cmd(){ require_cmd docker +if [ "$REMOTE_MODE" -eq 1 ]; then + if [ -z "$REMOTE_HOST" ]; then + err "Remote deployment requires --remote-host to be specified" + exit 1 + fi + if [ -z "$REMOTE_USER" ]; then + err "Remote deployment requires --remote-user to be specified" + exit 1 + fi + if [ -n "$REMOTE_IDENTITY" ]; then + REMOTE_IDENTITY="${REMOTE_IDENTITY/#\~/$HOME}" + if [ ! -f "$REMOTE_IDENTITY" ]; then + err "Remote identity file not found: $REMOTE_IDENTITY" + exit 1 + fi + fi + if [ ! -f "$ROOT_DIR/scripts/migrate-stack.sh" ]; then + err "Migration script not found: $ROOT_DIR/scripts/migrate-stack.sh" + exit 1 + fi +fi + read_env(){ local key="$1" default="${2:-}" local value="" @@ -302,6 +346,32 @@ determine_profile(){ echo "standard" } +run_remote_migration(){ + local args=(--host "$REMOTE_HOST" --user "$REMOTE_USER") + + if [ -n "$REMOTE_PORT" ] && [ "$REMOTE_PORT" != "22" ]; then + args+=(--port "$REMOTE_PORT") + fi + + if [ -n "$REMOTE_IDENTITY" ]; then + args+=(--identity "$REMOTE_IDENTITY") + fi + + if [ -n "$REMOTE_PROJECT_DIR" ]; then + args+=(--project-dir "$REMOTE_PROJECT_DIR") + fi + + if [ "$REMOTE_SKIP_STORAGE" -eq 1 ]; then + args+=(--skip-storage) + fi + + if [ "$ASSUME_YES" -eq 1 ]; then + args+=(--yes) + fi + + (cd "$ROOT_DIR" && ./scripts/migrate-stack.sh "${args[@]}") +} + stage_runtime(){ local args=(--yes) @@ -383,8 +453,26 @@ main(){ show_deployment_header - local resolved_profile - resolved_profile="$(determine_profile)" + if [ "$REMOTE_MODE" -eq 1 ]; then + local remote_steps=2 + show_step 1 "$remote_steps" "Checking build requirements" + if ! prompt_build_if_needed; then + err "Build required but not completed. Remote deployment cancelled." + exit 1 + fi + + show_step 2 "$remote_steps" "Migrating deployment to $REMOTE_HOST" + if run_remote_migration; then + ok "Remote deployment package prepared for $REMOTE_USER@$REMOTE_HOST." + local remote_dir="${REMOTE_PROJECT_DIR:-~/acore-compose}" + info "Run the following on the remote host to complete deployment:" + printf ' %bcd %s && ./deploy.sh --no-watch%b\n' "$YELLOW" "$remote_dir" "$NC" + exit 0 + else + err "Remote migration failed." + exit 1 + fi + fi show_step 1 4 "Checking build requirements" if ! prompt_build_if_needed; then diff --git a/docker-compose.yml b/docker-compose.yml index a2402c1..b25df7b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -203,7 +203,7 @@ services: profiles: ["client-data"] image: ${AC_CLIENT_DATA_IMAGE} container_name: ac-client-data - user: "0:0" + user: "${CONTAINER_USER}" volumes: - ac-client-data:/azerothcore/data - ${CLIENT_DATA_CACHE_PATH}:/cache @@ -216,14 +216,7 @@ services: - sh - -c - | - if command -v apk >/dev/null 2>&1; then - apk add --no-cache curl unzip wget bash ca-certificates p7zip aria2 jq - elif command -v apt-get >/dev/null 2>&1; then - apt-get update && apt-get install -y --no-install-recommends curl unzip wget bash ca-certificates p7zip-full aria2 jq && rm -rf /var/lib/apt/lists/* - elif command -v yum >/dev/null 2>&1; then - yum install -y curl unzip wget bash ca-certificates p7zip aria2 jq - fi - mkdir -p /cache && chown ${CONTAINER_USER} /cache /azerothcore/data 2>/dev/null || true + mkdir -p /cache if [ -f /tmp/scripts/download-client-data.sh ]; then chmod +x /tmp/scripts/download-client-data.sh 2>/dev/null || true bash /tmp/scripts/download-client-data.sh @@ -238,7 +231,7 @@ services: profiles: ["client-data-bots"] image: ${AC_CLIENT_DATA_IMAGE_PLAYERBOTS} container_name: ac-client-data - user: "0:0" + user: "${CONTAINER_USER}" volumes: - ac-client-data:/azerothcore/data - ${CLIENT_DATA_CACHE_PATH}:/cache @@ -251,14 +244,7 @@ services: - sh - -c - | - if command -v apk >/dev/null 2>&1; then - apk add --no-cache curl unzip wget bash ca-certificates p7zip aria2 jq - elif command -v apt-get >/dev/null 2>&1; then - apt-get update && apt-get install -y --no-install-recommends curl unzip wget bash ca-certificates p7zip-full aria2 jq && rm -rf /var/lib/apt/lists/* - elif command -v yum >/dev/null 2>&1; then - yum install -y curl unzip wget bash ca-certificates p7zip aria2 jq - fi - mkdir -p /cache && chown ${CONTAINER_USER} /cache /azerothcore/data 2>/dev/null || true + mkdir -p /cache if [ -f /tmp/scripts/download-client-data.sh ]; then chmod +x /tmp/scripts/download-client-data.sh 2>/dev/null || true bash /tmp/scripts/download-client-data.sh