Status: Completed 2026-08-11 — SSH-based monitoring replaced with SIAAS port probes; canonical DB target confirmed (VPS2 container); backup pipeline restored; monitoring generalised to all client tenants.
CORRECTION (2026-10-15) — "revoked" was our inference, not a decision. Matthew confirms he never revoked
SSH access to this box. Re-tested today, one deliberate attempt per candidate (three keys we hold: the
documentedclientadmin-keyasclientadmin, andvps_clientand the primary's own key asroot): all
three refused —Permission denied (publickey,password). The box answers on 22 and offers password auth,
so it is reachable and reachability was never the issue: we hold no credential it accepts. The 2026-08-11
wording below ("revoked") recorded a failed login, not a decision anyone took, and it should be read that
way. Closing it needs a credential the box accepts — a key installed through the Fasthosts console, or the
clientadminpassword — which is Matthew's to supply; nothing about the estate's design has to change.
Created: 2026-08-11 (investigation only — no changes made)
Related: SIAAS Remaining Tasks, Client VPS Setup, Client VPS Backups
The tenant app is fine: test-client.gp.veripath.co.uk resolves to VPS1 nginx → VPS2 app, and its app DB (dsp_clinic_dev) lives in the client_vps_postgres container on VPS2 (reached via tun-apps-vps2 → 172.18.0.1:5435). Tunnel-health reports HEALTHY for this canonical path.
Decision (2026-08-11): The VPS2 client_vps_postgres container is the canonical DB target for monitoring. The client VPS (77.68.97.101) remains a live client resource and is monitored for availability via a TCP port-22 probe (SIAAS no-SSH model). SSH key access to the client VPS was refused (corrected 2026-10-15: no revocation decision exists — see the correction above; the key we held was simply not accepted) and is not required for monitoring.
/usr/local/bin/check-client-uptime.sh rewritten to probe TCP 22 (the client VPS's only public exposure per UFW). Runs every 15 min for 77.68.97.101 and dental 194.164.18.33. Logs to /var/log/client-vps-uptime.log, alerts via logger.check-tunnel-health.py now accepts --tenant-slug + --credentials; per-tenant credential files created (/root/client-credentials.json, client-credentials-dental.json, client-credentials-dev-client.json). Cron now covers test-client (5435), test-client-dental (5436), dev-client (5437) for tunnel-health, capacity, and uptime.backup-client.py + backup-healthcheck.sh restored from /root/cleanup-quarantine-20260811/ (they had been disabled 2026-08-11 10:29). Cron (/etc/cron.d/practice-backup 02:30 daily, /etc/cron.d/backup-health every 2h) reinstated. Config /etc/practice-backup.conf corrected to the canonical target (dsp_clinic_dev via 172.18.0.1:5435). Backups are GPG-encrypted and stored in /var/backups/practice/daily/./opt/check-backup-status.py scans infrastructure_clientbackuplog for failures/stale (>30h) backups across all client tenants and alerts via logger (runs every 2h)./root/client-credentials.json updated to reflect the canonical VPS2-container DB, tunnel path, and backup location; reconciliation note added to /root/client-handover.md. client-credentials-dental.json / client-credentials-dev-client.json created for the other tenants.ubuntuPer the (now-superseded) handover doc it hosted PostgreSQL practice_app_db, pgAdmin4, daily DB backups, UFW, and pg-tunnel.service. The canonical tenant DB is now on VPS2.
| Check | Result |
|---|---|
| Port 22 reachable from primary | ✅ SSH banner responds (SSH-2.0-OpenSSH_10.2p1) |
SSH login clientadmin@77.68.97.101 with /root/clientadmin-key |
❌ Permission denied (publickey,password) — key no longer in authorized_keys |
| Key matches handover doc | ✅ Same fingerprint SHA256:v+9cxPAkDVTEVCP7SQ7W9xSkJtgTT7sb3uSUP15kUpE |
Reverse tunnel pg-tunnel.service → 127.0.0.1:15432 |
❌ Not established — legacy path, superseded by VPS2 container |
check-client-uptime.sh (cron */15) |
❌ Was failing continuously since ~2026-07-16 → now OK (port probe) |
check-tunnel-health.py for 172.18.0.1:5435 |
✅ HEALTHY (canonical VPS2 container DB) |
| Dental / dev-client tunnels (5436 / 5437) | ✅ Now monitored (were unmonitored) |
| Client backup pipeline | ❌ Was disabled 2026-08-11 → restored, passing |
tenant-gateway@15432 socat on VPS1 has no live target (legacy client-VPS path). Left in place; not used.client_monitor/tasks.py exist but are not in CELERY_BEAT_SCHEDULE; the cron scripts are the live monitors.Access is open and was used. Matthew supplied root credentials for the box; the visit was executed in
SSH/dev mode (the test estate's standing mode), and the box now holds the estate key: the public half of
/root/.ssh/vps_client is authorised for root and key-only login is verified, so the credential is no longer
the only path in. The temporary password was then rotated — new credential logs in, the old one is refused.
What the visit did: minted the box's agent credentials in the app, installed the client patch agent and its
four timers on the box's own 04:07Z quiet-window slot, and confirmed the loop end to end — the first
inventory posted and landed as a maintenance record, the signed-job poll answers, and the run renders on the
client's own page and in both CSV exports (verified as the tenant's own manager, 19/19 checks). Recorded in
the app as the box's own build-visit record plus a temporary_credential row. The 44 pending upgrades and the
outstanding reboot were not triggered — the first real run belongs to the managed service.
Finding for the record (security). This box's SSH is exposed to the internet with PermitRootLogin yes
and PasswordAuthentication yes (UFW: 22/tcp from anywhere; no fail2ban), and its auth log shows ~62,000
failed password attempts in the last 7 days — a continuous brute-force against root. The exposed password is
now dead (rotated), and the estate key works, so key-only SSH (or restricting 22/tcp to our own addresses)
is the next hardening step — and Matthew decided it the same day: key-only SSH is now in force on both test-estate Client
VPSes (2026-10-15). A host-local sshd_config.d/00-veripath-key-only.conf sets
PasswordAuthentication no, KbdInteractiveAuthentication no and PermitRootLogin prohibit-password;
sshd -t passed before the reload, and it is verified in both directions — the key signs in, and a
password attempt is refused (Permission denied (publickey), so the method is not even offered).
Reversing it is removing that one file and reloading ssh. The change is recorded on each box's own
maintenance record, so the client's page carries it.
tasks/siaas-remaining item 3) — infrastructure-level alerting now wired via cron; app badge still to do.