Multi-Host Deploy Runner
Build a Bash tool that deploys an application to several servers over SSH, running an ordered list of steps on each (for example: pull the new version, run migrations on one host only, restart the service, check health). It deploys in waves, a few hosts at a time, checks each host's health with curl after the update, and stops the rollout as soon as something fails, so a bad release never reaches every server. Every host gets its own log, a summary is produced with awk, and a failed deployment can be rolled back. You'll learn SSH automation, running work in parallel with limits, rolling deployments, health checks, safe failure handling in Bash, and testing scripts that act on remote machines.
- Estimate
- ~13.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
curl · GNU Awk
Project roadmap
- 01
Design the deployment
~2hWrite DESIGN.md: the inventory file (hosts with groups and optional user and port), the plan file (ordered steps, each a command with options: run on all hosts, once, or only on a group; a timeout; and whether a failure is fatal), the wave size, the health check URL per host, and what rollback does. Describe what happens when a step or health check fails in the middle of a wave. Done when: DESIGN.md defines the files, waves and failure rules.
- 02
Run steps on one host
~2hWrite a function that runs a plan's steps on one host in order with ssh -o BatchMode=yes -o ConnectTimeout=10, applying each step's timeout, writing the output of each step with timestamps to logs/RUN_ID/HOST.log, and stopping at the first fatal failure. Record the result of each step (ok, failed or skipped, with its duration) in a results file. Done when: running a plan against one test host logs each step and stops on failure.
- 03
Deploy in waves
~2.5hSplit the hosts into waves (such as 1 canary host first, then groups of N), run hosts in a wave in parallel as background jobs, wait for them all, and continue to the next wave only if every host succeeded. Run once steps on the first host only, before the rest. Stop the whole rollout on the first failed wave. Done when: a failure on the canary host stops the deployment before any other host is touched.
- 04
Check health
~1.5hAfter each host's steps, poll its health URL with curl --fail --max-time until it answers correctly or a deadline passes, and treat a failed health check as a failed host. Optionally check the version reported by the service matches the one being deployed. Done when: a host whose service doesn't come back is marked failed and stops the rollout.
- 05
Roll back
~2hAdd a rollback plan that runs on hosts that were already updated in the failed run (read from the results file), newest first, and a --rollback RUN_ID command to run it later. Keep a lock (flock) so two deployments can never run at the same time, and a --dry-run that prints what would happen on each host. Done when: a failed deployment can be rolled back on exactly the hosts that changed.
- 06
Summarize the run
~1hAt the end, use awk on the results file to print a summary table: each host's steps, status and duration, the wave it was in, and the total time, plus the paths to failing hosts' logs. Exit with a non-zero code when anything failed. Done when: the summary makes the result of the run clear at a glance.
- 07
Test it
~2.5hTest with several SSH servers in Docker containers (for example linuxserver/openssh-server) running a small fake service with a health endpoint, including one that fails on purpose. Check waves, the canary stop, once steps, health failures, rollback and dry runs. Add bats-core tests for the plan and inventory parsing, and run shellcheck. Done when: the tests pass, and shellcheck reports no warnings.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack