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.
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.
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.
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.