diff --git a/deploy/novacpx-post-restore.sh b/deploy/novacpx-post-restore.sh index 603107e..df97c61 100755 --- a/deploy/novacpx-post-restore.sh +++ b/deploy/novacpx-post-restore.sh @@ -1,73 +1,130 @@ #!/usr/bin/env bash -# NovaCPX Post-Restore Script -# Run after any PBS/backup restore to fix config drift and rebuild hosting state -# Usage: /usr/local/bin/novacpx-post-restore +# NovaCPX Post-Restore Script v2 +# Run after any PBS/backup restore +# Usage: /usr/local/bin/novacpx-post-restore [--no-git] set -euo pipefail LOG="/var/log/novacpx/post-restore.log" -PAT=$(python3 -c "import configparser; c=configparser.ConfigParser(); c.read('/etc/novacpx/config.ini'); print(c.get('deploy','github_pat',fallback=''))" 2>/dev/null || true) +PAT=$(python3 -c "import configparser; c=configparser.ConfigParser(); c.read('/etc/novacpx/config.ini'); print(c.get('deploy','github_pat',fallback=''))" 2>/dev/null || echo "") WEB_DASHBOARD_REPO="https://${PAT}@github.com/myronblair/web-dashboard.git" +NOVACPX_REPO="https://${PAT}@github.com/myronblair/novacpx.git" +SKIP_GIT="${1:-}" -log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; } +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; } +ok() { log " ✓ $*"; } +warn() { log " ⚠ $*"; } +mkdir -p /var/log/novacpx log "=== NovaCPX Post-Restore Started ===" -# 1. Fix config.ini — always reverts to apache after restore -log "Fixing config.ini web server setting..." +# ── 1. Fix config.ini ───────────────────────────────────────────────────── +log "1. Fixing config.ini..." sed -i 's/^server = apache/server = nginx/' /etc/novacpx/config.ini -grep "^server" /etc/novacpx/config.ini >> "$LOG" +ok "server = $(grep '^server' /etc/novacpx/config.ini | cut -d= -f2 | tr -d ' ')" -# 2. Clean orphaned PHP-FPM pool configs (users deleted during restore) -log "Cleaning orphaned PHP-FPM pools..." +# Disable Apache2 if running +systemctl stop apache2 2>/dev/null && systemctl disable apache2 2>/dev/null || true + +# ── 2. Fix PHP-FPM ──────────────────────────────────────────────────────── +log "2. Fixing PHP-FPM..." REMOVED=0 for f in /etc/php/8.3/fpm/pool.d/*.conf; do [[ "$f" == *"www.conf"* ]] && continue u=$(basename "$f" .conf) - if ! id "$u" &>/dev/null; then - log " Removing orphan pool: $f" - rm -f "$f" - ((REMOVED++)) || true - fi + id "$u" &>/dev/null || { rm -f "$f"; ((REMOVED++)) || true; } done -log " Removed $REMOVED orphaned pools" +[[ $REMOVED -gt 0 ]] && warn "Removed $REMOVED orphaned pools" || ok "No orphaned pools" -# 3. Start/restart PHP-FPM -log "Starting PHP-FPM..." -systemctl start php8.3-fpm 2>/dev/null || systemctl restart php8.3-fpm -systemctl is-active php8.3-fpm >> "$LOG" - -# 4. Check if webacct Linux user and hosting account exist -if ! id "webacct" &>/dev/null; then - log "webacct user missing — creating hosting account for web.orbishosting.com..." - php8.3 << 'PHPEOF' >> "$LOG" 2>&1 -insert( - "INSERT INTO users (username, password, email, role, status) VALUES (?,?,?,?,?)", - ['webacct', password_hash('Joker1974!!!', PASSWORD_BCRYPT), 'webacct@web.orbishosting.com', 'user', 'active'] -); -$result = AccountManager::create(['username'=>'webacct','domain'=>'web.orbishosting.com', - 'password'=>'Joker1974!!!','user_id'=>$userId,'php_version'=>'8.3']); -echo "Account created: " . json_encode($result) . "\n"; -PHPEOF -else - log "webacct user exists — skipping account creation" +# Fix pm.max_children if still at default 5 +PM=$(grep "^pm.max_children" /etc/php/8.3/fpm/pool.d/www.conf 2>/dev/null | awk '{print $3}') +if [[ "$PM" == "5" ]] || [[ -z "$PM" ]]; then + echo -e "\npm = dynamic\npm.max_children = 20\npm.start_servers = 5\npm.min_spare_servers = 3\npm.max_spare_servers = 10" >> /etc/php/8.3/fpm/pool.d/www.conf + ok "PHP-FPM max_children bumped to 20" fi -# 5. Ensure nginx vhost for web.orbishosting.com exists +systemctl start php8.3-fpm 2>/dev/null || systemctl restart php8.3-fpm +ok "PHP-FPM $(systemctl is-active php8.3-fpm)" + +# ── 3. Pull latest NovaCPX code ─────────────────────────────────────────── +if [[ "$SKIP_GIT" != "--no-git" ]] && [[ -n "$PAT" ]]; then + log "3. Pulling latest NovaCPX code..." + cd /opt/novacpx-src 2>/dev/null || { warn "novacpx-src not found, skipping"; true; } + if [[ -d /opt/novacpx-src/.git ]]; then + git remote set-url origin "$NOVACPX_REPO" 2>/dev/null + git pull origin main 2>&1 | tail -3 | while read l; do log " $l"; done + rsync -a --delete --exclude=".git" --exclude="api/config.php" \ + /opt/novacpx-src/panel/public/ /srv/novacpx/public/ 2>/dev/null + rsync -a --delete --exclude="config.php" \ + /opt/novacpx-src/panel/api/ /srv/novacpx/public/api/ 2>/dev/null + rsync -a --delete /opt/novacpx-src/panel/lib/ /srv/novacpx/public/lib/ 2>/dev/null + ok "Code deployed" + # Run migrations + DB=/var/lib/novacpx/panel.db + for SQL in /opt/novacpx-src/db/migrations/*.sql; do + [[ -f "$SQL" ]] || continue + NAME=$(basename "$SQL" .sql) + DONE=$(sqlite3 "$DB" "SELECT value FROM settings WHERE key='migration_$NAME'" 2>/dev/null) + if [[ -z "$DONE" ]]; then + sqlite3 "$DB" < "$SQL" 2>/dev/null && \ + sqlite3 "$DB" "INSERT OR REPLACE INTO settings (key,value,updated_at) VALUES ('migration_$NAME','$(date)',datetime('now'))" 2>/dev/null + ok "Migration: $NAME" + fi + done + fi +else + log "3. Skipping git pull" +fi + +# ── 4. Fix webacct hosting account ──────────────────────────────────────── +log "4. Fixing webacct hosting account..." +DB=/var/lib/novacpx/panel.db + +# Clean orphaned user record (user exists in DB but Linux user doesn't) +if id "webacct" &>/dev/null; then + ok "webacct Linux user exists" +else + warn "webacct Linux user missing — cleaning DB and recreating..." + # Remove orphaned DB record + sqlite3 "$DB" "DELETE FROM users WHERE username='webacct' AND id NOT IN (SELECT user_id FROM accounts WHERE username='webacct');" 2>/dev/null || true + sqlite3 "$DB" "DELETE FROM users WHERE username='webacct' AND role='user';" 2>/dev/null || true + + # Create via PHP + php8.3 /tmp/_nova_create_webacct.php >> "$LOG" 2>&1 || true +fi + +# Ensure account exists in DB +ACCT_EXISTS=$(sqlite3 "$DB" "SELECT COUNT(*) FROM accounts WHERE username='webacct';" 2>/dev/null || echo "0") +if [[ "$ACCT_EXISTS" == "0" ]]; then + warn "webacct account not in DB — creating..." + cat > /tmp/_nova_create_webacct.php << 'PHPEOF' +execute("DELETE FROM users WHERE username='webacct' AND role='user'"); +$uid = (int)$db->insert( + "INSERT INTO users (username,password,email,role,status) VALUES (?,?,?,?,?)", + ['webacct',password_hash('Joker1974!!!',PASSWORD_BCRYPT),'webacct@web.orbishosting.com','user','active'] +); +$r = AccountManager::create(['username'=>'webacct','domain'=>'web.orbishosting.com','password'=>'Joker1974!!!','user_id'=>$uid,'php_version'=>'8.3']); +echo "Created: ".json_encode($r)."\n"; +PHPEOF + php8.3 /tmp/_nova_create_webacct.php >> "$LOG" 2>&1 && ok "Account created" || warn "Account creation failed — check log" +fi + +# ── 5. Ensure nginx vhost and Basic Auth ────────────────────────────────── +log "5. Ensuring nginx vhost..." VHOST="/etc/nginx/sites-available/novacpx-webacct.conf" if [[ ! -f "$VHOST" ]]; then - log "Creating nginx vhost for web.orbishosting.com..." cat > "$VHOST" << 'NGINX' server { listen 80; @@ -76,10 +133,8 @@ server { index index.php index.html index.htm; access_log /home/webacct/logs/access.log; error_log /home/webacct/logs/error.log; - auth_basic "Blair HQ"; auth_basic_user_file /etc/nginx/htpasswd.webacct; - location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/run/php/php8.3-fpm-webacct.sock; @@ -90,35 +145,33 @@ server { } NGINX ln -sf "$VHOST" /etc/nginx/sites-enabled/novacpx-webacct.conf - log " Vhost created and enabled" + ok "Vhost created" fi -# 6. Ensure Basic Auth password file exists -if [[ ! -f /etc/nginx/htpasswd.webacct ]]; then - log "Creating htpasswd for web.orbishosting.com..." - htpasswd -cb /etc/nginx/htpasswd.webacct "myronblair@outlook.com" "Joker1974!!!" +[[ -f /etc/nginx/htpasswd.webacct ]] || { + htpasswd -cb /etc/nginx/htpasswd.webacct "myronblair@outlook.com" "Joker1974!!!" 2>/dev/null + ok "Basic auth created" +} + +# ── 6. Deploy Blair HQ dashboard ────────────────────────────────────────── +log "6. Deploying Blair HQ dashboard..." +if [[ -n "$PAT" ]]; then + TMP=$(mktemp -d) + git clone --depth=1 "$WEB_DASHBOARD_REPO" "$TMP" 2>/dev/null && { + cp "$TMP/index.html" /home/webacct/public_html/index.html 2>/dev/null + cp "$TMP/notes.php" /home/webacct/public_html/notes.php 2>/dev/null + chown webacct:www-data /home/webacct/public_html/index.html /home/webacct/public_html/notes.php 2>/dev/null + [[ -f /home/webacct/notes.json ]] || { echo "[]" > /home/webacct/notes.json; chown webacct:www-data /home/webacct/notes.json; } + ok "Dashboard deployed" + } || warn "Dashboard deploy failed (check PAT)" + rm -rf "$TMP" fi -# 7. Deploy Blair HQ dashboard from GitHub -log "Deploying Blair HQ dashboard from GitHub..." -TMP_DIR=$(mktemp -d) -git clone --depth=1 "$WEB_DASHBOARD_REPO" "$TMP_DIR" 2>> "$LOG" && \ - cp "$TMP_DIR/index.html" /home/webacct/public_html/index.html && \ - chown webacct:www-data /home/webacct/public_html/index.html && \ - log " Dashboard deployed" || log " Dashboard deploy failed (check PAT)" -rm -rf "$TMP_DIR" - -# 8. Reload nginx -log "Reloading nginx..." -nginx -t >> "$LOG" 2>&1 && systemctl reload nginx -log " nginx reloaded" - -# 9. Disable Apache2 if present -if systemctl is-active apache2 &>/dev/null; then - log "Disabling Apache2..." - systemctl stop apache2 && systemctl disable apache2 -fi +# ── 7. Reload nginx ─────────────────────────────────────────────────────── +log "7. Reloading nginx..." +nginx -t 2>/dev/null && systemctl reload nginx && ok "nginx reloaded" || warn "nginx config error" +systemctl reload php8.3-fpm 2>/dev/null || true log "=== Post-Restore Complete ===" echo "" -echo "✓ NovaCPX post-restore complete. Check $LOG for details." +echo "✓ NovaCPX post-restore complete. Log: $LOG"