| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- # Gooneral Wheelchair - Local Deployment Preparation Script
- # Run this on your Windows development machine
- param(
- [Parameter(Mandatory=$true)]
- [string]$Domain,
-
- [Parameter(Mandatory=$false)]
- [string]$ServerUser = "root",
-
- [Parameter(Mandatory=$false)]
- [string]$ServerHost,
-
- [Parameter(Mandatory=$false)]
- [switch]$UploadToServer
- )
- Write-Host "🚀 Preparing Gooneral Wheelchair for deployment..." -ForegroundColor Green
- Write-Host "📁 Domain: $Domain" -ForegroundColor Cyan
- # Generate a secure session secret
- $SessionSecret = [System.Web.Security.Membership]::GeneratePassword(64, 10)
- # Build the frontend
- Write-Host "🏗️ Building frontend..." -ForegroundColor Yellow
- npm run build
- if ($LASTEXITCODE -ne 0) {
- Write-Host "❌ Frontend build failed!" -ForegroundColor Red
- exit 1
- }
- # Create deployment directory
- $DeployDir = ".\deployment-ready"
- if (Test-Path $DeployDir) {
- Remove-Item $DeployDir -Recurse -Force
- }
- New-Item -ItemType Directory -Path $DeployDir -Force | Out-Null
- Write-Host "📦 Packaging files..." -ForegroundColor Yellow
- # Copy built frontend
- Copy-Item -Path ".\dist" -Destination "$DeployDir\dist" -Recurse
- # Copy backend files
- $BackendDir = "$DeployDir\backend"
- New-Item -ItemType Directory -Path $BackendDir -Force | Out-Null
- $BackendFiles = @(
- "server.js",
- "start-production.js",
- "package.json",
- "auth.js",
- "themes.js"
- )
- foreach ($file in $BackendFiles) {
- if (Test-Path ".\backend\$file") {
- Copy-Item -Path ".\backend\$file" -Destination "$BackendDir\$file"
- }
- }
- # Copy public directory
- if (Test-Path ".\public") {
- Copy-Item -Path ".\public" -Destination "$DeployDir\public" -Recurse
- }
- # Create production environment file with the generated secret
- $EnvContent = @"
- # Production Environment Variables - Generated $(Get-Date)
- # Server Configuration
- NODE_ENV=production
- PORT=3001
- # IMPORTANT: This session secret was auto-generated
- # Keep this secret and secure!
- SESSION_SECRET=$SessionSecret
- # 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
- "@
- $EnvContent | Out-File -FilePath "$BackendDir\.env.production" -Encoding UTF8
- # Create Caddyfile with the actual domain
- $CaddyContent = @"
- # 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
- }
- }
- "@
- $CaddyContent | Out-File -FilePath "$DeployDir\Caddyfile" -Encoding UTF8
- # Create systemd service file
- $ServiceContent = @"
- [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
- "@
- $ServiceContent | Out-File -FilePath "$DeployDir\gooneral-wheelchair.service" -Encoding UTF8
- # Create the server deployment script
- $ServerDeployScript = @"
- #!/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
- echo "🚀 Starting automated deployment of Gooneral Wheelchair CMS..."
- # Check if running as root
- if [[ `$EUID -eq 0 ]]; then
- echo "❌ Please run this script as a regular user with sudo privileges, not as root"
- exit 1
- fi
- # Check if required commands exist
- for cmd in node npm caddy systemctl; do
- if ! command -v `$cmd &> /dev/null; then
- echo "❌ Required command '`$cmd' not found. Please install it first."
- exit 1
- fi
- done
- echo "✅ Prerequisites check passed"
- # Generate random password for admin user
- ADMIN_PASSWORD=`$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-16)
- # Create application directory
- echo "📁 Setting up application directory..."
- sudo mkdir -p /opt/gooneral-wheelchair
- sudo chown `$USER:`$USER /opt/gooneral-wheelchair
- # Copy files
- echo "📦 Installing application files..."
- 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 "📥 Installing backend dependencies..."
- 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 "👤 Setting up system user..."
- 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 "⚙️ Setting up systemd service..."
- 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 "✅ Backend service started successfully"
- else
- echo "❌ Backend service failed to start. Checking logs..."
- sudo systemctl status gooneral-wheelchair
- exit 1
- fi
- # Set up Caddy
- echo "🌐 Configuring Caddy..."
- sudo cp Caddyfile /etc/caddy/Caddyfile
- # Test Caddy configuration
- if sudo caddy validate --config /etc/caddy/Caddyfile; then
- echo "✅ Caddy configuration is valid"
- sudo systemctl reload caddy
- else
- echo "❌ Caddy configuration is invalid"
- exit 1
- fi
- # Create admin user
- echo "👨💼 Creating admin user..."
- 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
- # Final status check
- echo ""
- echo "🎉 Deployment completed successfully!"
- echo ""
- echo "==================== IMPORTANT ===================="
- echo "🔐 Your admin credentials:"
- echo " Username: admin"
- echo " Password: `$ADMIN_PASSWORD"
- echo ""
- echo "⚠️ SAVE THESE CREDENTIALS SECURELY!"
- echo "⚠️ Change the password after first login!"
- echo "==================== IMPORTANT ===================="
- echo ""
- echo "🌐 Your blog is now available at: https://$Domain"
- echo "🔧 Admin panel: https://$Domain/admin"
- echo ""
- echo "📊 Service status:"
- sudo systemctl status gooneral-wheelchair --no-pager
- echo ""
- sudo systemctl status caddy --no-pager
- echo ""
- echo "📝 To view logs:"
- echo " Backend: sudo journalctl -u gooneral-wheelchair -f"
- echo " Caddy: sudo journalctl -u caddy -f"
- echo ""
- echo "✅ Deployment complete!"
- "@
- $ServerDeployScript | Out-File -FilePath "$DeployDir\deploy.sh" -Encoding UTF8
- # Create a README for the deployment
- $ReadmeContent = @"
- # 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.
- "@
- $ReadmeContent | Out-File -FilePath "$DeployDir\README.md" -Encoding UTF8
- # Copy the detailed deployment guide
- Copy-Item -Path ".\DEPLOYMENT.md" -Destination "$DeployDir\DEPLOYMENT.md"
- # Create the upload script if server details provided
- if ($ServerHost -and $UploadToServer) {
- Write-Host "📤 Uploading to server..." -ForegroundColor Yellow
-
- # Create a tar.gz for easier upload (requires tar on Windows or WSL)
- $TarFile = "gooneral-wheelchair-deployment.tar.gz"
-
- if (Get-Command tar -ErrorAction SilentlyContinue) {
- tar -czf $TarFile -C $DeployDir .
-
- # Upload and deploy
- scp $TarFile "${ServerUser}@${ServerHost}:~/"
- ssh "${ServerUser}@${ServerHost}" "
- mkdir -p gooneral-wheelchair-deploy
- cd gooneral-wheelchair-deploy
- tar -xzf ../$TarFile
- chmod +x deploy.sh
- ./deploy.sh
- "
-
- Remove-Item $TarFile
- Write-Host "✅ Deployment completed remotely!" -ForegroundColor Green
- } else {
- Write-Host "⚠️ tar command not found. Please upload manually or install tar." -ForegroundColor Yellow
- }
- }
- Write-Host ""
- Write-Host "🎉 Deployment package ready!" -ForegroundColor Green
- Write-Host "📁 Location: $DeployDir" -ForegroundColor Cyan
- Write-Host ""
- Write-Host "Next steps:" -ForegroundColor Yellow
- Write-Host "1. Upload the '$DeployDir' folder to your server" -ForegroundColor White
- Write-Host "2. SSH to your server and run: ./deploy.sh" -ForegroundColor White
- Write-Host "3. Access your blog at https://$Domain" -ForegroundColor White
- Write-Host ""
- Write-Host "💡 Or run this again with -UploadToServer and -ServerHost flags for automatic upload" -ForegroundColor Gray
- # Save deployment info
- $DeployInfo = @{
- Domain = $Domain
- SessionSecret = $SessionSecret
- DeploymentTime = Get-Date
- DeploymentPath = $DeployDir
- }
- $DeployInfo | ConvertTo-Json | Out-File -FilePath "$DeployDir\deployment-info.json" -Encoding UTF8
- Write-Host ""
- Write-Host "✅ Session secret generated and saved securely in deployment package" -ForegroundColor Green
- Write-Host "🔐 Keep your deployment files secure - they contain sensitive configuration!" -ForegroundColor Red
|