#!/bin/bash # Gooneral Wheelchair - Linux/macOS Deployment Preparation Script # Usage: ./prepare-deployment.sh yourdomain.com [server-host] [server-user] set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Parse arguments DOMAIN="$1" SERVER_HOST="$2" SERVER_USER="${3:-root}" if [ -z "$DOMAIN" ]; then echo -e "${RED}❌ Error: Domain name is required${NC}" echo "" echo "Usage:" echo " $0 yourdomain.com # Create deployment package" echo " $0 yourdomain.com server-ip # Deploy directly to server" echo " $0 yourdomain.com server-ip username # Deploy with custom user" exit 1 fi echo -e "${GREEN}🚀 Preparing Gooneral Wheelchair for deployment...${NC}" echo -e "${CYAN}📁 Domain: $DOMAIN${NC}" # Generate secure session secret SESSION_SECRET=$(openssl rand -base64 64 | tr -d "=+/" | cut -c1-64) # Build the frontend echo -e "${YELLOW}🏗️ Building frontend...${NC}" npm run build if [ $? -ne 0 ]; then echo -e "${RED}❌ Frontend build failed!${NC}" exit 1 fi # Create deployment directory DEPLOY_DIR="./deployment-ready" if [ -d "$DEPLOY_DIR" ]; then rm -rf "$DEPLOY_DIR" fi mkdir -p "$DEPLOY_DIR" echo -e "${YELLOW}📦 Packaging files...${NC}" # Copy built frontend cp -r ./dist "$DEPLOY_DIR/" # Copy backend files BACKEND_DIR="$DEPLOY_DIR/backend" mkdir -p "$BACKEND_DIR" BACKEND_FILES=( "server.js" "start-production.js" "package.json" "auth.js" "themes.js" ) for file in "${BACKEND_FILES[@]}"; do if [ -f "./backend/$file" ]; then cp "./backend/$file" "$BACKEND_DIR/" fi done # Copy public directory if it exists if [ -d "./public" ]; then cp -r ./public "$DEPLOY_DIR/" fi # Create production environment file cat > "$BACKEND_DIR/.env.production" << EOF # Production Environment Variables - Generated $(date) # Server Configuration NODE_ENV=production PORT=3001 # IMPORTANT: This session secret was auto-generated # Keep this secret and secure! SESSION_SECRET=$SESSION_SECRET # CORS Configuration FRONTEND_URL=https://$DOMAIN # Database/Storage paths (relative to backend directory) POSTS_DIR=../public/posts THEMES_FILE=./themes.json SESSIONS_DIR=./sessions # Security Settings COOKIE_SECURE=true COOKIE_SAME_SITE=strict EOF # Create Caddyfile with the actual domain cat > "$DEPLOY_DIR/Caddyfile" << EOF # Caddy configuration for $DOMAIN $DOMAIN { # Enable automatic HTTPS # Caddy will automatically get and renew SSL certificates # Serve the React frontend (static files) root * dist # Try to serve static files first, then fallback to index.html for SPA routing try_files {path} /index.html # API routes - proxy to backend handle /api/* { reverse_proxy localhost:3001 } # Health check endpoint handle /health { reverse_proxy localhost:3001 } # Serve static files with proper headers header /assets/* { Cache-Control "public, max-age=31536000, immutable" } # Security headers header { # Enable HSTS Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" # Prevent clickjacking X-Frame-Options "DENY" # Prevent MIME type sniffing X-Content-Type-Options "nosniff" # XSS protection X-XSS-Protection "1; mode=block" # Referrer policy Referrer-Policy "strict-origin-when-cross-origin" # Content Security Policy (adjust as needed) Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;" } # Gzip compression encode gzip # Logging log { output file /var/log/caddy/gooneral-wheelchair.log format json } } EOF # Create systemd service file cat > "$DEPLOY_DIR/gooneral-wheelchair.service" << EOF [Unit] Description=Gooneral Wheelchair CMS Backend After=network.target [Service] Type=simple User=gooneral WorkingDirectory=/opt/gooneral-wheelchair/backend Environment=NODE_ENV=production ExecStart=/usr/bin/node start-production.js Restart=always RestartSec=10 StandardOutput=syslog StandardError=syslog SyslogIdentifier=gooneral-wheelchair [Install] WantedBy=multi-user.target EOF # Create the server deployment script cat > "$DEPLOY_DIR/deploy.sh" << 'EOF' #!/bin/bash # Gooneral Wheelchair - Automated Server Deployment Script # This script will fully set up your CMS on the server set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' echo -e "${GREEN}🚀 Starting automated deployment of Gooneral Wheelchair CMS...${NC}" # Check if running as root if [[ $EUID -eq 0 ]]; then echo -e "${RED}❌ Please run this script as a regular user with sudo privileges, not as root${NC}" exit 1 fi # Check if required commands exist for cmd in node npm caddy systemctl; do if ! command -v $cmd &> /dev/null; then echo -e "${RED}❌ Required command '$cmd' not found. Please install it first.${NC}" exit 1 fi done echo -e "${GREEN}✅ Prerequisites check passed${NC}" # Generate random password for admin user ADMIN_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-16) # Create application directory echo -e "${YELLOW}📁 Setting up application directory...${NC}" sudo mkdir -p /opt/gooneral-wheelchair sudo chown $USER:$USER /opt/gooneral-wheelchair # Copy files echo -e "${YELLOW}📦 Installing application files...${NC}" cp -r dist /opt/gooneral-wheelchair/ cp -r backend /opt/gooneral-wheelchair/ cp -r public /opt/gooneral-wheelchair/ 2>/dev/null || mkdir -p /opt/gooneral-wheelchair/public/posts # Install backend dependencies echo -e "${YELLOW}📥 Installing backend dependencies...${NC}" cd /opt/gooneral-wheelchair/backend npm install --production --silent # Create required directories mkdir -p sessions mkdir -p ../public/posts # Set up system user for security echo -e "${YELLOW}👤 Setting up system user...${NC}" if ! id "gooneral" &>/dev/null; then sudo useradd --system --shell /bin/false --home /opt/gooneral-wheelchair gooneral fi # Set proper ownership sudo chown -R gooneral:gooneral /opt/gooneral-wheelchair # Make start script executable chmod +x start-production.js # Install and start systemd service echo -e "${YELLOW}⚙️ Setting up systemd service...${NC}" sudo cp ../gooneral-wheelchair.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable gooneral-wheelchair sudo systemctl start gooneral-wheelchair # Give the service a moment to start sleep 3 if sudo systemctl is-active --quiet gooneral-wheelchair; then echo -e "${GREEN}✅ Backend service started successfully${NC}" else echo -e "${RED}❌ Backend service failed to start. Checking logs...${NC}" sudo systemctl status gooneral-wheelchair exit 1 fi # Set up Caddy echo -e "${YELLOW}🌐 Configuring Caddy...${NC}" sudo cp Caddyfile /etc/caddy/Caddyfile # Test Caddy configuration if sudo caddy validate --config /etc/caddy/Caddyfile; then echo -e "${GREEN}✅ Caddy configuration is valid${NC}" sudo systemctl reload caddy else echo -e "${RED}❌ Caddy configuration is invalid${NC}" exit 1 fi # Create admin user echo -e "${YELLOW}👨‍💼 Creating admin user...${NC}" cd /opt/gooneral-wheelchair/backend node -e " const bcrypt = require('bcryptjs'); const fs = require('fs'); const path = require('path'); const username = 'admin'; const password = '$ADMIN_PASSWORD'; const hashedPassword = bcrypt.hashSync(password, 10); const usersFile = path.join(__dirname, 'users.json'); const users = [ { id: 1, username: username, password: hashedPassword, role: 'admin' } ]; fs.writeFileSync(usersFile, JSON.stringify(users, null, 2)); console.log('Admin user created successfully'); " # Set proper ownership again after creating files sudo chown -R gooneral:gooneral /opt/gooneral-wheelchair # Extract domain from Caddyfile DOMAIN=$(grep -E '^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} {' Caddyfile | head -1 | cut -d' ' -f1) # Final status check echo "" echo -e "${GREEN}🎉 Deployment completed successfully!${NC}" echo "" echo "==================== IMPORTANT ====================" echo -e "${BLUE}🔐 Your admin credentials:${NC}" echo " Username: admin" echo " Password: $ADMIN_PASSWORD" echo "" echo -e "${RED}⚠️ SAVE THESE CREDENTIALS SECURELY!${NC}" echo -e "${RED}⚠️ Change the password after first login!${NC}" echo "==================== IMPORTANT ====================" echo "" echo -e "${CYAN}🌐 Your blog is now available at: https://$DOMAIN${NC}" echo -e "${CYAN}🔧 Admin panel: https://$DOMAIN/admin${NC}" echo "" echo -e "${YELLOW}📊 Service status:${NC}" sudo systemctl status gooneral-wheelchair --no-pager echo "" sudo systemctl status caddy --no-pager echo "" echo -e "${YELLOW}📝 To view logs:${NC}" echo " Backend: sudo journalctl -u gooneral-wheelchair -f" echo " Caddy: sudo journalctl -u caddy -f" echo "" echo -e "${GREEN}✅ Deployment complete!${NC}" EOF chmod +x "$DEPLOY_DIR/deploy.sh" # Create README cat > "$DEPLOY_DIR/README.md" << EOF # Gooneral Wheelchair - Deployment Package ## Quick Deployment 1. Upload this entire directory to your server 2. Run the deployment script: \`./deploy.sh\` 3. Access your blog at https://$DOMAIN ## What's Included - Built frontend in \`dist/\` - Backend application in \`backend/\` - Auto-configured Caddyfile for $DOMAIN - Systemd service configuration - Automated deployment script ## Generated Configuration - **Domain**: $DOMAIN - **Session Secret**: Auto-generated (64 characters) - **Admin User**: Will be created automatically - **SSL**: Automatic via Caddy + Let's Encrypt ## After Deployment The script will output your admin credentials. Save them securely! Access your blog: - **Blog**: https://$DOMAIN - **Admin**: https://$DOMAIN/admin ## Manual Steps (if needed) If the automated script doesn't work, see DEPLOYMENT.md for manual instructions. EOF # Copy the detailed deployment guide cp ./DEPLOYMENT.md "$DEPLOY_DIR/" 2>/dev/null || echo "Note: DEPLOYMENT.md not found, skipping..." # Upload and deploy if server specified if [ -n "$SERVER_HOST" ]; then echo -e "${YELLOW}📤 Uploading to server...${NC}" # Create tarball TAR_FILE="gooneral-wheelchair-deployment.tar.gz" tar -czf "$TAR_FILE" -C "$DEPLOY_DIR" . echo -e "${YELLOW}🚀 Deploying to $SERVER_HOST...${NC}" # Upload and execute deployment scp "$TAR_FILE" "${SERVER_USER}@${SERVER_HOST}:~/" ssh "${SERVER_USER}@${SERVER_HOST}" " mkdir -p gooneral-wheelchair-deploy cd gooneral-wheelchair-deploy tar -xzf ../$TAR_FILE chmod +x deploy.sh ./deploy.sh " # Clean up local tarball rm "$TAR_FILE" echo -e "${GREEN}✅ Remote deployment completed!${NC}" else echo "" echo -e "${GREEN}🎉 Deployment package ready!${NC}" echo -e "${CYAN}📁 Location: $DEPLOY_DIR${NC}" echo "" echo -e "${YELLOW}Next steps:${NC}" echo "1. Upload the '$DEPLOY_DIR' folder to your server" echo "2. SSH to your server and run: ./deploy.sh" echo "3. Access your blog at https://$DOMAIN" echo "" echo -e "${BLUE}💡 Or run this again with server details for automatic deployment:${NC}" echo "./prepare-deployment.sh $DOMAIN your.server.ip username" fi # Save deployment info cat > "$DEPLOY_DIR/deployment-info.json" << EOF { "domain": "$DOMAIN", "sessionSecret": "$SESSION_SECRET", "deploymentTime": "$(date -Iseconds)", "deploymentPath": "$DEPLOY_DIR" } EOF echo "" echo -e "${GREEN}✅ Session secret generated and saved securely in deployment package${NC}" echo -e "${RED}🔐 Keep your deployment files secure - they contain sensitive configuration!${NC}"