Skip to content
prod e051e98
Browse

Set up shared hosting

Objective — bootstrap the per-server Admin-Server toolkit on a fresh hosting account so config drift detection, MD5 integrity checks, disk/inode alerts, PHP error-log scanning, domain inventory, log rotation, and three alert channels (ops · deploys · backups) are wired once for every app on that account.


This playbook is Phase 0 in the Residoro corpus — account-scoped server setup before CodeCanyon setup-new. Conceptual companion: Three-tier admin (handbook).

Once per account, then every app

Once per account, then every app 1. This account (Admin-Server (Phase 0)) → 2. App #1 (setup-new) → 3. App #N (reuse server tier) This account Admin-Server (Phase 0) App #1 setup-new App #N reuse server tier
flowchart LR
A["New hosting account"] --> B["Phase 0 · this playbook"]
B --> C["setup-new · app 1"]
B --> D["setup-new · app N"]

Every task in this phase follows four rules from the Phase 0 stub:

RuleMeaning
Runs on the serverSSH into ~/Admin-Server/ on the hosting account — zero toolkit binaries on your laptop
Secrets stay server-sideNo webhook URL or SA token in laptop argv or agent chat — see Secrets discipline
IdempotentRe-run safe: git pull-friendly; baselines non-destructive; cron lines detected before duplicate add
P9C-1 targetFuture: webhooks in 1Password vault, only OP_SERVICE_ACCOUNT_TOKEN on disk — interim: URLs in server.env at chmod 600
PrerequisiteVerify
SSH public-key auth to the accountssh <SSH_ALIAS> 'echo ok' — no password prompt
Private GitHub repo Admin-Hostinger-<account>Empty repo OK for first push
Discord or Slack ops channelWebhook ready — configure only on server via nano
(After P9C-1) 1Password vault + SA tokenNot required for interim flow

Run before any install work:

Terminal window
ssh <SSH_ALIAS> 'ls ~/Admin-Server/scripts/*.sh 2>/dev/null | head -10'
OutputAction
Scripts listedJump to Verify existing — skip tasks 0.1–0.5
No such fileContinue with Tasks 0.1–0.10
Scripts but no lib/init.shLegacy layout — resolve before cron (see Admin-Server repo docs)

Eight-step flow from the cross-phase proposal: Clone → op CLI (P9C-1) → server.env → verify → baseline → smoke test → cron → commit/push. Below maps to tasks 0.1–0.10 from the Phase 0 stub.

  1. Clone the per-server private repo into ~/Admin-Server/.

    Terminal window
    ssh <SSH_ALIAS> '
    git clone git@github.com-<GITHUB_USER>:<GITHUB_USER>/Admin-Hostinger-<account>.git ~/Admin-Server
    cd ~/Admin-Server && git remote -v
    '
    # Expected: origin → your Admin-Hostinger-<account> repo
  2. If the directory already exists, update instead of re-cloning.

    Terminal window
    ssh <SSH_ALIAS> 'cd ~/Admin-Server && git fetch && git pull'

Task 0.2 (download op 1Password CLI, no root) is MUST after P9C-1, not part of the interim bootstrap. For forward compatibility only, add an empty placeholder when editing server.env in task 0.3:

Terminal window
OP_SERVICE_ACCOUNT_TOKEN=""

Do not run op signin from an agent session.

  1. Create server.env from the template on the server only.

    Terminal window
    ssh <SSH_ALIAS> '
    cd ~/Admin-Server
    cp config/server.env.example config/server.env
    chmod 600 config/server.env
    nano config/server.env
    '
  2. Set identity and at least one ops webhook (paste URL in nano on server — never into chat).

    Minimum fields: SERVER_NAME, SERVER_LABEL, SERVER_ENV (staging | production), DISCORD_WEBHOOK_OPS (or SLACK_WEBHOOK_OPS). Optional channel slots: DISCORD_WEBHOOK_DEPLOYS, DISCORD_WEBHOOK_BACKUPS.

0.4 · Executable scripts + server.env permissions

Section titled “0.4 · Executable scripts + server.env permissions”
  1. chmod scripts and confirm server.env stays private.

    Terminal window
    ssh <SSH_ALIAS> '
    chmod +x ~/Admin-Server/scripts/*.sh
    chmod 600 ~/Admin-Server/config/server.env
    ls -l ~/Admin-Server/scripts/status.sh ~/Admin-Server/config/server.env
    '
    # Expected: scripts -rwx; server.env -rw-------
  1. Generate and commit the integrity baseline.

    Terminal window
    ssh <SSH_ALIAS> '
    ~/Admin-Server/scripts/generate-baseline.sh
    cd ~/Admin-Server
    git add baselines/checksums.md5
    git commit -m "Initial integrity baseline"
    '
    # Expected: checksums.md5 with ≥4 monitored paths
  1. Run the health snapshot — this is the verify step in the eight-step flow.

    Terminal window
    ssh <SSH_ALIAS> '~/Admin-Server/scripts/status.sh'

    Expected: clean SERVER_LABEL / SERVER_ENV; baseline ✅; webhook slots show ✅/❌ (at least one ✅ before you leave Phase 0); cron schedule printed — use that output for task 0.8.

0.7 · Fire one synthetic alert (ops channel)

Section titled “0.7 · Fire one synthetic alert (ops channel)”
  1. Send a test alert through the ops channel.

    Terminal window
    ssh <SSH_ALIAS> '
    ~/Admin-Server/scripts/alert-helper.sh INFO "Phase 0 smoke test" "Hello from $(hostname)" ops
    '

    Expected: Discord/Slack message with [STAGING] 🟡 or [PRODUCTION] 🔴 prefix (gate condition from Phase 0 stub).

Hostinger has no crontab CLI — use hPanel → Advanced → Cron Jobs.

Cron jobTypical scriptWatches
Config snapshotsnapshot-config.shTracked config drift
MD5 integrityintegrity-check.shBaseline mutations
Disk / inoderesource-check.shSpace and inode exhaustion
PHP error logerror-log-check.shNew PHP errors across domains
Domain inventorydomain-inventory.shApps/domains on account
Log rotationrotate-logs.shLog volume
  1. Copy cron expressions from status.sh output (task 0.6) — do not guess schedules.

  2. Add six lines in hPanel using /bin/bash $HOME/Admin-Server/scripts/<script>.sh and verify five-field syntax (min hour dom mon dow).

  3. Confirm log files update after the first interval (or check mtimes).

    Terminal window
    ssh <SSH_ALIAS> 'ls -la ~/Admin-Server/logs/*.log 2>/dev/null'
  1. Push the Admin-Server repo (baseline + any committed config such as server-environment.conf if your deploy template needs PHP/Node paths).

    Terminal window
    ssh <SSH_ALIAS> '
    cd ~/Admin-Server
    git status
    git push
    '

Record in the project’s CLAUDE.local.md (or equivalent local-only notes): SSH alias, Admin-Hostinger-<account> repo name, last baseline date, last webhook rotation — not in git-tracked secrets.


When detect-and-skip found scripts already installed:

Terminal window
ssh <SSH_ALIAS> '
~/Admin-Server/scripts/status.sh
ls -la ~/Admin-Server/logs/*.log 2>/dev/null
'

Fix only failed checks (missing baseline → 0.5; stale logs → 0.8; unset webhooks → 0.3 + 0.7). Then return to your app playbook.

ConcernOn second run
Repogit fetch && git pull — no re-clone
CronDetected before add — no duplicates
BaselineRegeneration non-destructive
Healthstatus.sh + ls ~/Admin-Server/scripts/*.sh
  • Webhook URLs are credentials — revoke immediately if leaked (2026-04-29 incident).
  • server.env: chmod 600, gitignored — interim SoT for ops / deploys / backups.
  • Prefer server-to-server copy or clipboard bridge at keyboard — never through agent chat.
  • P9C-1 (future): 1Password SA fetch replaces plaintext URLs — see Hardening.
WeaknessInterimAfter P9C-1
Plaintext webhooks on diskchmod 600 + gitignoreSA fetch at runtime
No audit trailRotation log in monitoring state1Password activity log
Per-server manual rotationOperator checklistRotate vault once; servers pull fresh

P9C-1 unblocks after Phase 6 Task 62 proves op on Hostinger CloudLinux.


Nine-item verification (cross-phase proposal):

  • SSH alias works passwordlessly from laptop
  • Server GitHub auth: ssh -T git@github.com-<GITHUB_USER> succeeds
  • ~/Admin-Server/ present; git remote -v correct
  • All monitoring scripts executable (-rwx)
  • config/server.env exists at chmod 600, gitignored
  • Six cron entries in hPanel (five-field syntax verified against status.sh)
  • baselines/checksums.md5 exists with ≥4 entries
  • Test alert received with [STAGING] 🟡 or [PRODUCTION] 🔴 prefix
  • config/server-environment.conf committed with PHP/Node/Composer paths (if deploy template uses it)
  • Server documented in CLAUDE.local.md (task 0.10)

When the gate passes, continue with CodeCanyon setup-new — Phase 1 workspace setup on your laptop.