Capistrano is a great tool for running batches of shell commands on remote servers. It’s mostly used in the Rails community, but is helpful for deploying non-rails apps, or even running commands unrelated to web apps at all.

All our apps are run on Solaris servers and managed by SMF, and we use a series of manifests to control each individual thin instance (named thin/port4000…thin/port4014). Getting Capistrano to play with SMF (so we can restart the app servers with the new code) is luckily pretty simple. We could create our own spin and reaper scripts, but it’s nicer to keep the commands in the deploy script. We can tell Cap to run our commands like this:

namespace :deploy do
  task :start, :roles => :app do
    run "/usr/sbin/svcadm enable network/thin/*"

The stop task is similar, but calling svcadm with disable instead. The majority of the time we will be deploying a new version of the app to production, and it’s the restart task that gets called. Restart can be composed of the stop and start tasks:

namespace :deploy do
  task :restart, :roles => :app do

By default, SMF only allows the root user to control SMF managed processes. For security we disable root logins over ssh, so we need a way for lower privileged users to control our process instances. Role Based Access Control (RBAC) is a clean way of allowing a user to perform specific tasks. To begin, we need to add a new authorisation. Add this line to the end of /etc/security/auth_attr:

solaris.smf.manage.thin:::Manage Thin::

This is simply to tell Solaris there is a new authorisation – we could have named it anything. To be able to control SMF using this authorisation, we need to apply it the instances we want to control. There are two types of authorisation we need to apply to each instance: the action authorisation, and the value authorisation. Action is used to perform an action on an instance (e.g restart), value is used to change a value on an instance (e.g set the enabled/disabled state). We need to do this once for each thin instance we are controlling:

svccfg -s network/thin/port4000 setprop general/value_authorization=astring: 'solaris.smf.manage.thin'
svccfg -s network/thin/port4000 setprop general/action_authorization=astring: 'solaris.smf.manage.thin'

Finally we need to apply this authorisation to the user we want to give control to:

usermod -A solaris.smf.manage.thin admin

Admin will now be able to completely start and stop our thin instances now:

svcadm restart network/thin/port4000
svcadm enable network/thin/port4000
svcadm disable network/thin/port4000
svcadm refresh network/thin/port4000