| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- #!/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}"
|