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
flowchart LR A["New hosting account"] --> B["Phase 0 · this playbook"] B --> C["setup-new · app 1"] B --> D["setup-new · app N"]Operating rules
Section titled “Operating rules”Every task in this phase follows four rules from the Phase 0 stub:
| Rule | Meaning |
|---|---|
| Runs on the server | SSH into ~/Admin-Server/ on the hosting account — zero toolkit binaries on your laptop |
| Secrets stay server-side | No webhook URL or SA token in laptop argv or agent chat — see Secrets discipline |
| Idempotent | Re-run safe: git pull-friendly; baselines non-destructive; cron lines detected before duplicate add |
| P9C-1 target | Future: webhooks in 1Password vault, only OP_SERVICE_ACCOUNT_TOKEN on disk — interim: URLs in server.env at chmod 600 |
Before you start
Section titled “Before you start”| Prerequisite | Verify |
|---|---|
| SSH public-key auth to the account | ssh <SSH_ALIAS> 'echo ok' — no password prompt |
Private GitHub repo Admin-Hostinger-<account> | Empty repo OK for first push |
| Discord or Slack ops channel | Webhook ready — configure only on server via nano |
| (After P9C-1) 1Password vault + SA token | Not required for interim flow |
Detect and skip
Section titled “Detect and skip”Run before any install work:
ssh <SSH_ALIAS> 'ls ~/Admin-Server/scripts/*.sh 2>/dev/null | head -10'| Output | Action |
|---|---|
| Scripts listed | Jump to Verify existing — skip tasks 0.1–0.5 |
| No such file | Continue with Tasks 0.1–0.10 |
Scripts but no lib/init.sh | Legacy 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.
0.1 · Clone Admin-Server toolkit
Section titled “0.1 · Clone Admin-Server toolkit”-
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-Servercd ~/Admin-Server && git remote -v'# Expected: origin → your Admin-Hostinger-<account> repo -
If the directory already exists, update instead of re-cloning.
Terminal window ssh <SSH_ALIAS> 'cd ~/Admin-Server && git fetch && git pull'
0.2 · op CLI (deferred — P9C-1)
Section titled “0.2 · op CLI (deferred — P9C-1)”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:
OP_SERVICE_ACCOUNT_TOKEN=""Do not run op signin from an agent session.
0.3 · Bootstrap config/server.env
Section titled “0.3 · Bootstrap config/server.env”-
Create
server.envfrom the template on the server only.Terminal window ssh <SSH_ALIAS> 'cd ~/Admin-Servercp config/server.env.example config/server.envchmod 600 config/server.envnano config/server.env' -
Set identity and at least one ops webhook (paste URL in
nanoon server — never into chat).Minimum fields:
SERVER_NAME,SERVER_LABEL,SERVER_ENV(staging|production),DISCORD_WEBHOOK_OPS(orSLACK_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”-
chmod scripts and confirm
server.envstays private.Terminal window ssh <SSH_ALIAS> 'chmod +x ~/Admin-Server/scripts/*.shchmod 600 ~/Admin-Server/config/server.envls -l ~/Admin-Server/scripts/status.sh ~/Admin-Server/config/server.env'# Expected: scripts -rwx; server.env -rw-------
0.5 · Generate initial MD5 baseline
Section titled “0.5 · Generate initial MD5 baseline”-
Generate and commit the integrity baseline.
Terminal window ssh <SSH_ALIAS> '~/Admin-Server/scripts/generate-baseline.shcd ~/Admin-Servergit add baselines/checksums.md5git commit -m "Initial integrity baseline"'# Expected: checksums.md5 with ≥4 monitored paths
0.6 · Run status.sh smoke test
Section titled “0.6 · Run status.sh smoke test”-
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)”-
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).
0.8 · Register six hPanel cron entries
Section titled “0.8 · Register six hPanel cron entries”Hostinger has no crontab CLI — use hPanel → Advanced → Cron Jobs.
| Cron job | Typical script | Watches |
|---|---|---|
| Config snapshot | snapshot-config.sh | Tracked config drift |
| MD5 integrity | integrity-check.sh | Baseline mutations |
| Disk / inode | resource-check.sh | Space and inode exhaustion |
| PHP error log | error-log-check.sh | New PHP errors across domains |
| Domain inventory | domain-inventory.sh | Apps/domains on account |
| Log rotation | rotate-logs.sh | Log volume |
-
Copy cron expressions from
status.shoutput (task 0.6) — do not guess schedules. -
Add six lines in hPanel using
/bin/bash $HOME/Admin-Server/scripts/<script>.shand verify five-field syntax (min hour dom mon dow). -
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'
0.9 · First commit + push
Section titled “0.9 · First commit + push”-
Push the Admin-Server repo (baseline + any committed config such as
server-environment.confif your deploy template needs PHP/Node paths).Terminal window ssh <SSH_ALIAS> 'cd ~/Admin-Servergit statusgit push'
0.10 · Document the server (SHOULD)
Section titled “0.10 · Document the server (SHOULD)”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.
Verify existing
Section titled “Verify existing”When detect-and-skip found scripts already installed:
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.
Idempotent re-run
Section titled “Idempotent re-run”| Concern | On second run |
|---|---|
| Repo | git fetch && git pull — no re-clone |
| Cron | Detected before add — no duplicates |
| Baseline | Regeneration non-destructive |
| Health | status.sh + ls ~/Admin-Server/scripts/*.sh |
Secrets discipline
Section titled “Secrets discipline”- Webhook URLs are credentials — revoke immediately if leaked (2026-04-29 incident).
server.env:chmod 600, gitignored — interim SoT forops/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.
Hardening server.env
Section titled “Hardening server.env”| Weakness | Interim | After P9C-1 |
|---|---|---|
| Plaintext webhooks on disk | chmod 600 + gitignore | SA fetch at runtime |
| No audit trail | Rotation log in monitoring state | 1Password activity log |
| Per-server manual rotation | Operator checklist | Rotate vault once; servers pull fresh |
P9C-1 unblocks after Phase 6 Task 62 proves op on Hostinger CloudLinux.
Checklist
Section titled “Checklist”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 -vcorrect - All monitoring scripts executable (
-rwx) -
config/server.envexists atchmod 600, gitignored - Six cron entries in hPanel (five-field syntax verified against
status.sh) -
baselines/checksums.md5exists with ≥4 entries - Test alert received with
[STAGING] 🟡or[PRODUCTION] 🔴prefix -
config/server-environment.confcommitted with PHP/Node/Composer paths (if deploy template uses it) - Server documented in
CLAUDE.local.md(task 0.10)
What’s next
Section titled “What’s next”When the gate passes, continue with CodeCanyon setup-new — Phase 1 workspace setup on your laptop.