This is the ideal server configuration for the easiest deployment possible. When deployment is time-consuming and error-prone, there is a resistance to deploying frequently. Our requirements are: Several programmers are working on the same machine, and pushing their changes to a shared git repository. Production code may or may not be hosted on the same machine as development and test environments. Developers must not be able to read database passwords for the live environment. Developers must be able to run shell scripts, not only web scripts through apache. Our directory structure is this: /sites/mydomain/mydomain.git/ /sites/mydomain/conf/ /sites/mydomain/conf/config.php /sites/mydomain/conf/live-constants.php /sites/mydomain/conf/test-constants.php /sites/mydomain/conf/dev-constants.php /sites/mydomain/live/ /sites/mydomain/test/ /sites/mydomain/somedeveloper/ /sites/mydomain/someotherdeveloper/ /sites/mydomain/v2.0/ /sites/mydomain/v2.1/ (If two different machines are being used, mydomain/live and mydomain/test are on the production machine.) Apache virtual hosts would be configured such that: `www.mydomain.com` and `mydomain.com` are served from `/sites/mydomain/live` `test.mydomain.com` is served from `/sites/mydomain/test` `somedeveloper.mydomain.com` is served from `/sites/mydomain/somedeveloper` `someotherdeveloper.mydomain.com` is served from `/sites/mydomain/someotherdeveloper` `/sites/mydomain/somedeveloper` is owned by user `somedeveloper` `/sites/mydomain/someotherdeveloper` is owned by user `someotherdeveloper` The other directories are owned by `admin`. `/sites/mydomain/live` is a symbolic link pointing to `/sites/mydomain/v2.0` (the currently deployed version) `/sites/mydomain/test` is a symbolic link pointing to `/sites/mydomain/v2.1` (the new version being tested for deployment) We have a custom `git-export` shell script which can copy all files controlled by a repo into its own directory. We would do this within `/sites/mydomain`: git export mydomain.git v2.1 ln -snf v2.1 test This is how we deployed the latest code to `test.mydomain.com`. If the production machine is different from the dev machine, we have the added step of copying v2.1 to another machine before changing the symbolic link on that machine. Once this code has been tested, we deploy it to `www.mydomain.com` by running: ln -snf v2.1 live Deployment is instantaneous. Eventually we'll be able to `rm -rf v2.0`. In case we need to run SQL queries at deployment, we'd do something like: ln -snf upgrading live mysql < sql/v2.1.sql ln -snf v2.1 live The contents of the `upgrading` directory is a transient version of the web site which just tells visitors that the site is being upgraded. It could temporarily serve data from another database, while prohibiting writing to the database for the duration of the upgrade. Now, this is how the configuration is handled. Every script (shell and web) begins by including `/sites/mydomain/conf/config.php`, which does the following: It reads the directory of the script that included it, and sets the `SERVER_ENV` constant based on the directory: For `/sites/mydomain/live`, `SERVER_ENV` becomes `live` For `/sites/mydomain/test`, `SERVER_ENV` becomes `test` For anything else, such as `/sites/mydomain/somedeveloper` and `/sites/mydomain/someotherdeveloper`, `SERVER_ENV` becomes 'dev'. Then `config.php` includes either `live-constants.php`, `test-constants.php`, or `dev-constants.php`. Each of those files cannot be read by all, but can be read by its group. `live-constants.php` and `test-constants.php` are owned by the `admin` group. `dev-constants.php` is owned by the `dev` group. `somedeveloper` and `someotherdeveloper` belong to the `dev` group and are able to read `dev-constants.php`, but they cannot read the other two files. We use apache's `mod_privileges` module to have apache run as different users for different virtual domains: `www.mydomain.com` and `domain.com` would be run by `httpd-live` which belongs to the `admin` group and is thus able to read `live-constants.php`. `somedeveloper.mydomain.com` and `someotherdeveloper.mydomain.com` would be run by `httpd-dev` which belongs to the `dev` group and is thus able to read `dev-constants.php` but not the other two files. `somedeveloper` can run their own scripts in two ways: by requesting them via `http://somedeveloper.mydomain.com` or by running them from the shell. In either case, they will begin by including `/sites/mydomain/conf/config.php` in order to define constants like `DB_PASSWD`. Since both `somedeveloper` and `httpd-dev` belong to the `dev` group, and this group has read permissions on `dev-constants.php`, both methods will work. But `somedeveloper` will have no way of reading `live-constants.php` (unless the admin deploys their code to live without reading it, and that would leave evidence in the git repo). If there are files which the web site needs to access that are not under git control, such as media files uploaded by users, the paths to these files are set by the `conf/*-constants.php` files. The code could then reference these files like `MEDIA_DIR.'/'.$myfile`. The various `MEDIA_DIR` directories would have the same access restrictions as their `conf/*-constants.php` files. For example, if each has its own temp and logs directories, we could have: /sites/mydomain/log/live/ /sites/mydomain/log/test/ /sites/mydomain/log/dev/ /sites/mydomain/tmp/live/ /sites/mydomain/tmp/test/ /sites/mydomain/tmp/dev/ /sites/mydomain/media/live/ /sites/mydomain/media/test/ /sites/mydomain/media/dev/ With `TEMP_DIR`, `LOG_DIR`, and `MEDIA_DIR` defined by the `conf/*-constants.php` files. You can always split up `dev` into `somedeveloper` and `someotherdeveloper` if needed.