From 596bf0bce0ce4533ebe960ec8ef1e0440410fdbb Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Tue, 5 May 2026 12:46:57 +0100 Subject: [PATCH] deploy.sh: update for new auth structure (lib/, data/, better-sqlite3, pm2 reload) --- deploy.sh | 116 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/deploy.sh b/deploy.sh index 46f1234..ba4f44a 100644 --- a/deploy.sh +++ b/deploy.sh @@ -7,11 +7,11 @@ # Apache (port 80) → reverse proxy → Node.js (port 3000) # # Prerequisites (do these manually before running this script): -# git clone git@bitbucket.org:zlalani/3m-portal.git /opt/3m-portal +# Upload new code to the server (rsync or git pull), then: # # Usage: # sudo bash /opt/3m-portal/deploy.sh # first-time install -# sudo bash /opt/3m-portal/deploy.sh --update # reload after git pull +# sudo bash /opt/3m-portal/deploy.sh --update # reload after code update # ============================================================= set -euo pipefail @@ -32,7 +32,8 @@ UPDATE_ONLY=false # ── 0. Checks ───────────────────────────────────────────────── [[ $EUID -ne 0 ]] && error "Run as root: sudo bash deploy.sh" -[[ ! -f "$APP_DIR/server.js" ]] && error "Code not found at $APP_DIR. Clone the repo first:\n git clone git@bitbucket.org:zlalani/3m-portal.git $APP_DIR" +[[ ! -f "$APP_DIR/server.js" ]] && error "Code not found at $APP_DIR. Upload the code first." +[[ ! -d "$APP_DIR/lib" ]] && error "lib/ directory missing — make sure the full codebase is uploaded." # ── 1. Node.js + build tools ────────────────────────────────── if ! $UPDATE_ONLY; then @@ -44,7 +45,7 @@ if ! $UPDATE_ONLY; then fi info "Node.js $(node -v), npm $(npm -v)" - section "Build tools (for better-sqlite3 native module)" + section "Build tools (required for better-sqlite3 native module)" apt-get install -y build-essential python3 make g++ info "Build tools installed" fi @@ -75,7 +76,7 @@ section "Data directory" mkdir -p "$APP_DIR/data" chown "$APP_USER":"$APP_USER" "$APP_DIR/data" chmod 700 "$APP_DIR/data" -info "Data directory: $APP_DIR/data" +info "Data directory: $APP_DIR/data (owner: $APP_USER, mode: 700)" # ── 4. .env ─────────────────────────────────────────────────── section ".env" @@ -93,15 +94,15 @@ COOKIE_SECURE=true SESSION_TTL_MS=28800000 INITIAL_ADMINS=[{"email":"CHANGE_ME","one2editUsername":"CHANGE_ME","password":"CHANGE_ME"}] MAILGUN_API_KEY=CHANGE_ME -MAILGUN_DOMAIN=CHANGE_ME -MAILGUN_FROM=CHANGE_ME +MAILGUN_DOMAIN=mg.oliver.solutions +MAILGUN_FROM=noreply@mg.oliver.solutions EOF warn "──────────────────────────────────────────────────" warn "Edit all values now: nano $ENV_FILE" warn "──────────────────────────────────────────────────" read -rp "Press Enter after updating .env to continue..." else - info ".env already exists — skipping" + info ".env exists" fi if grep -q "CHANGE_ME" "$ENV_FILE"; then @@ -110,32 +111,51 @@ fi # ── 5. Permissions ──────────────────────────────────────────── section "Permissions" +# Own all app files as nodeapp, then lock down .env and data chown -R "$APP_USER":"$APP_USER" "$APP_DIR" chmod 600 "$ENV_FILE" -info "Owner: $APP_USER, .env: 600" +# Re-apply data dir restriction (chown -R sets ownership but not mode) +chmod 700 "$APP_DIR/data" +info "Owner: $APP_USER, .env: 600, data/: 700" # ── 5a. npm install ─────────────────────────────────────────── section "npm install" -cd "$APP_DIR" && sudo -u "$APP_USER" npm install --omit=dev -info "Dependencies installed" +cd "$APP_DIR" && HOME="$APP_DIR" sudo -u "$APP_USER" npm install --omit=dev +info "Dependencies installed (including better-sqlite3 native build)" # ── 6. PM2 process ──────────────────────────────────────────── section "PM2 process" -pm2 stop 3m-portal 2>/dev/null || true -pm2 delete 3m-portal 2>/dev/null || true +if $UPDATE_ONLY; then + # Reload picks up new code + fresh .env without dropping existing sessions + if pm2 describe 3m-portal &>/dev/null; then + pm2 reload 3m-portal --update-env + info "PM2 reloaded with updated env" + else + warn "PM2 process not found — starting fresh" + pm2 start "$APP_DIR/server.js" \ + --name 3m-portal \ + --user "$APP_USER" \ + --log /var/log/3m-portal.log \ + --restart-delay 3000 \ + --max-restarts 10 + fi +else + pm2 stop 3m-portal 2>/dev/null || true + pm2 delete 3m-portal 2>/dev/null || true -pm2 start "$APP_DIR/server.js" \ - --name 3m-portal \ - --user "$APP_USER" \ - --log /var/log/3m-portal.log \ - --restart-delay 3000 \ - --max-restarts 10 + pm2 start "$APP_DIR/server.js" \ + --name 3m-portal \ + --user "$APP_USER" \ + --log /var/log/3m-portal.log \ + --restart-delay 3000 \ + --max-restarts 10 + + env PATH="$PATH:/usr/bin" pm2 startup systemd -u "$APP_USER" --hp "$APP_DIR" \ + | tail -1 | bash || warn "Run 'pm2 startup' manually if autostart is needed" +fi pm2 save -info "PM2 process started" - -env PATH="$PATH:/usr/bin" pm2 startup systemd -u "$APP_USER" --hp "$APP_DIR" \ - | tail -1 | bash || warn "Run 'pm2 startup' manually if autostart is needed" +info "PM2 state saved" # ── 7. Apache modules ───────────────────────────────────────── if ! $UPDATE_ONLY; then @@ -145,23 +165,20 @@ if ! $UPDATE_ONLY; then fi # ── 8. Apache virtual host ──────────────────────────────────── -section "Apache vhost" +if ! $UPDATE_ONLY; then + section "Apache vhost" -if [ -f "$APACHE_CONF" ]; then - cp "$APACHE_CONF" "${APACHE_CONF}.bak.$(date +%Y%m%d%H%M%S)" - info "Backed up existing config" -fi + if [ -f "$APACHE_CONF" ]; then + cp "$APACHE_CONF" "${APACHE_CONF}.bak.$(date +%Y%m%d%H%M%S)" + info "Backed up existing config" + fi -cat > "$APACHE_CONF" << EOF + cat > "$APACHE_CONF" << EOF # 3M OMG Portal — Apache reverse proxy to Node.js # # SSL is terminated at the load balancer. # This server receives plain HTTP on port 80 from the LB # and proxies it to Node.js on port ${NODE_PORT}. -# -# App: ${APP_DIR} -# Note: /var/vhosts/${DOMAIN}/htdocs exists (created by DevOps) -# but is intentionally unused — all traffic goes to Node.js. ServerName ${DOMAIN} @@ -181,17 +198,18 @@ cat > "$APACHE_CONF" << EOF EOF -info "Apache config written: $APACHE_CONF" + info "Apache config written: $APACHE_CONF" -# ── 9. Enable site & reload Apache ──────────────────────────── -section "Apache reload" -a2ensite "${DOMAIN}.conf" 2>/dev/null || true + # ── 9. Enable site & reload Apache ──────────────────────────── + section "Apache reload" + a2ensite "${DOMAIN}.conf" 2>/dev/null || true -if apache2ctl configtest 2>&1; then - systemctl reload apache2 - info "Apache reloaded" -else - error "Apache config test failed — check $APACHE_CONF" + if apache2ctl configtest 2>&1; then + systemctl reload apache2 + info "Apache reloaded" + else + error "Apache config test failed — check $APACHE_CONF" + fi fi # ── 10. Smoke test ──────────────────────────────────────────── @@ -203,10 +221,12 @@ else error "Node.js not responding. Check logs: pm2 logs 3m-portal" fi -if curl -sf "http://127.0.0.1/" -o /dev/null; then - info "Apache proxy responding on port 80" -else - warn "Apache not responding on port 80 — check: systemctl status apache2" +if ! $UPDATE_ONLY; then + if curl -sf "http://127.0.0.1/" -o /dev/null; then + info "Apache proxy responding on port 80" + else + warn "Apache not responding on port 80 — check: systemctl status apache2" + fi fi # ── Done ────────────────────────────────────────────────────── @@ -216,7 +236,7 @@ echo -e "${GREEN}║ Deploy complete! ║${N echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}║ Portal: https://${DOMAIN} ║${NC}" echo -e "${GREEN}║ Admin: https://${DOMAIN}/admin.html ║${NC}" -echo -e "${GREEN}║ App: ${APP_DIR} ║${NC}" echo -e "${GREEN}║ Logs: pm2 logs 3m-portal ║${NC}" -echo -e "${GREEN}║ Update: git pull && sudo bash deploy.sh --update ║${NC}" +echo -e "${GREEN}║ DB: sqlite3 ${APP_DIR}/data/portal.db ║${NC}" +echo -e "${GREEN}║ Update: upload code → sudo bash deploy.sh --update ║${NC}" echo -e "${GREEN}╚══════════════════════════════════════════════════════╝${NC}"