prepare-deployment.ps1 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. # Gooneral Wheelchair - Local Deployment Preparation Script
  2. # Run this on your Windows development machine
  3. param(
  4. [Parameter(Mandatory=$true)]
  5. [string]$Domain,
  6. [Parameter(Mandatory=$false)]
  7. [string]$ServerUser = "root",
  8. [Parameter(Mandatory=$false)]
  9. [string]$ServerHost,
  10. [Parameter(Mandatory=$false)]
  11. [switch]$UploadToServer
  12. )
  13. Write-Host "🚀 Preparing Gooneral Wheelchair for deployment..." -ForegroundColor Green
  14. Write-Host "📁 Domain: $Domain" -ForegroundColor Cyan
  15. # Generate a secure session secret
  16. $SessionSecret = [System.Web.Security.Membership]::GeneratePassword(64, 10)
  17. # Build the frontend
  18. Write-Host "🏗️ Building frontend..." -ForegroundColor Yellow
  19. npm run build
  20. if ($LASTEXITCODE -ne 0) {
  21. Write-Host "❌ Frontend build failed!" -ForegroundColor Red
  22. exit 1
  23. }
  24. # Create deployment directory
  25. $DeployDir = ".\deployment-ready"
  26. if (Test-Path $DeployDir) {
  27. Remove-Item $DeployDir -Recurse -Force
  28. }
  29. New-Item -ItemType Directory -Path $DeployDir -Force | Out-Null
  30. Write-Host "📦 Packaging files..." -ForegroundColor Yellow
  31. # Copy built frontend
  32. Copy-Item -Path ".\dist" -Destination "$DeployDir\dist" -Recurse
  33. # Copy backend files
  34. $BackendDir = "$DeployDir\backend"
  35. New-Item -ItemType Directory -Path $BackendDir -Force | Out-Null
  36. $BackendFiles = @(
  37. "server.js",
  38. "start-production.js",
  39. "package.json",
  40. "auth.js",
  41. "themes.js"
  42. )
  43. foreach ($file in $BackendFiles) {
  44. if (Test-Path ".\backend\$file") {
  45. Copy-Item -Path ".\backend\$file" -Destination "$BackendDir\$file"
  46. }
  47. }
  48. # Copy public directory
  49. if (Test-Path ".\public") {
  50. Copy-Item -Path ".\public" -Destination "$DeployDir\public" -Recurse
  51. }
  52. # Create production environment file with the generated secret
  53. $EnvContent = @"
  54. # Production Environment Variables - Generated $(Get-Date)
  55. # Server Configuration
  56. NODE_ENV=production
  57. PORT=3001
  58. # IMPORTANT: This session secret was auto-generated
  59. # Keep this secret and secure!
  60. SESSION_SECRET=$SessionSecret
  61. # CORS Configuration
  62. FRONTEND_URL=https://$Domain
  63. # Database/Storage paths (relative to backend directory)
  64. POSTS_DIR=../public/posts
  65. THEMES_FILE=./themes.json
  66. SESSIONS_DIR=./sessions
  67. # Security Settings
  68. COOKIE_SECURE=true
  69. COOKIE_SAME_SITE=strict
  70. "@
  71. $EnvContent | Out-File -FilePath "$BackendDir\.env.production" -Encoding UTF8
  72. # Create Caddyfile with the actual domain
  73. $CaddyContent = @"
  74. # Caddy configuration for $Domain
  75. $Domain {
  76. # Enable automatic HTTPS
  77. # Caddy will automatically get and renew SSL certificates
  78. # Serve the React frontend (static files)
  79. root * dist
  80. # Try to serve static files first, then fallback to index.html for SPA routing
  81. try_files {path} /index.html
  82. # API routes - proxy to backend
  83. handle /api/* {
  84. reverse_proxy localhost:3001
  85. }
  86. # Health check endpoint
  87. handle /health {
  88. reverse_proxy localhost:3001
  89. }
  90. # Serve static files with proper headers
  91. header /assets/* {
  92. Cache-Control "public, max-age=31536000, immutable"
  93. }
  94. # Security headers
  95. header {
  96. # Enable HSTS
  97. Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
  98. # Prevent clickjacking
  99. X-Frame-Options "DENY"
  100. # Prevent MIME type sniffing
  101. X-Content-Type-Options "nosniff"
  102. # XSS protection
  103. X-XSS-Protection "1; mode=block"
  104. # Referrer policy
  105. Referrer-Policy "strict-origin-when-cross-origin"
  106. # Content Security Policy (adjust as needed)
  107. 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:;"
  108. }
  109. # Gzip compression
  110. encode gzip
  111. # Logging
  112. log {
  113. output file /var/log/caddy/gooneral-wheelchair.log
  114. format json
  115. }
  116. }
  117. "@
  118. $CaddyContent | Out-File -FilePath "$DeployDir\Caddyfile" -Encoding UTF8
  119. # Create systemd service file
  120. $ServiceContent = @"
  121. [Unit]
  122. Description=Gooneral Wheelchair CMS Backend
  123. After=network.target
  124. [Service]
  125. Type=simple
  126. User=gooneral
  127. WorkingDirectory=/opt/gooneral-wheelchair/backend
  128. Environment=NODE_ENV=production
  129. ExecStart=/usr/bin/node start-production.js
  130. Restart=always
  131. RestartSec=10
  132. StandardOutput=syslog
  133. StandardError=syslog
  134. SyslogIdentifier=gooneral-wheelchair
  135. [Install]
  136. WantedBy=multi-user.target
  137. "@
  138. $ServiceContent | Out-File -FilePath "$DeployDir\gooneral-wheelchair.service" -Encoding UTF8
  139. # Create the server deployment script
  140. $ServerDeployScript = @"
  141. #!/bin/bash
  142. # Gooneral Wheelchair - Automated Server Deployment Script
  143. # This script will fully set up your CMS on the server
  144. set -e # Exit on any error
  145. echo "🚀 Starting automated deployment of Gooneral Wheelchair CMS..."
  146. # Check if running as root
  147. if [[ `$EUID -eq 0 ]]; then
  148. echo "❌ Please run this script as a regular user with sudo privileges, not as root"
  149. exit 1
  150. fi
  151. # Check if required commands exist
  152. for cmd in node npm caddy systemctl; do
  153. if ! command -v `$cmd &> /dev/null; then
  154. echo "❌ Required command '`$cmd' not found. Please install it first."
  155. exit 1
  156. fi
  157. done
  158. echo "✅ Prerequisites check passed"
  159. # Generate random password for admin user
  160. ADMIN_PASSWORD=`$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-16)
  161. # Create application directory
  162. echo "📁 Setting up application directory..."
  163. sudo mkdir -p /opt/gooneral-wheelchair
  164. sudo chown `$USER:`$USER /opt/gooneral-wheelchair
  165. # Copy files
  166. echo "📦 Installing application files..."
  167. cp -r dist /opt/gooneral-wheelchair/
  168. cp -r backend /opt/gooneral-wheelchair/
  169. cp -r public /opt/gooneral-wheelchair/ 2>/dev/null || mkdir -p /opt/gooneral-wheelchair/public/posts
  170. # Install backend dependencies
  171. echo "📥 Installing backend dependencies..."
  172. cd /opt/gooneral-wheelchair/backend
  173. npm install --production --silent
  174. # Create required directories
  175. mkdir -p sessions
  176. mkdir -p ../public/posts
  177. # Set up system user for security
  178. echo "👤 Setting up system user..."
  179. if ! id "gooneral" &>/dev/null; then
  180. sudo useradd --system --shell /bin/false --home /opt/gooneral-wheelchair gooneral
  181. fi
  182. # Set proper ownership
  183. sudo chown -R gooneral:gooneral /opt/gooneral-wheelchair
  184. # Make start script executable
  185. chmod +x start-production.js
  186. # Install and start systemd service
  187. echo "⚙️ Setting up systemd service..."
  188. sudo cp ../gooneral-wheelchair.service /etc/systemd/system/
  189. sudo systemctl daemon-reload
  190. sudo systemctl enable gooneral-wheelchair
  191. sudo systemctl start gooneral-wheelchair
  192. # Give the service a moment to start
  193. sleep 3
  194. if sudo systemctl is-active --quiet gooneral-wheelchair; then
  195. echo "✅ Backend service started successfully"
  196. else
  197. echo "❌ Backend service failed to start. Checking logs..."
  198. sudo systemctl status gooneral-wheelchair
  199. exit 1
  200. fi
  201. # Set up Caddy
  202. echo "🌐 Configuring Caddy..."
  203. sudo cp Caddyfile /etc/caddy/Caddyfile
  204. # Test Caddy configuration
  205. if sudo caddy validate --config /etc/caddy/Caddyfile; then
  206. echo "✅ Caddy configuration is valid"
  207. sudo systemctl reload caddy
  208. else
  209. echo "❌ Caddy configuration is invalid"
  210. exit 1
  211. fi
  212. # Create admin user
  213. echo "👨‍💼 Creating admin user..."
  214. cd /opt/gooneral-wheelchair/backend
  215. node -e "
  216. const bcrypt = require('bcryptjs');
  217. const fs = require('fs');
  218. const path = require('path');
  219. const username = 'admin';
  220. const password = '`$ADMIN_PASSWORD';
  221. const hashedPassword = bcrypt.hashSync(password, 10);
  222. const usersFile = path.join(__dirname, 'users.json');
  223. const users = [
  224. {
  225. id: 1,
  226. username: username,
  227. password: hashedPassword,
  228. role: 'admin'
  229. }
  230. ];
  231. fs.writeFileSync(usersFile, JSON.stringify(users, null, 2));
  232. console.log('Admin user created successfully');
  233. "
  234. # Set proper ownership again after creating files
  235. sudo chown -R gooneral:gooneral /opt/gooneral-wheelchair
  236. # Final status check
  237. echo ""
  238. echo "🎉 Deployment completed successfully!"
  239. echo ""
  240. echo "==================== IMPORTANT ===================="
  241. echo "🔐 Your admin credentials:"
  242. echo " Username: admin"
  243. echo " Password: `$ADMIN_PASSWORD"
  244. echo ""
  245. echo "⚠️ SAVE THESE CREDENTIALS SECURELY!"
  246. echo "⚠️ Change the password after first login!"
  247. echo "==================== IMPORTANT ===================="
  248. echo ""
  249. echo "🌐 Your blog is now available at: https://$Domain"
  250. echo "🔧 Admin panel: https://$Domain/admin"
  251. echo ""
  252. echo "📊 Service status:"
  253. sudo systemctl status gooneral-wheelchair --no-pager
  254. echo ""
  255. sudo systemctl status caddy --no-pager
  256. echo ""
  257. echo "📝 To view logs:"
  258. echo " Backend: sudo journalctl -u gooneral-wheelchair -f"
  259. echo " Caddy: sudo journalctl -u caddy -f"
  260. echo ""
  261. echo "✅ Deployment complete!"
  262. "@
  263. $ServerDeployScript | Out-File -FilePath "$DeployDir\deploy.sh" -Encoding UTF8
  264. # Create a README for the deployment
  265. $ReadmeContent = @"
  266. # Gooneral Wheelchair - Deployment Package
  267. ## Quick Deployment
  268. 1. Upload this entire directory to your server
  269. 2. Run the deployment script: `./deploy.sh`
  270. 3. Access your blog at https://$Domain
  271. ## What's Included
  272. - Built frontend in `dist/`
  273. - Backend application in `backend/`
  274. - Auto-configured Caddyfile for $Domain
  275. - Systemd service configuration
  276. - Automated deployment script
  277. ## Generated Configuration
  278. - **Domain**: $Domain
  279. - **Session Secret**: Auto-generated (64 characters)
  280. - **Admin User**: Will be created automatically
  281. - **SSL**: Automatic via Caddy + Let's Encrypt
  282. ## After Deployment
  283. The script will output your admin credentials. Save them securely!
  284. Access your blog:
  285. - **Blog**: https://$Domain
  286. - **Admin**: https://$Domain/admin
  287. ## Manual Steps (if needed)
  288. If the automated script doesn't work, see DEPLOYMENT.md for manual instructions.
  289. "@
  290. $ReadmeContent | Out-File -FilePath "$DeployDir\README.md" -Encoding UTF8
  291. # Copy the detailed deployment guide
  292. Copy-Item -Path ".\DEPLOYMENT.md" -Destination "$DeployDir\DEPLOYMENT.md"
  293. # Create the upload script if server details provided
  294. if ($ServerHost -and $UploadToServer) {
  295. Write-Host "📤 Uploading to server..." -ForegroundColor Yellow
  296. # Create a tar.gz for easier upload (requires tar on Windows or WSL)
  297. $TarFile = "gooneral-wheelchair-deployment.tar.gz"
  298. if (Get-Command tar -ErrorAction SilentlyContinue) {
  299. tar -czf $TarFile -C $DeployDir .
  300. # Upload and deploy
  301. scp $TarFile "${ServerUser}@${ServerHost}:~/"
  302. ssh "${ServerUser}@${ServerHost}" "
  303. mkdir -p gooneral-wheelchair-deploy
  304. cd gooneral-wheelchair-deploy
  305. tar -xzf ../$TarFile
  306. chmod +x deploy.sh
  307. ./deploy.sh
  308. "
  309. Remove-Item $TarFile
  310. Write-Host "✅ Deployment completed remotely!" -ForegroundColor Green
  311. } else {
  312. Write-Host "⚠️ tar command not found. Please upload manually or install tar." -ForegroundColor Yellow
  313. }
  314. }
  315. Write-Host ""
  316. Write-Host "🎉 Deployment package ready!" -ForegroundColor Green
  317. Write-Host "📁 Location: $DeployDir" -ForegroundColor Cyan
  318. Write-Host ""
  319. Write-Host "Next steps:" -ForegroundColor Yellow
  320. Write-Host "1. Upload the '$DeployDir' folder to your server" -ForegroundColor White
  321. Write-Host "2. SSH to your server and run: ./deploy.sh" -ForegroundColor White
  322. Write-Host "3. Access your blog at https://$Domain" -ForegroundColor White
  323. Write-Host ""
  324. Write-Host "💡 Or run this again with -UploadToServer and -ServerHost flags for automatic upload" -ForegroundColor Gray
  325. # Save deployment info
  326. $DeployInfo = @{
  327. Domain = $Domain
  328. SessionSecret = $SessionSecret
  329. DeploymentTime = Get-Date
  330. DeploymentPath = $DeployDir
  331. }
  332. $DeployInfo | ConvertTo-Json | Out-File -FilePath "$DeployDir\deployment-info.json" -Encoding UTF8
  333. Write-Host ""
  334. Write-Host "✅ Session secret generated and saved securely in deployment package" -ForegroundColor Green
  335. Write-Host "🔐 Keep your deployment files secure - they contain sensitive configuration!" -ForegroundColor Red