#!/bin/bash # Interactive Setup Wizard for Custom PHP Framework Deployment # Provides step-by-step guided configuration for production-ready deployments # Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4 set -euo pipefail # Script configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../" && pwd)" DEPLOYMENT_DIR="${SCRIPT_DIR}" # Configuration state CURRENT_STEP=1 TOTAL_STEPS=8 ENVIRONMENT="" DOMAIN="" EMAIL="" SERVER_IP="" SSH_KEY_PATH="" # Configuration storage declare -A CONFIG_VALUES declare -A PASSWORD_STORE # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' NC='\033[0m' # Enhanced logging functions log() { echo -e "${GREEN}[$(date +'%H:%M:%S')] ✅ $1${NC}"; } warn() { echo -e "${YELLOW}[$(date +'%H:%M:%S')] ⚠️ $1${NC}"; } error() { echo -e "${RED}[$(date +'%H:%M:%S')] ❌ $1${NC}"; } info() { echo -e "${BLUE}[$(date +'%H:%M:%S')] ℹ️ $1${NC}"; } success() { echo -e "${WHITE}[$(date +'%H:%M:%S')] 🎉 $1${NC}"; } # Progress indicator show_progress() { local step=$1 local total=$2 local description="$3" local progress=$((step * 100 / total)) local bars=$((progress / 5)) local spaces=$((20 - bars)) printf "\n${PURPLE}[Step %d/%d] ${WHITE}%s${NC}\n" "$step" "$total" "$description" printf "${CYAN}Progress: [${GREEN}" printf "█%.0s" $(seq 1 $bars) printf "${CYAN}" printf "░%.0s" $(seq 1 $spaces) printf "${CYAN}] %d%%${NC}\n\n" "$progress" } # Welcome screen show_welcome() { clear cat << 'EOF' ███████╗███████╗████████╗██╗ ██╗██████╗ ██╔════╝██╔════╝╚══██╔══╝██║ ██║██╔══██╗ ███████╗█████╗ ██║ ██║ ██║██████╔╝ ╚════██║██╔══╝ ██║ ██║ ██║██╔═══╝ ███████║███████╗ ██║ ╚██████╔╝██║ ╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ EOF cat << EOF ${WHITE}Custom PHP Framework Deployment Setup Wizard${NC} ${CYAN}Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4${NC} ${GREEN}This wizard will guide you through setting up a production-ready deployment:${NC} ✅ Environment configuration with secure defaults ✅ Automatic password generation and validation ✅ SSH key setup and server connectivity testing ✅ SSL/TLS certificate configuration ✅ Docker and Ansible integration ✅ Complete deployment validation ${YELLOW}Prerequisites:${NC} Internet connection, sudo access (if needed) ${YELLOW}Time Required:${NC} 10-15 minutes ${YELLOW}What You'll Need:${NC} Server details and domain information ${WHITE}Press Enter to start, or Ctrl+C to exit...${NC} EOF read -r } # Step 1: Environment Selection step_environment_selection() { show_progress $CURRENT_STEP $TOTAL_STEPS "Environment Selection" cat << EOF ${WHITE}Select Deployment Environment${NC} ${CYAN}Available environments:${NC} 1) ${GREEN}Development${NC} - Local development with debug enabled 2) ${YELLOW}Staging${NC} - Pre-production testing environment 3) ${RED}Production${NC} - Live production environment (recommended) ${WHITE}Which environment would you like to configure?${NC} EOF while true; do printf "${CYAN}Enter choice (1-3): ${NC}" read -r choice case $choice in 1) ENVIRONMENT="development" DOMAIN="dev.michaelschiemer.de" info "Selected: Development environment" break ;; 2) ENVIRONMENT="staging" DOMAIN="staging.michaelschiemer.de" info "Selected: Staging environment" break ;; 3) ENVIRONMENT="production" DOMAIN="michaelschiemer.de" info "Selected: Production environment" break ;; *) error "Invalid choice. Please enter 1, 2, or 3." ;; esac done CONFIG_VALUES[ENVIRONMENT]=$ENVIRONMENT CONFIG_VALUES[DOMAIN]=$DOMAIN } # Step 2: Domain and Contact Configuration step_domain_configuration() { show_progress $CURRENT_STEP $TOTAL_STEPS "Domain and Contact Information" cat << EOF ${WHITE}Domain and Contact Configuration${NC} Current settings: • Environment: ${GREEN}${ENVIRONMENT}${NC} • Suggested domain: ${GREEN}${DOMAIN}${NC} • Contact email: ${GREEN}kontakt@michaelschiemer.de${NC} EOF printf "\n${CYAN}Is this domain correct? [Y/n]: ${NC}" read -r confirm if [[ $confirm =~ ^[Nn]$ ]]; then printf "${CYAN}Enter your domain name: ${NC}" read -r custom_domain if [[ -n "$custom_domain" ]]; then DOMAIN="$custom_domain" CONFIG_VALUES[DOMAIN]="$custom_domain" info "Domain updated to: $custom_domain" fi fi EMAIL="kontakt@michaelschiemer.de" printf "${CYAN}Contact email for SSL certificates [${EMAIL}]: ${NC}" read -r custom_email if [[ -n "$custom_email" ]]; then EMAIL="$custom_email" fi CONFIG_VALUES[EMAIL]=$EMAIL success "Domain configuration completed" } # Step 3: Server Configuration step_server_configuration() { show_progress $CURRENT_STEP $TOTAL_STEPS "Server Configuration" cat << EOF ${WHITE}Server Configuration${NC} Enter your deployment server details: EOF while true; do printf "${CYAN}Server IP address or hostname: ${NC}" read -r server_ip if [[ -n "$server_ip" ]]; then if [[ $server_ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ $server_ip =~ ^[a-zA-Z0-9.-]+$ ]]; then SERVER_IP="$server_ip" CONFIG_VALUES[SERVER_IP]="$server_ip" break else error "Invalid IP address or hostname format" fi else error "Server IP/hostname is required" fi done printf "${CYAN}SSH username [root]: ${NC}" read -r ssh_user ssh_user=${ssh_user:-root} CONFIG_VALUES[SSH_USER]="$ssh_user" printf "${CYAN}SSH port [22]: ${NC}" read -r ssh_port ssh_port=${ssh_port:-22} CONFIG_VALUES[SSH_PORT]="$ssh_port" info "Server: ${ssh_user}@${SERVER_IP}:${ssh_port}" success "Server configuration completed" } # Step 4: SSH Key Setup step_ssh_key_setup() { show_progress $CURRENT_STEP $TOTAL_STEPS "SSH Key Configuration" cat << EOF ${WHITE}SSH Key Setup${NC} We need SSH access to your server for deployment. EOF local default_key="$HOME/.ssh/production" printf "${CYAN}SSH private key path [${default_key}]: ${NC}" read -r key_path SSH_KEY_PATH=${key_path:-$default_key} if [[ ! -f "$SSH_KEY_PATH" ]]; then warn "SSH key not found: $SSH_KEY_PATH" printf "${CYAN}Generate new SSH key pair? [Y/n]: ${NC}" read -r generate_key if [[ ! $generate_key =~ ^[Nn]$ ]]; then info "Generating SSH key pair..." mkdir -p "$(dirname "$SSH_KEY_PATH")" ssh-keygen -t ed25519 -C "deploy@${DOMAIN}" -f "$SSH_KEY_PATH" -N "" success "SSH key pair generated:" info "Private key: $SSH_KEY_PATH" info "Public key: ${SSH_KEY_PATH}.pub" cat << EOF ${YELLOW}📋 COPY THIS PUBLIC KEY TO YOUR SERVER:${NC} $(cat "${SSH_KEY_PATH}.pub") ${YELLOW}Add this key to ~/.ssh/authorized_keys on your server.${NC} EOF printf "${CYAN}Press Enter when you've added the key to your server...${NC}" read -r fi else success "Found existing SSH key: $SSH_KEY_PATH" fi CONFIG_VALUES[SSH_KEY_PATH]="$SSH_KEY_PATH" } # Step 5: Test Server Connectivity step_test_connectivity() { show_progress $CURRENT_STEP $TOTAL_STEPS "Server Connectivity Test" cat << EOF ${WHITE}Testing Server Connectivity${NC} Testing SSH connection to ${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}... EOF if ssh -i "$SSH_KEY_PATH" -p "${CONFIG_VALUES[SSH_PORT]}" \ -o ConnectTimeout=10 -o BatchMode=yes \ "${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}" \ "echo 'Connection successful'" 2>/dev/null; then success "SSH connection test passed" info "Testing server requirements..." local server_info server_info=$(ssh -i "$SSH_KEY_PATH" -p "${CONFIG_VALUES[SSH_PORT]}" \ "${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}" \ "uname -a && free -h && df -h /" 2>/dev/null) echo -e "${BLUE}Server Information:${NC}" echo "$server_info" else error "SSH connection failed" cat << EOF ${YELLOW}Troubleshooting tips:${NC} 1. Verify the server IP and SSH port 2. Ensure your SSH public key is in ~/.ssh/authorized_keys on the server 3. Check if SSH service is running on the server 4. Verify firewall allows SSH connections EOF printf "${CYAN}Continue anyway? [y/N]: ${NC}" read -r continue_anyway if [[ ! $continue_anyway =~ ^[Yy]$ ]]; then error "Setup cancelled due to connectivity issues" exit 1 fi fi } # Step 6: Secure Password Generation step_password_generation() { show_progress $CURRENT_STEP $TOTAL_STEPS "Secure Credential Generation" cat << EOF ${WHITE}Generating Secure Credentials${NC} Creating secure passwords and keys for your deployment... EOF if ! command -v openssl >/dev/null 2>&1; then error "OpenSSL not found. Please install OpenSSL first." exit 1 fi info "Generating database passwords..." PASSWORD_STORE[DB_PASSWORD]=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25) PASSWORD_STORE[DB_ROOT_PASSWORD]=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25) info "Generating Redis password..." PASSWORD_STORE[REDIS_PASSWORD]=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25) info "Generating application key..." PASSWORD_STORE[APP_KEY]=$(openssl rand -base64 32) if [[ "$ENVIRONMENT" == "production" ]]; then info "Generating monitoring passwords..." PASSWORD_STORE[GRAFANA_ADMIN_PASSWORD]=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-16) fi success "All credentials generated securely" # Show password strength cat << EOF ${CYAN}Password Strength Summary:${NC} • Database passwords: 25 characters, alphanumeric • Redis password: 25 characters, alphanumeric • Application key: 32 characters, base64 encoded • All passwords cryptographically secure EOF } # Step 7: Configuration File Creation step_create_configuration() { show_progress $CURRENT_STEP $TOTAL_STEPS "Configuration File Creation" cat << EOF ${WHITE}Creating Configuration Files${NC} Building environment configuration for ${ENVIRONMENT}... EOF local env_file="${DEPLOYMENT_DIR}/applications/environments/.env.${ENVIRONMENT}" local template_file="${env_file}.template" if [[ ! -f "$template_file" ]]; then error "Template file not found: $template_file" exit 1 fi info "Creating .env.${ENVIRONMENT} from template..." cp "$template_file" "$env_file" # Apply configurations info "Applying domain and email settings..." sed -i "s|DOMAIN_NAME=.*|DOMAIN_NAME=${CONFIG_VALUES[DOMAIN]}|g" "$env_file" sed -i "s|MAIL_FROM_ADDRESS=.*|MAIL_FROM_ADDRESS=${CONFIG_VALUES[EMAIL]}|g" "$env_file" # Apply generated passwords info "Applying secure credentials..." for key in "${!PASSWORD_STORE[@]}"; do local value="${PASSWORD_STORE[$key]}" sed -i "s|${key}=\*\*\* REQUIRED \*\*\*|${key}=${value}|g" "$env_file" sed -i "s|${key}=changeme|${key}=${value}|g" "$env_file" done # Environment-specific settings if [[ "$ENVIRONMENT" == "production" ]]; then sed -i 's|APP_DEBUG=.*|APP_DEBUG=false|g' "$env_file" sed -i 's|LOG_LEVEL=.*|LOG_LEVEL=warning|g' "$env_file" fi # Set secure permissions chmod 600 "$env_file" success "Configuration file created: $env_file" # Update Ansible inventory info "Updating Ansible inventory..." local inventory_file="${DEPLOYMENT_DIR}/infrastructure/inventories/${ENVIRONMENT}/hosts.yml" if [[ -f "$inventory_file" ]]; then # Backup original cp "$inventory_file" "${inventory_file}.backup" # Update server details sed -i "s|ansible_host:.*|ansible_host: ${CONFIG_VALUES[SERVER_IP]}|g" "$inventory_file" sed -i "s|ansible_user:.*|ansible_user: ${CONFIG_VALUES[SSH_USER]}|g" "$inventory_file" sed -i "s|ansible_port:.*|ansible_port: ${CONFIG_VALUES[SSH_PORT]}|g" "$inventory_file" sed -i "s|ansible_ssh_private_key_file:.*|ansible_ssh_private_key_file: ${CONFIG_VALUES[SSH_KEY_PATH]}|g" "$inventory_file" success "Ansible inventory updated: $inventory_file" else warn "Ansible inventory not found: $inventory_file" fi } # Step 8: Final Validation and Summary step_final_validation() { show_progress $CURRENT_STEP $TOTAL_STEPS "Final Validation" cat << EOF ${WHITE}Final Validation and Summary${NC} Running configuration validation... EOF # Validate configuration local env_file="${DEPLOYMENT_DIR}/applications/environments/.env.${ENVIRONMENT}" info "Validating environment configuration..." if grep -q "\*\*\* REQUIRED \*\*\*" "$env_file" 2>/dev/null; then error "Some required fields are still unfilled:" grep "\*\*\* REQUIRED \*\*\*" "$env_file" exit 1 fi success "All required fields are configured" # Test Docker Compose configuration info "Validating Docker Compose configuration..." cd "$PROJECT_ROOT" if docker-compose -f docker-compose.yml -f "deployment/applications/docker-compose.${ENVIRONMENT}.yml" config >/dev/null 2>&1; then success "Docker Compose configuration is valid" else warn "Docker Compose validation failed - may need manual review" fi # Show summary cat << EOF ${WHITE}🎉 SETUP WIZARD COMPLETED SUCCESSFULLY! 🎉${NC} ${CYAN}Configuration Summary:${NC} • Environment: ${WHITE}${ENVIRONMENT}${NC} • Domain: ${WHITE}${CONFIG_VALUES[DOMAIN]}${NC} • Server: ${WHITE}${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}:${CONFIG_VALUES[SSH_PORT]}${NC} • SSH Key: ${WHITE}${CONFIG_VALUES[SSH_KEY_PATH]}${NC} • Configuration: ${WHITE}.env.${ENVIRONMENT}${NC} ${CYAN}Generated Secure Credentials:${NC} • Database passwords: ${GREEN}Generated${NC} • Redis password: ${GREEN}Generated${NC} • Application key: ${GREEN}Generated${NC} EOF if [[ "$ENVIRONMENT" == "production" ]]; then echo "• Monitoring passwords: ${GREEN}Generated${NC}" fi cat << EOF ${CYAN}Files Created/Updated:${NC} • ${YELLOW}deployment/applications/environments/.env.${ENVIRONMENT}${NC} • ${YELLOW}deployment/infrastructure/inventories/${ENVIRONMENT}/hosts.yml${NC} • ${YELLOW}${CONFIG_VALUES[SSH_KEY_PATH]} (if generated)${NC} ${CYAN}Next Steps:${NC} 1. Review configuration: ${YELLOW}less deployment/applications/environments/.env.${ENVIRONMENT}${NC} 2. Test deployment: ${YELLOW}./deployment/deploy.sh ${ENVIRONMENT} --dry-run${NC} 3. Deploy: ${YELLOW}./deployment/deploy.sh ${ENVIRONMENT}${NC} ${GREEN}Your Custom PHP Framework is ready for deployment!${NC} ${CYAN}Domain: ${CONFIG_VALUES[DOMAIN]} | Environment: ${ENVIRONMENT}${NC} EOF } # Main wizard flow main() { show_welcome # Execute wizard steps CURRENT_STEP=1; step_environment_selection; ((CURRENT_STEP++)) CURRENT_STEP=2; step_domain_configuration; ((CURRENT_STEP++)) CURRENT_STEP=3; step_server_configuration; ((CURRENT_STEP++)) CURRENT_STEP=4; step_ssh_key_setup; ((CURRENT_STEP++)) CURRENT_STEP=5; step_test_connectivity; ((CURRENT_STEP++)) CURRENT_STEP=6; step_password_generation; ((CURRENT_STEP++)) CURRENT_STEP=7; step_create_configuration; ((CURRENT_STEP++)) CURRENT_STEP=8; step_final_validation; ((CURRENT_STEP++)) success "Setup wizard completed successfully!" } # Error handling cleanup() { local exit_code=$? if [ $exit_code -ne 0 ]; then error "Setup wizard failed with exit code: $exit_code" echo echo -e "${RED}If you need help, check the troubleshooting guide or start over.${NC}" fi } trap cleanup EXIT # Execute if run directly if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi