A Full Script Override Instead of a Hook DSL

Why customizing a bosun deploy means copying and editing a real bash script, not learning a plugin system — and a worked example swapping Sidekiq for a RabbitMQ consumer.

Most deploy tools handle customization with hooks: before_symlink, after_deploy, a chain of named callbacks you register into. That's a real DSL to learn, with its own execution order and edge cases, for what's often a small, one-off need. Bosun takes a different position: the built-in do-release manages exactly Puma + Sidekiq, unconditionally, with no configuration knob for the common case — and when one specific app needs something else, you don't configure around the edges, you copy the whole script and edit it.

How the override actually works

cp /usr/lib/bosun/deploy/do-release.sample /var/www/myapp/shared/do-release
chmod +x /var/www/myapp/shared/do-release
vi /var/www/myapp/shared/do-release        # it's your script now, edit freely

bosun deploy myapp <branch> checks for shared/do-release first and, if it's present and executable, execs that instead of the built-in default — for myapp only; every other app on the box keeps using the default, untouched. Copied and unedited, it behaves identically to the built-in script, so the first useful step after copying it is deploying once with zero changes, to confirm the override wiring itself works before you start customizing. If an app has no override at all (or one that exists but isn't executable), a recent version of do-release prints a one-line, non-blocking warning and proceeds with the built-in default anyway — a safety net against a forgotten chmod +x, not a hard stop.

What you actually get: real bash, same safety rails

This is a full replacement, not a hook — your script owns the entire deploy from the moment it's invoked, so it can do anything a whitelisted developer/admin already can: different services, extra build steps, a health check, a notification, running a worker via docker instead of systemd. What it can't do is grant new privileges — every sudo call your override makes is still checked against the exact same developer/admin sudoers whitelist as everything else bosun does. Writing your own script doesn't add to that whitelist; it only lets you rearrange what already fits inside it.

Worked example: swapping Sidekiq for a sneakers consumer

Developers/admins have no whitelisted way to create a new systemd unit file themselves — so a third service needs either an admin to hand-create one (following the exact same template bosun add uses for Puma/Sidekiq), or docker instead, which is already fully whitelisted and needs no unit file at all:

sudo docker rm -f sneakers-myapp 2>/dev/null || true
sudo docker run -d --name sneakers-myapp --restart unless-stopped \
  -v "$APP_HOME/current:/app" -w /app --env-file "$ENV_FILE" \
  your-ruby-image bundle exec rake sneakers:run

Then, in your do-release override: rename every *_worker function/variable to match (e.g. WORKER_UNIT → the container/unit name), and swap the systemctl stop/start/health-check calls for docker stop/start/inspect wherever they appear. The rest of the pipeline — clone, build, symlink, rollback-on-failure, cleanup — stays exactly as it was. Full walkthrough, including the systemd-unit path and the logging convention every bosun-managed worker follows, in adding a custom service.

Further reading