#!/bin/bash # This script is used to clone a project from a remote server # and perform full project setup including Docker, environment, # SSH keys, and database synchronization. # Called by sync-project.sh with --git flag. # Get current script real directory (follow symlinks) SCRIPT_PATH="$(realpath "$0")" SCRIPT_DIR="$(dirname "$SCRIPT_PATH")" # Source shared variables source "$SCRIPT_DIR/shared.sh" # Arguments: SERVER_HOST SSH_PASSWORD SERVER_PROJECT_PATH LOCAL_FOLDER SERVER_HOST="$1" SSH_PASSWORD="$2" SERVER_PROJECT_PATH="$3" LOCAL_FOLDER="$4" # Validate arguments if [ -z "$SERVER_HOST" ] || [ -z "$SSH_PASSWORD" ] || [ -z "$SERVER_PROJECT_PATH" ] || [ -z "$LOCAL_FOLDER" ]; then echo -e "${RED}Usage: sync-git-project.sh SERVER_HOST SSH_PASSWORD SERVER_PROJECT_PATH LOCAL_FOLDER${NC}" exit 1 fi # Extract username and host from SERVER_HOST USERNAME="${SERVER_HOST%@*}" HOST="${SERVER_HOST#*@}" # ============================================================ # STEP 1: Clone Fork # ============================================================ echo -e "${BLUE}=== Step 1: Cloning Repository ===${NC}" GIT_SSH_COMMAND="sshpass -p '${SSH_PASSWORD}' ssh $SSH_OPTS" \ git clone ${SERVER_HOST}:${SERVER_PROJECT_PATH} "${LOCAL_FOLDER}" if [ $? -ne 0 ]; then echo -e "${RED}Failed to clone repository${NC}" echo -e "${YELLOW}Check that:${NC}" echo " - SSH credentials are correct" echo " - Repository exists at ${SERVER_PROJECT_PATH}" echo " - You have access to the server" exit 1 fi echo -e "${GREEN}Repository cloned successfully${NC}" # Change into project directory cd "${LOCAL_FOLDER}" # Check for .npmrc if [ ! -f ".npmrc" ]; then pause_for_user ".npmrc file not found! Please add .npmrc file to the project root before continuing." fi echo -e "${GREEN}Step 1 complete${NC}" # ============================================================ # STEP 2: Copy Docker Env File # ============================================================ echo -e "${BLUE}=== Step 2: Copying Docker Env File ===${NC}" if [ -f ".docker/config/.env.local" ]; then cp ".docker/config/.env.local" ".env" echo -e "${GREEN}.env copied from .docker/config/.env.local${NC}" else echo -e "${RED}.docker/config/.env.local not found!${NC}" pause_for_user "Please ensure .docker/config/.env.local exists before continuing." # Re-check after user resolves if [ -f ".docker/config/.env.local" ]; then cp ".docker/config/.env.local" ".env" echo -e "${GREEN}.env copied from .docker/config/.env.local${NC}" else echo -e "${RED}Still no .docker/config/.env.local - continuing without it${NC}" fi fi echo -e "${GREEN}Step 2 complete${NC}" # ============================================================ # STEP 3: Clean Docker Volumes # ============================================================ echo -e "${BLUE}=== Step 3: Cleaning Docker Volumes ===${NC}" echo "Stopping all containers..." docker stop $(docker ps -aq) 2>/dev/null || true echo "Removing all containers..." docker rm $(docker ps -aq) 2>/dev/null || true echo "Removing all volumes..." docker volume rm $(docker volume ls -q) 2>/dev/null || true echo -e "${GREEN}Docker volumes cleaned${NC}" echo -e "${GREEN}Step 3 complete${NC}" # ============================================================ # STEP 4: Run docker-setup.sh # ============================================================ echo -e "${BLUE}=== Step 4: Running docker-setup.sh ===${NC}" if [ -f "docker-setup.sh" ]; then echo "Running docker-setup.sh..." sh docker-setup.sh if [ $? -ne 0 ]; then echo -e "${YELLOW}docker-setup.sh exited with non-zero status${NC}" pause_for_user "Please check docker-setup.sh output and resolve any issues." else echo -e "${GREEN}docker-setup.sh completed successfully${NC}" fi else echo -e "${YELLOW}docker-setup.sh not found in project!${NC}" pause_for_user "No docker-setup.sh found. Please set up Docker manually if needed." fi echo -e "${GREEN}Step 4 complete${NC}" # ============================================================ # STEP 5: Copy Server .env # ============================================================ echo -e "${BLUE}=== Step 5: Copying Server .env ===${NC}" sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS ${SERVER_HOST}:${SERVER_PROJECT_PATH}/.env .server.env if [ $? -ne 0 ]; then echo -e "${RED}Failed to copy server .env file${NC}" pause_for_user "Please ensure .env exists on server at ${SERVER_PROJECT_PATH}/.env" # Retry after user resolves sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS ${SERVER_HOST}:${SERVER_PROJECT_PATH}/.env .server.env if [ $? -ne 0 ]; then echo -e "${RED}Still cannot copy server .env - continuing without it${NC}" fi fi if [ -f ".server.env" ]; then git update-index --assume-unchanged .server.env 2>/dev/null || true echo -e "${GREEN}Server .env copied to .server.env and marked as assume-unchanged${NC}" fi echo -e "${GREEN}Step 5 complete${NC}" # ============================================================ # STEP 6: Modify Local .env # ============================================================ echo -e "${BLUE}=== Step 6: Modifying Local .env ===${NC}" if [ -f ".server.env" ] && [ -f ".env" ]; then # Extract values from server env APP_NAME=$(get_env_value ".server.env" "APP_NAME") APP_KEY=$(get_env_value ".server.env" "APP_KEY") if [ -n "$APP_NAME" ]; then set_env_value ".env" "APP_NAME" "$APP_NAME" echo -e "${GREEN}Set APP_NAME=${APP_NAME}${NC}" else echo -e "${YELLOW}APP_NAME not found in .server.env${NC}" fi if [ -n "$APP_KEY" ]; then set_env_value ".env" "APP_KEY" "$APP_KEY" echo -e "${GREEN}Set APP_KEY${NC}" else echo -e "${YELLOW}APP_KEY not found in .server.env${NC}" fi else echo -e "${YELLOW}Skipping .env modification - missing .server.env or .env${NC}" fi echo -e "${GREEN}Step 6 complete${NC}" # ============================================================ # STEP 7: Create .env.prod.local # ============================================================ echo -e "${BLUE}=== Step 7: Creating .env.prod.local ===${NC}" if [ -f ".server.env" ]; then # Extract database credentials from server env DB_DATABASE=$(get_env_value ".server.env" "DB_DATABASE") DB_USERNAME=$(get_env_value ".server.env" "DB_USERNAME") DB_PASSWORD=$(get_env_value ".server.env" "DB_PASSWORD") cat > .env.prod.local << EOF PROD_HOST="${HOST}" PROD_USER="${USERNAME}" PROD_DB_NAME="${DB_DATABASE}" PROD_DB_USER="${DB_USERNAME}" PROD_DB_PASS="${DB_PASSWORD}" EOF echo -e "${GREEN}.env.prod.local created with production credentials${NC}" else echo -e "${YELLOW}Skipping .env.prod.local creation - .server.env not found${NC}" fi echo -e "${GREEN}Step 7 complete${NC}" # ============================================================ # STEP 8: Add Helper Scripts # ============================================================ echo -e "${BLUE}=== Step 8: Adding Helper Scripts ===${NC}" # Define scripts to generate scripts=("ssh.sh") for script in "${scripts[@]}"; do # Create script with variables header cat > "${script}" << EOF #!/bin/bash set -e # Configuration SERVER_USER="${USERNAME}" SERVER_HOST="${HOST}" SERVER_PASSWORD="${SSH_PASSWORD}" SERVER_PATH="${SERVER_PROJECT_PATH}/" REMOTE_PROGRESS=".remote-in-progress" EOF # Append the template content cat "${SCRIPT_DIR}/scripts/${script}" >> "${script}" # Make executable chmod +x "${script}" echo -e "${GREEN}${script} created successfully${NC}" # Add to .gitignore add_to_gitignore "${script}" done echo -e "${GREEN}Step 8 complete${NC}" # ============================================================ # STEP 9: Upload lazygit # ============================================================ echo -e "${BLUE}=== Step 9: Uploading lazygit ===${NC}" sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS "${SCRIPT_DIR}/lazygit" ${SERVER_HOST}:${SERVER_PROJECT_PATH} if [ $? -ne 0 ]; then echo -e "${RED}Failed to upload lazygit${NC}" pause_for_user "Please check server connectivity and permissions." else echo -e "${GREEN}lazygit uploaded successfully${NC}" # Mark lazygit as assume-unchanged on server echo "Marking lazygit as assume-unchanged on server..." sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \ "cd ${SERVER_PROJECT_PATH} && git update-index --assume-unchanged lazygit" # Pull to get lazygit locally, then mark as assume-unchanged echo "Syncing and marking lazygit as assume-unchanged locally..." GIT_SSH_COMMAND="sshpass -p '${SSH_PASSWORD}' ssh $SSH_OPTS" git pull git update-index --assume-unchanged lazygit echo -e "${GREEN}lazygit configured successfully${NC}" fi echo -e "${GREEN}Step 9 complete${NC}" # ============================================================ # STEP 10: SSH Key Management # ============================================================ echo -e "${BLUE}=== Step 10: SSH Key Management ===${NC}" # Check server state for SSH keys HAS_PRIVATE=$(sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "test -f ~/.ssh/id_rsa && echo 'yes' || echo 'no'") HAS_PUBLIC=$(sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "test -f ~/.ssh/id_rsa.pub && echo 'yes' || echo 'no'") echo "Server SSH key state: private=$HAS_PRIVATE, public=$HAS_PUBLIC" if [ "$HAS_PRIVATE" = "no" ] && [ "$HAS_PUBLIC" = "yes" ]; then # Case A: Server has ONLY public key (no private) echo -e "${YELLOW}Case A: Server has only public key - generating new keypair${NC}" # Generate new keypair locally ssh-keygen -t rsa -b 4096 -f staging.key -N "" -q # Upload both keys to server sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key ${SERVER_HOST}:~/.ssh/id_rsa sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key.pub ${SERVER_HOST}:~/.ssh/id_rsa.pub # Set correct permissions on server sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "chmod 600 ~/.ssh/id_rsa && chmod 644 ~/.ssh/id_rsa.pub" # Add public key to authorized_keys sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \ "cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" # Clean up local public key rm -f staging.key.pub echo -e "${GREEN}New keypair generated and uploaded to server${NC}" elif [ "$HAS_PRIVATE" = "yes" ] && [ "$HAS_PUBLIC" = "yes" ]; then # Case B: Server has BOTH keys echo -e "${YELLOW}Case B: Server has both keys - downloading private key${NC}" # Check if public key is in authorized_keys IN_AUTH=$(sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \ "grep -qf ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys 2>/dev/null && echo 'yes' || echo 'no'") if [ "$IN_AUTH" = "no" ]; then echo "Adding public key to authorized_keys..." sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \ "cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" fi # Download private key sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS ${SERVER_HOST}:~/.ssh/id_rsa staging.key chmod 600 staging.key echo -e "${GREEN}Private key downloaded as staging.key${NC}" else # Case C: Server has NEITHER key (or only private, which is unusual) echo -e "${YELLOW}Case C: Server missing keys - generating new keypair${NC}" # Generate new keypair locally ssh-keygen -t rsa -b 4096 -f staging.key -N "" -q # Create .ssh directory on server if needed sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "mkdir -p ~/.ssh && chmod 700 ~/.ssh" # Upload both keys to server sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key ${SERVER_HOST}:~/.ssh/id_rsa sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key.pub ${SERVER_HOST}:~/.ssh/id_rsa.pub # Set correct permissions on server sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "chmod 600 ~/.ssh/id_rsa && chmod 644 ~/.ssh/id_rsa.pub" # Add public key to authorized_keys (create if doesn't exist) sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \ "cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" # Clean up local public key rm -f staging.key.pub echo -e "${GREEN}New keypair generated and uploaded to server${NC}" fi # Add staging.key to .gitignore and mark as assume-unchanged if [ -f "staging.key" ]; then add_to_gitignore "staging.key" git update-index --assume-unchanged staging.key 2>/dev/null || true echo -e "${GREEN}staging.key marked as assume-unchanged${NC}" fi echo -e "${GREEN}Step 10 complete${NC}" # ============================================================ # STEP 11: SSH-Add # ============================================================ echo -e "${BLUE}=== Step 11: Adding SSH Key to Agent ===${NC}" if [ -f "staging.key" ]; then ssh-add ./staging.key 2>/dev/null if [ $? -ne 0 ]; then echo -e "${YELLOW}Failed to add staging.key to SSH agent${NC}" echo "This may happen if ssh-agent is not running." echo "You can start it with: eval \$(ssh-agent -s)" echo "Then run: ssh-add ./staging.key" pause_for_user "Please ensure SSH agent is running and add the key manually if needed." else echo -e "${GREEN}staging.key added to SSH agent${NC}" fi else echo -e "${YELLOW}staging.key not found - skipping ssh-add${NC}" fi echo -e "${GREEN}Step 11 complete${NC}" # ============================================================ # STEP 12: Database Setup # ============================================================ echo -e "${BLUE}=== Step 12: Database Setup ===${NC}" # Wipe local database echo "Wiping local database..." docker exec mtc-pharmacy-web php artisan db:wipe if [ $? -ne 0 ]; then echo -e "${YELLOW}Failed to wipe database${NC}" echo "This may happen if Docker container is not running." pause_for_user "Please ensure mtc-pharmacy-web container is running." # Retry docker exec mtc-pharmacy-web php artisan db:wipe fi # Sync database from staging echo "Syncing database from staging..." make db-sync if [ $? -ne 0 ]; then echo -e "${YELLOW}make db-sync failed${NC}" pause_for_user "Please check Makefile and database connection settings." else echo -e "${GREEN}Database synced successfully${NC}" fi echo -e "${GREEN}Step 12 complete${NC}" # ============================================================ # COMPLETE # ============================================================ echo "" echo -e "${GREEN}========================================${NC}" echo -e "${GREEN} Project Setup Complete!${NC}" echo -e "${GREEN}========================================${NC}" echo "" echo "Project cloned to: ${LOCAL_FOLDER}" echo "SSH key: ./staging.key" echo "" echo "Available commands:" echo " ./ssh.sh - SSH into server" echo " ./ssh.sh --git - Run lazygit on server" echo " ./ssh.sh --db - Forward database port" echo "" exit 0