Files
peptide-e2e/infra/vps/install-orchestrator.sh
peptiderepo d922a8368f infra/vps: PRAB generation orchestrator (VPS-driven SSH, systemd timer)
Adds the VPS-side orchestrator for Option A (ADR 2026-06-22):
the Coolify KVM8 VPS (76.13.220.15) drives PRAutoBlogger generation
on prod synchronously over a held-open SSH session, escaping
Hostinger's ~10-min background-PHP-process kill.

Files:
  infra/vps/orchestrate-generation.sh
    - SSH to Hostinger; reaper sweep; wp prautoblogger generate --sync
    - Lock-aware: skips if run in-flight (plugin DB mutex)
    - Structured log lines (captured by systemd journal)
    - Failure alert: email to cto@peptiderepo.com via system mail
    - DRY_RUN=1 mode: echoes commands without executing generation
    - All config via env vars (SSH_KEY, SSH_HOST, etc.); no hardcoded secrets
    - SSH key referenced by PATH (/root/.ssh/hostinger_prod_ed25519)

  infra/vps/install-orchestrator.sh
    - Installs orchestrator to /opt/prab-orchestrator/
    - Installs systemd .service and .timer to /etc/systemd/system/
    - Does NOT enable or start timer (explicit post-QA cutover step)

  infra/vps/prab-generation.service
    - Type=oneshot, User=root, TimeoutStartSec=7200 (covers 32-min LLM calls)
    - Restart=no (timer retries next day on failure)

  infra/vps/prab-generation.timer
    - OnCalendar=*-*-* 06:00:00 UTC, Persistent=true, RandomizedDelaySec=300

DO NOT install or enable on the VPS this round — QA-gated, hold for CTO review.

Agent-Session: prab-reliability-20260622
2026-06-22 16:33:55 +00:00

65 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# install-orchestrator.sh — One-time setup for the PRAB generation orchestrator on the VPS.
#
# Installs:
# 1. orchestrate-generation.sh -> /opt/prab-orchestrator/ (from this repo)
# 2. prab-generation.service -> /etc/systemd/system/
# 3. prab-generation.timer -> /etc/systemd/system/
#
# Does NOT enable or start the timer — that is an explicit post-QA cutover step.
# Does NOT write secrets — the SSH key at /root/.ssh/hostinger_prod_ed25519 must
# already be present (placed manually by the CTO from .env.credentials).
#
# Run as root on the KVM8 VPS (76.13.220.15):
# bash infra/vps/install-orchestrator.sh
#
# After install, validate with DRY_RUN=1 before enabling the timer:
# DRY_RUN=1 /opt/prab-orchestrator/orchestrate-generation.sh
# systemctl enable --now prab-generation.timer # only after CEO greenlight
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="/opt/prab-orchestrator"
SYSTEMD_DIR="/etc/systemd/system"
ORCHESTRATE_SH="${SCRIPT_DIR}/orchestrate-generation.sh"
SERVICE_FILE="${SCRIPT_DIR}/prab-generation.service"
TIMER_FILE="${SCRIPT_DIR}/prab-generation.timer"
# Must be root.
if [[ "$(id -u)" -ne 0 ]]; then
echo "ERROR: install-orchestrator.sh must be run as root." >&2
exit 1
fi
# Validate source files exist.
for f in "${ORCHESTRATE_SH}" "${SERVICE_FILE}" "${TIMER_FILE}"; do
if [[ ! -f "$f" ]]; then
echo "ERROR: source file not found: $f" >&2
exit 1
fi
done
echo "Installing PRAB orchestrator to ${INSTALL_DIR}..."
mkdir -p "${INSTALL_DIR}"
install -m 0750 "${ORCHESTRATE_SH}" "${INSTALL_DIR}/orchestrate-generation.sh"
echo " OK: ${INSTALL_DIR}/orchestrate-generation.sh"
echo "Installing systemd units..."
install -m 0644 "${SERVICE_FILE}" "${SYSTEMD_DIR}/prab-generation.service"
install -m 0644 "${TIMER_FILE}" "${SYSTEMD_DIR}/prab-generation.timer"
echo " OK: ${SYSTEMD_DIR}/prab-generation.service"
echo " OK: ${SYSTEMD_DIR}/prab-generation.timer"
systemctl daemon-reload
echo " OK: systemctl daemon-reload"
echo ""
echo "Install complete. Timer is installed but NOT enabled."
echo "Next steps (post-QA + CEO greenlight only):"
echo " 1. Ensure SSH key exists: ls -la /root/.ssh/hostinger_prod_ed25519"
echo " 2. Validate with dry run: DRY_RUN=1 /opt/prab-orchestrator/orchestrate-generation.sh"
echo " 3. Run first real invocation: /opt/prab-orchestrator/orchestrate-generation.sh"
echo " 4. Enable timer: systemctl enable --now prab-generation.timer"
echo " 5. Confirm next run: systemctl list-timers prab-generation.timer"