How a Small Web Agency Turned Hosting Nightmares into Predictable SSH Workflows
This is a real-world case study about a five-person web agency that managed about 35 client sites across a mix of shared hosts, managed WordPress providers, and a couple of VPS instances. They were spending too much time on support, losing money on hosting bills, and getting blamed for outages they couldn’t reproduce. They moved to an SSH-first operating model and, within six months, reduced incident load, saved money, and gained repeatable deploys. This case study breaks down what they did, why it worked, step-by-step actions, measurable outcomes, lessons learned, and how you can copy it for your 5-50 site portfolio.
Why Traditional Shared Hosting Broke Down for Agencies Managing 5-50 Sites
The agency’s starting point is familiar: dozens of sites on three shared hosts, two managed WordPress accounts, a handful of hacked sites per year, slow backups, and zero centralized control. Pain points included:
- Support load: 40 monthly tickets about slow sites, broken SSL renewals, and failed updates.
- Cost unpredictability: $1,850 monthly on hosting, plus $600 in emergency overtime per month.
- Deployment chaos: FTP uploads, manual plugin updates, developers deploying different versions without rollback plans.
- Security friction: Compromises on shared hosts took hours to identify and days to remediate.
- Operational blind spots: No consistent backups, no standardized access control, no audit trail.
These issues are typical when managing several client sites with ad hoc tools. Outsourced hosting can mask technical debt for a while, but once you hit growth or a security event, the lack of centralized, scriptable control becomes a liability. The team realized rooting everything in SSH would give them the control they needed without becoming full-time sysadmins.

Choosing SSH as the Backbone: A Lean, Scriptable Approach
They needed a solution that met four criteria:
SSH met these needs because it is a standard, secure transport that supports command execution, file sync, port forwarding, and authenticated access without GUI reliance. The team rejected one-click host panels and complex orchestration products because those introduced new failure modes and vendor lock-in. Instead they built a thin, SSH-based stack around three pillars:
- Single VPS fleet with per-client isolation via containers (LXC) or lightweight VMs.
- Git-based deployments over SSH to bare repos with post-receive hooks or Ansible/Capistrano calling SSH.
- Automated SSH tunnels for maintenance and a single bastion host for centralized access and logging.
Think of SSH as the plumbing. Once you control the pipes, you can reliably deliver water to every faucet without running across the house to fix leaks.
Rolling Out SSH-First Operations: A 90-Day Implementation Plan
They executed in 90 days with three workstreams: infrastructure, deployment, and security. Below is the chronological roadmap they followed, with weekly milestones and concrete commands or configurations where applicable.
Weeks 1-2: Inventory and standardization
- List all sites, DNS providers, SSL status, plugins, and PHP versions. Result: 35 sites mapped to 4 risk buckets (urgent, upgrade, stable, legacy).
- Create a standard server image: Ubuntu LTS + nginx + PHP-FPM + MariaDB + fail2ban + UFW. They templated the image with cloud-init for reproducible servers.
Weeks 3-5: Bastion, keys, and host config
- Provision a small bastion host. All admin SSH access must go through this box. They set up key-only access and enforced 2FA for the bastion using a YubiKey for owners.
- Standardize SSH config in developers’ machines. Example entries in their ~/.ssh/config allowed simple commands like:
Host client1
HostName 203.0.113.45

User deploy
IdentityFile ~/.ssh/id_rsa_deploy
- Rotate keys and install an ssh-agent setup so passphrases are entered once per day on developer laptops.
Weeks 6-8: Git over SSH and deploy hooks
https://saaspirate.com/best-wordpress-hosting-for-agencies/
- Converted each site to a bare Git repo on the target container: git init –bare /srv/repo.git
- Added a post-receive hook that checks out to the webroot and runs migrations, asset builds, and cache clears. Example process: push -> post-receive runs ./deploy.sh -> restart php-fpm
- For WordPress sites they used a similar approach: composer for dependencies, Git for custom code, and WP-CLI executed via SSH for database operations.
Weeks 9-11: Automation and monitoring
- Introduced Ansible for routine tasks across hosts. They used the ssh connection plugin in Ansible to run playbooks without additional agents.
- Set up unattended backups via rsync over SSH to an offsite S3-compatible object store and daily snapshots via borg over SSH. This produced a 30-day retention window at a predictable cost.
- Installed Prometheus exporters and used an SSH port forward to push metrics from isolated containers to the monitoring server when necessary.
Weeks 12: Validation and cutover
- Moved sites in batches. Each batch followed a checklist: DNS TTL reduction, push to bare repo, smoke test, SSL check, and fallback to previous snapshot if any issue.
- Documented runbooks and trained the team on failover, rollbacks using git revert or restoring borg snapshots, and incident steps using the bastion logs.
They used small, repeatable procedures so moving 35 sites did not become a months-long project. The work was front-loaded: most automation paid back in time savings during operate-and-maintain phases.
From 40 Support Tickets to 6: Measurable Hosting Improvements in 6 Months
Numbers matter. Here are the before-and-after metrics the agency tracked and reported to clients and staff:
Financially, the agency saved about $1,100/month in hosting and cut emergency overtime costs by roughly $600/month, resulting in roughly $1,700/month in recurring savings. Operationally, the major win was predictability: deployments were auditable, rollbacks took minutes, and incident triage had clear logs. The team could bill fewer hours for maintenance and focus on feature work.
5 Hard Lessons Agencies Learned About SSH and Hosting
Not everything was smooth. Here are the practical lessons that mattered.
These are operational realities, not marketing fluff. If you skip them, you trade one set of problems for another.
How Your Agency Can Build the Same SSH-Based Platform
If you’re managing 5-50 client sites and tired of late-night hosting fires, you can replicate this approach. Below is a practical playbook with checklists, commands, and trade-offs so you can estimate time and risk.
Quick checklist to get started
- Inventory everything: site URL, DNS provider, current host, backup status, PHP versions, SSL status, and contact person.
- Pick a bastion host and force all admin access through it. Budget: $10-50/month depending on provider and redundancy needs.
- Decide between containers (LXC/docker) or lightweight VMs. Containers are dense and cheap, VMs isolate better for some clients.
- Standardize a server image and bake in tools: nginx, php-fpm, MariaDB, fail2ban, UFW, backup agent (borg or rclone).
- Implement Git-based deploys to bare repos over SSH, and a rollback strategy using git tags and snapshots.
Key commands and patterns you will use daily
- git push deploy master (push to remote bare repo over SSH)
- rsync -azP –delete -e “ssh -p 2222” ./build/ deploy@host:/var/www/site
- ssh -A bastion ‘ssh web@site-host sudo systemctl restart php7.4-fpm’ (SSH agent forwarding via bastion)
- autossh -M 0 -N -o “ServerAliveInterval 30” -o “ServerAliveCountMax 3” -R 2222:localhost:22 user@bastion (reverse tunnel for quick maintenance)
Use per-site deploy scripts that run migrations, clear caches, and check health endpoints. Example deploy sequence: push -> post-receive executes deploy.sh -> runs smoke tests -> triggers uptime check and alert if fail.
Security configurations to implement immediately
- Disable password auth. Enforce key-based auth in sshd_config: PasswordAuthentication no
- Limit user shells for deploy accounts using ForceCommand or restrict commands in authorized_keys for automation keys.
- Install fail2ban and configure rate limits for SSH. Move SSH to a non-standard port if that fits your threat model.
- Centralize logs: forward auth logs from servers to the bastion or a log collector for forensics.
When to use managed platforms instead
This approach is not for every agency. If you manage a few very large, mission-critical sites with strict SLAs and need 24/7 on-call, a managed host with an SLA might be better. But for 5-50 typical client sites where cost, control, and repeatability matter, SSH-first gives the best balance.
Estimated resource plan
- Initial migration: 2-4 weeks of part-time work for a single engineer for up to 20 sites; scale linearly beyond that.
- Monthly ops: 8-20 hours for maintenance and improvements after automation.
- Hosting costs: $10-40/site depending on density and SLA targets; compared with $50-150/site on many managed host plans.
Think of this as moving from messy, rented office space to a small, well-organized workshop you control. It requires some setup and discipline, but the work you do once compounds and keeps paying back.
Final pragmatic notes
- Start with a small batch of non-critical sites to prove the pipeline.
- Automate the painful parts like backups and restores before you transport critical sites.
- Measure outcomes: tickets, downtime, and developer hours saved. These numbers justify the initial investment to clients or partners.
SSH won’t solve strategic problems like scope creep or client churn, and it’s not a silver bullet. But for agencies and freelancers tired of hosting headaches, it’s a practical tool that turns firefighting into predictable engineering work. If you prefer, I can sketch a tailored 90-day migration plan for your portfolio of sites with cost estimates and a rollout schedule.

SEARCH

