User/User_web strategy of DreamHost website deployment -- DreamHost best practices

Introduction

When I first signed up for DreamHost account, I understood, but wasn't overly fond of the way they ran web requests.

All requests to a deployed website on DreamHost are made in the context of the user owning the website.  That is, if a website is deployed under user 'X', calls into that website are performed as user 'X'.  This allows DreamHost to isolate security breaches to the user of the (defective) website.  However, this also has implications for those who use canned software (like Drupal) -- if a defect is found and a website is comprimised, files within that software could be modified as the call is done as the owning user.  Setting restrictive permissions on the file doesn't help as the files are owned by the calling user and (in a truly compromised environment) the file permissions could be modified.  On a traditional system, this wouldn't be an issue as web-initiated calls would be made by the (highly restricted) apache (et. al.) user with permission to only read (and not write) only those files to which it needed to have access.

What follows is the scheme I ended up coming up w/ to work around this issue.  (Other issues continue to exist of course, this is just my solution for this one particular one.)  In this discussion, I'll talk about Drupal sites; but the scheme is the same regardless of what files are deployed on a site.  The initial setup had only my primary user that owned all sites and files.  The files for my Drupal site ("site") were kept in a directory webroot/drupal/<sitename> (relative to the primary user's home directory).

The Scheme Summary

The scheme involves creating two users, the "user" user and the "web" user.  The "user" user will own the files comprising the website.  Those files will reside in a subdirectory of the "web" user's home directory.  These directories and files will be chmod'ed as group readable but not group writable (save those files that will be edited by the website and directories that will be written to.)  The "web" user will be the website "run as" user (as defined in the DreamHost domain edit screen).  Because the website directories/files were group readable (only), the calling user (the "run-as" user) can read, but not write access to the site's files, and the site functions correctly.  The site's files cannot to be modified during a web call.  This returns functionality to a semblance of a traditional web scenario.

Implementing It

Note: in this discussion I use the naming convention 'site_user' for the "user" user and 'site_web' for the "web" user where the token 'site' is something that identifies the site or sites being hosted by that user pair.  (See also this note on using only ssh to shell to another user.)  For this scheme to work, the "Enhanced User Security" must be turned off on the user edit screen in the DreamHost panel.  Note that this whole scheme works because DreamHost puts all users for the same account on the same box.  It is also possible to have your primary account be the "user" user rather than creating a new user for this role.  If electing this, just ignore any steps to 'ssh site_user@<sitename>' below....

Here are the steps I followed:

  1. Start by creating the two user accounts, 'site_user' and 'site_web', both with simple to use passwords.  (Changing their passwords will be done at the end.)
     
  2. Log in as site_web and the user's home directory to be group-writable.
    $ ssh site_web@<sitename>
    ....authenticate
    $ chmod g+w ~
    $ exit
     
  3. As user site_user, creat a directory in site_web's home dir called "webroot" and set the permission to 0751.   Then, create a symlink in site_user's home directory to the 'webroot' dir in site_web's home directory.  This will allow site_user to conveniently access the files
    $ ssh site_user@<sitename>
    ....authenticate
    $ cd ~site_web
    $ mkdir webroot
    $ chmod 0751 webroot
    $ cd
    $ ln -s ~site_web/webroot .
    $ exit

    At this point, site_user can create new site files in ~/webroot (or a subdirectory).

  4. Now, remove the group writable permission from site_web's home directory, resetting it to its initial state.  This is necessary so that the .ssh directory will be used by the sshd (which is central to my scheme of using only ssh to switch between users.)  (This obscure bit of ssh functionality cost me an hour of beating my head against a wall.)
    $ ssh site_web@<sitename>
    ....authenticate
    $ chmod g-w ~
    $ exit
     
  5. After the files are in place, create the domain entry for the new site and set user site_web to own the website.  The 'web directory' (the directory from which the site is served) should be under the 'webroot' tree.  It is important to not create the domain entry before placing the files (or at least the upper directory) as DreamHost will create an empty directory for you as the run-as user (in this case site_web) if it does not already exist.  This would break the sceme -- we want site_user to own that directory (and all subdirectories/files, not site_web.
     
  6. Once the files are in place, set permissions of all subdirectories/sub-files to be group-readable; but not group writable.
    $ ssh site_user@<sitename>
    ....authenticate
    $ cd <site root directory of site>
    $ chmod 0751 .
    $ find . -type d -exec chmod 0751 {} \;
    $ find . -type f -exec chmod 0644 {} \;
    $ exit
     
  7. If there are any files/directories in the site's tree that need to be writable by the site, those need to be group writable.  An example is the 'files' directory on a Drupal site.

UPDATE: After this was written, I added an article on setting up a ssh based system for the navigation between accounts.
See node/23
 

 

Comments

The functionality described

The functionality described in this post is now available in the setupUserPair.sh script -- a part of my DreamHost script library.