Multi-Tenant Rails Deployment Without Root or a Personal SSH Key

The developer/deployer/admin tier model argus-tty provides and bosun enforces, and the shared per-app git deploy key that replaces everyone's own key.

A single-developer deploy script doesn't need to think about "who is allowed to do this" — there's one person, with one key, who can do everything. The moment a second developer, a dedicated deployer (or a CI pipeline), and an admin all need different levels of access to the same box, that assumption breaks, and most deploy tools don't try to fix it — they assume you've solved it separately (a shared SSH key, a CI token with full access, everyone just using sudo). Bosun is built specifically for the box that several real people share.

Three tiers, enforced per command

argus-tty (the package bosun depends on) manages three account tiers. Bosun's require_role() checks every one of its own subcommands against the caller's active session groups — not just sudoers, which only covers the handful of root-requiring calls (systemctl, apt-get, docker). The actual clone/ bundle install/symlink/console work is plain Unix file permissions under the webapps group, which every tier shares — without require_role(), a deployer-only account could open a full Rails console (and every secret in it) just as easily as a developer could run deploy, even though neither is supposed to.

Commanddeveloperdeployeradmin
add (provision an app)——root only
install / setup✓—✓
run (console/rake) / logs✓—✓
deploy / cleanup—✓✓
version (diagnostic, no secrets)✓✓✓

A plain developer can't deploy or prune releases; a plain deployer can't open a console, run a migration by hand, or install a new app's dependencies. Each tier gets exactly the access its job needs — not everything, and not nothing.

One deploy key per app, not one per person

deploy needs to git clone the app's repo, which normally means SSH access to that repo for whoever runs it. The usual answer — every admin/deployer using their own personal key — means whitelisting N different keys on the git host, and losing access the moment someone's key rotates or they're offboarded. bosun add generates one ed25519 keypair per app instead, and distributes an individually-owned 600 copy into every current admin/deployer account's own $HOME automatically:

sudo bosun add myapp
# ── Generated git deploy key for 'myapp' ──
# Add this PUBLIC key as a read-only Deploy Key on 'myapp's git repo:
#
# ssh-ed25519 AAAA... bosun@myapp
#
# Distributed 'myapp' deploy key to 2 admin/deployer account(s).

One key, one place to revoke it (remove it from the git host's Deploy Keys), and developers deliberately never get a copy — require_role() already blocks a plain developer from running deploy at all, so handing them a readable copy of the key anyway would be pure unnecessary exposure, especially since the same key is often what a CI pipeline uses too, via a dedicated deployer account.

Onboarding a new person doesn't mean re-keying anything

Add the Linux account (sudo argus-tty add alice ...), then re-run sudo bosun add myapp for each app they need — it backfills their copy of that app's existing deploy key without regenerating it or touching anything already provisioned (.env, deploy.conf, systemd units). Nothing on the git host ever needs to change for a new team member.

Further reading