7 · Shared-hosting readiness
Objective — prove the hosting account is ready for deployment before Phase 4 starts. If this server was already prepared, run the Admin-Server status check. If this is the first app on the hosting account, run the shared-hosting playbook first, then come back here and verify it.
Steps at a glance:
- Choose the hosting account and SSH alias — Confirm which hosting account this app will deploy to and which local SSH alias reaches it. Use the same alias you will use in Phase 4 and Phase 5.
- Check whether Admin-Server already exists and is alive — Run the status script and log-freshness probe if
the server already has
~/Admin-Server/. Scripts on disk are not enough; dead cron jobs block Phase 4. - Run the shared-hosting playbook when this account is new — If the status script is missing or clearly incomplete, stop this app playbook and run the shared-hosting playbook for the hosting account.
- Record the server readiness note locally — Write the result where future sessions can find it without re-discovering the hosting account.
Background
Section titled “Background”The Set up shared hosting playbook is once per hosting account, not once per app. It installs the server-wide ~/Admin-Server/ toolkit that later deploy tasks use for deploy webhooks, ops alerts, monitoring scripts, baselines, and server notes.
This page does not duplicate that server playbook. It only decides whether the hosting account is already ready, routes first-time setup to the right place, registers this app’s domain path in the integrity baseline, and gives Phase 4 a clean gate.
1. Choose the hosting account and SSH alias
Section titled “1. Choose the hosting account and SSH alias”Confirm which hosting account this app will deploy to and which local SSH alias reaches it. Use the same alias you will use in Phase 4 and Phase 5.
-
Discover any existing SSH alias before treating SSH as unconfigured.
Terminal window grep -nE '^Host |HostName|User|Port|IdentityFile' ~/.ssh/config 2>/dev/null# Match the target hosting IP/domain from Zaj-PROJECT.md or the onboarding summary.# Expected: either a reusable Host alias appears, or you know one must be created.- Expected: if an existing alias matches host/user/port, reuse it and record that alias in
Zaj-PROJECT.md. If it points at an old IP, update the stanza. If no alias exists, return to Phase 2 SSH setup and create one.
- Expected: if an existing alias matches host/user/port, reuse it and record that alias in
-
Set the alias for this terminal session.
Terminal window export SSH_ALIAS="<selected-hosting-account-ssh-alias>"export PHPBIN="${PHPBIN:-php}" # replace with /opt/alt/phpXX/usr/bin/php once Phase 4 confirms itssh -o BatchMode=yes -o ConnectTimeout=8 "$SSH_ALIAS" "pwd && $PHPBIN -v | head -1"# Expected: SSH connects without an interactive password prompt and prints a remote path plus PHP version.- Expected: the command exits
0; a timeout, password prompt, or unknown host means SSH is not ready for Phase 4.
- Expected: the command exits
2. Check whether Admin-Server already exists and is alive
Section titled “2. Check whether Admin-Server already exists and is alive”Run the status script and freshness probe if the server already has ~/Admin-Server/. This is the fast path for a hosting account that was prepared by a previous project — but only if the cron-backed logs are fresh.
-
Run the status and freshness check.
Terminal window ssh "$SSH_ALIAS" 'bash -s' <<'REMOTE'set -euo pipefailcd ~/Admin-Servertest -x scripts/status.sh./scripts/status.shnow=$(date +%s)check_log() {label="$1"; path="$2"; max_age="$3"if [ ! -f "$path" ]; then echo "❌ STALE $label — missing $path"; exit 1; fimtime=$(stat -c %Y "$path")age=$((now - mtime))if [ "$age" -gt "$max_age" ]; thenecho "❌ STALE $label — last run $(date -d "@$mtime" -Is), age ${age}s, max ${max_age}s"; exit 1fiecho "✅ fresh $label — last run $(date -d "@$mtime" -Is)"}check_any_log() {label="$1"; max_age="$2"; shift 2for path in "$@"; do[ -f "$path" ] && check_log "$label" "$path" "$max_age" && return 0doneecho "❌ STALE $label — missing expected log: $*"; exit 1}check_any_log "config snapshot" 172800 logs/snapshot-config.logcheck_any_log "integrity" 172800 logs/integrity.log logs/integrity-check.logcheck_any_log "disk/inode" 43200 logs/resource.log logs/resources.log logs/resource-check.logcheck_any_log "PHP error scan" 43200 logs/error-log.log logs/error-log-check.logcheck_any_log "domain inventory" 2592000 logs/domain-inventory.logcheck_any_log "log rotation" 1209600 logs/rotate-logs.logREMOTE# Expected: status.sh exits 0 and every log row prints "fresh"; any STALE row blocks Phase 4.- Expected: the script runs and every log freshness row passes. If the file is missing, not executable, reports missing setup, or prints
STALE, continue to step 3 and fix the shared-hosting playbook before Phase 4.
- Expected: the script runs and every log freshness row passes. If the file is missing, not executable, reports missing setup, or prints
-
Add this app’s domain path to the Admin-Server integrity baseline.
Terminal window APP_DOMAIN="<selected-domain-from-Zaj-PROJECT>"ssh "$SSH_ALIAS" "APP_DOMAIN='$APP_DOMAIN' bash -s" <<'REMOTE'set -euo pipefailcd ~/Admin-Serverpath="$HOME/domains/$APP_DOMAIN"conf="config/monitored-paths.conf"touch "$conf"for monitored in "$HOME/.ssh/authorized_keys" "$path"; dogrep -Fxq "$monitored" "$conf" 2>/dev/null || printf '%s\n' "$monitored" >> "$conf"grep -Fx "$monitored" "$conf"done./scripts/generate-baseline.shgit add "$conf" baselines/checksums.md5git diff --cached --quiet || git commit -m "Monitor $APP_DOMAIN domain path"REMOTE# Expected: monitored-paths.conf contains authorized_keys + the app domain path; baseline regenerated.- Expected:
~/.ssh/authorized_keysand the domain path are present inmonitored-paths.conf, so integrity monitoring catches planted SSH keys and app-path drift once the app is deployed.
- Expected:
3. Run the shared-hosting playbook when this account is new
Section titled “3. Run the shared-hosting playbook when this account is new”If the status script is missing or clearly incomplete, stop this app playbook and run the shared-hosting playbook for the hosting account. Return here only after that server playbook reaches its checklist.
-
Open and complete the shared-hosting playbook.
-
Expected: the hosting account has
~/Admin-Server/, executable scripts, configured monitoring/alert state, and a documented SSH alias.
-
Re-run the status + freshness check after setup.
Terminal window ssh "$SSH_ALIAS" '~/Admin-Server/scripts/status.sh'# Expected: status.sh shows the correct identity. Then rerun step 2's freshness probe and require no STALE rows.- Expected: no missing Admin-Server toolkit and no stale cron-backed logs. Fix failed checks in the shared-hosting playbook before continuing.
4. Record the server readiness note
Section titled “4. Record the server readiness note”Write the result where future sessions can find it without re-discovering the hosting account.
-
Record the non-secret server mapping in
Zaj-PROJECT.md.Terminal window cat <<'EOF' >> Zaj-PROJECT.md## Shared-hosting readiness — <environment> — <YYYY-MM-DD>- SSH alias: <SSH_ALIAS>- Host/user/port: <host> · <user> · <port>- Hosting account: <host/account nickname>- Admin-Server status: verified with fresh logs; monitored-paths.conf includes ~/.ssh/authorized_keys and this domain- Shared-hosting playbook: completed or previously verifiedEOF# Expected: Zaj-PROJECT.md records the reusable non-secret alias/readiness facts.- Expected:
Zaj-PROJECT.mdnow carries the alias/readiness state that Phase 4 consumes.
- Expected:
-
Record personal/machine-only notes in
CLAUDE.local.mdwhen useful.Terminal window cat <<'EOF' >> CLAUDE.local.md## Shared-hosting readiness- SSH alias: <SSH_ALIAS>- Hosting account: <host/account nickname>- Admin-Server status: verified with fresh logs on <YYYY-MM-DD>- monitored-paths.conf includes: ~/.ssh/authorized_keys and ~/domains/<domain>- Shared-hosting playbook: completed or previously verifiedEOF# Expected: CLAUDE.local.md records the alias and readiness state without secrets.- Expected:
CLAUDE.local.mdremains gitignored; no webhook URL, password, token, or private key is written into tracked files.
- Expected:
Checklist
Section titled “Checklist”Do not mark this step done until every box below is checked.
- 🔀 Hosting account chosen — the app’s intended hosting account and SSH alias are known.
- 🤖 SSH works —
ssh "$SSH_ALIAS" ...connects without an interactive password prompt. - 🤖 Admin-Server present —
~/Admin-Server/scripts/status.shexists and is executable. - 🔀 Shared-hosting setup complete — first-time accounts completed the shared-hosting playbook before this app moved on.
- 🤖 Status + liveness clean —
status.shexits 0 and the log freshness probe has noSTALErows. - 🤖 Integrity baseline covers app —
~/Admin-Server/config/monitored-paths.confincludes~/.ssh/authorized_keysand this app’s~/domains/<domain>path, the baseline was regenerated, and the change is committed in the Admin-Server repo. - 🤖 Project state updated —
Zaj-PROJECT.mdrecords the non-secret alias/readiness state Phase 4 consumes. - 🔀 Local note updated —
CLAUDE.local.mdrecords any machine-only alias/readiness note and remains gitignored.