Here at Cloud 66 we've been building/deploying/maintaining Ruby on Rails (and Rack) applications for more than 6 years now! And during that time we've seen a lot of change; not only in our own adherence to best practice principles, some of which themselves becoming more prominent over time, but also in the requirements of the frameworks themselves.
When we first started for example, we were deploying pre-asset pipeline Rails on non-semantic versions of Ruby. Since then a lot has changed and we're pretty pleased with where we are now; We're deploying asset-pipeline Rails (oh asset pipeline; angel to some, devil to others) on semantic versions of Ruby, and using groups with permissions to ensure that web applications can see and write to shared resources that might be required by it and back end processes, but not overwrite the application code itself.
Recently we've been getting more frequent support tickets detailing strange things happening during deployments. They have reported two main things:
a) applications are reporting permission errors during deployment
b) deployments are taking significantly longer than before
So what has changed? We dug deep into the process and realized the root cause.. but first; reviewing our code deployment which is essentially (massively distilled) as follows:
a) create the application on the user's server
b) perform operations (asset pipeline compilation, sym-link, ...etc)
c) apply the relevant permissions for application files
So what could be done... the simplest solution would simply to have been to create the application AS the web user. This would mean that all permissions would be correct at the time the code was created; no mess no fuss! Unfortunately there is a mess! If the code is created as the web user, then that means the web user would be able to write files in its own application path. This isn't great practice... and this is why: Although modern web application frameworks (like Rails) take security very seriously; it is not impossible to envisage a user mistake in the application code itself that allows an intruder to modify files on the server. While the web user is a non-permissioned user, this isn't an issue. However, if the web user has write access they can modify application files maliciously in the application core, changing the application to do something else etc. So we definitely want to add a second level of protection at an infrastructure level to prevent this as much as possible!
So, what we decided to do was rely on native Linux permissions to get to what we need. Cue user groups and the setgid flag! We already have a group that allows frontend/backend shared access (this enables background processes to share resources with frontend processes for example). So what we do is we permission group ownership of the shared resource endpoint location with a setgid group. Any assets will ultimately be created and reside here. And now when they are created they automatically have the correct permissions!
We've rolled this code out now; and voila! Deployments are nice and snappy again... and still secure! Hooray for permissions!