PHP/MySQL Website Development and Production Environment Setup

Posted: Monday, January 2nd 2012 by Jeff Sturgis

This tutorial is for above average Linux users. It is described under generic Linux conditions so that it may be used across a variety of systems. Aside from DBCompare, the software dependencies should be easy to find through any package manager or by googling the packages themselves.

Software Dependencies:

There are many vulnerabilities in source code. SQL Injections, XSS Attacks, Buffer Overflows to name a few. Over time, these vulnerabilites become widely known and well documented. It is very important to keep your software upto date to ensure there exists as little documentation as possible about the vulnerabilities on your systems.

  • PHP - latest version
  • MySQL - latest version
  • Subversion (svn)
  • Rsync
  • DBCompare

Website Management Pieces

When you build a website, you have different pieces that need to be handled. Images, Javascript, Stylesheets, Source Code and Data all need to be configured in an easily manageable way. Here is a list of what tools we use to manage each piece of the website:

Website PieceManagment Tool
Config FilesManual
ImagesRSync or svn
User Uploaded FilesRSync
CSSsvn
Javascriptsvn
PHPsvn
DatabaseDBCompare

Config Files

Config Files need to be omitted from svn repositories. Everything you need to be different on the development environment and production environment should be stored in your config files. This includes database connection, system paths, url paths, development environment flags etc. By doing this, you can connect to a different database in your development environment, you can have your development environment in a different webroot, you can set flags so that your development environment doesn't use https. This way on the production environment, if you are using an SSL certificate, you can cookie users with an encrypted flag, but in the development environment you cookie them without.

Images

If users upload images or anything else, you should use rsync to maintain these files. That way, they stay out of the subversion repository and reduce clutter. You may from time to time need to sync uploaded files back to the development environment so that you can test. This is especially true if you store uploaded file information in your database. Another reason that I sometimes do not put the images into subversion is because I can create different skins for the development and production environments. This makes it blatently obvious to me which environment I am working in and can save you a lot of time refreshing the wrong site and expecting your changes to happen.

Otherwise, if you are using static images and you want to have subversion manage them, it isn't a bad idea. The only reason to definately not use svn to manage your images is if they are uploaded by users.

CSS/Javascript/PHP

CSS, Javascript and PHP can all be managed by svn. This allows you to make changes in your development environment, commit your changes with comments so you can trace them back later, revert your changes if need be and update your production environment quickly and easily.

Database

The database can be tricky. Here are some ways that your production environment can break if you have inconsitencies with your database:

  • If code is committed and updated in the production environment which refers to tables or fields that do not exist, it will cause MySQL to fail and this will certainly affect the user experience.
  • If data which is used for configuration of the site is not updated to the production environment, it could force things to load improperly, or even grant users access that they shouldn't have.

Some rules of thumb when designing databases:
Don't use antipermissions. An antipermission is when you give something to everybody, but revoke it to a few people on a case by case basis. For example: If you were to give super user access to everybody except this list of people, and you forget to move the database over that specifies who doesn't get it, then everybody on the site would have super user access. But if you design it so that nobody has super user access except for this list of people and you forget to move the data over, then nobody has super user access and there is no unauthorized access.

Development Environment Setup

  • create the svn repository on the development server
    svnadmin create /var/svn/example.com
  • checkout the repositor on a user by user basis svn co file:///var/svn/example.com

This will create a directory called example.com. Go into that directory. Make a directory html for your website. Here is how I usually setup my website structure:

example.com/html example.com/crons example.com/ssl_certificates example.com/config example.com/lib example.com/uploads

The html directory is your webroot. The other directories are optional depending on what you are doing with your website. I recommed that if your site is going to run crons, to keep the crons out of the webroot. That way you don't have to worry about people running your crons.

If you are going to have ssl_certificates, placing them in the example.com directory allows you to find them easily if/when the ssl certificates expire and need to be replaced. SSL certificates aren't really necessary for your development environment, you may not want to store them in your development environment if you are worried about developers gaining access to your private key. Generally developers have fairly low level access and this comes with a great deal of trust. But use your judgement here.

The config directory is a directory that you will keep out of your svn repository. To do this run: svn propset svn:ignore config . This will omit the config directory from being updated on the production environment. Again, the production environment should have it's own configuration. This allows you to have a seperate production database etc.

The lib folder is a place where you store your php libraries. By putting the directory here, you can access the libraries from the crons as well as the webroot.

The uploads folder is a directory that would be owned by the webserver, ie: apache or www-data etc. This is an optional directory which is used on websites that have users uploading videos, images, files or what have you. By keeping the uploads directory out of the html directory, you keep the subversion cleaner. You can add the uploads directory as a symbolic link from within the html folder. cd html ln -s ../uploads This will allow you to add the symbolic link to the subversion repository but keep the contents out.

Once you have done this add the html, crons and lib directory to your svn repositories. cd ~/example.com svn add html crons lib svn commit -m "added html crons and lib directoies"

Development Environment System Configuration

On a development server, I recommend leaving errors on. That is PHP and MySQL errors should display to the screen. When you setup the webserver for the development environment, use a different host name such as: stage.example.com In the html directory, you will want to either lock it down with htpasswd or drop a robots.txt file in denying crawlers. The last thing you want is your development environment ranking higher in google than your production environment. Example Apache Configuration:

NamedVirtualHost 199.199.199.199:80 <VirtualHost 199.199.199.199:80> ServerName stage.example.com DocumentRoot /home/user/example.com/html RewriteEngine On RewriteOptions Inherit <Directory /home/user/example.com/html> Options -Indexes </Directory> </VirtualHost>

Production Server Setup

  • You should have a place where you have all your websites. Such as /sites mkdir /sites cd /sites
  • check out the svn repository svn co svn+ssh:///stage.example.com/var/svn/example.com ./

This will creat the example.com directory and the html, crons and lib subdirectories. Go ahead and create the uploads directory

chown apache: uploads

Make your ssl_certificates directory if you are going to use ssl_certificates and put your ssl certificates in there. Create your config directory and put your production database and site configuration data in a config.php file. Configure your apache to receive www connections and 301 redirect all non-www connections to www. This ensures that all the links to your website get full credit to the pages they link to. The alternative is that somebody may link to www.example.com and somebody else links to example.com and the linking power is split. When this happens your pages are competing with each other for page rank even though they are the same page.

NamedVirtualHost 199.199.199.200:80 <VirtualHost 199.199.199.200:80> ServerName www.example.com DocumentRoot /sites/example.com/html RewriteEngine On RewriteOptions Inherit <Directory /sites/example.com/html> Options -Indexes </Directory> </VirtualHost> <VirtualHost 199.199.199.200:80> ServerName example.com RewriteEngine On RewriteCond %{HTTP_HOST} ^example.com RewriteRule (.*) http://www.example.com/$1 [R=301,L] </VirtualHost>

Production Server System Configuration

Ensure your PHP and MySQL errors are turned off and instead logged to a file. For PHP, you would edit your php.ini file and set

log_errors = On error_log = /sites/logs/php_errors.log

Setup a cron to empty and mail you the php and mysql error logs nightly. Assuming you are using apache, you may as well enable mod-deflate. This module will compress your web content for compatible browsers, making a better user experience by increasing your page speed. Additionally, you should set your .htaccess file to set your file type expirations. By doing this, you tell browsers how long to cache your content. When browsers cache your content, you give the user a faster experience and also increase your page speed.

Pushing Your Changes Live

First we are going to commit our source code changes. Committing changes are harmless. The changes are only being stored in the subversion repository. You have to update the production environment afterwards to put the subversion changes live. First let's look at how to commit our development environment changes.

Committing Development Environment Changes

When you are done building something in your development environment, you can see what files you edited by running:

svn status

If the file has an M beside it, it means it was modified. If you don't remember why the file was modified you can run:

svn diff

This will tell you what lines were removed (-) or added (+) to the file. If the file has a ? beside it, it means it has not yet been added to the subversion repository. Make sure all the files you want to go live are added by running:

svn add <file>

When you are satisfied, you run:

svn commit -m "reason for changes"

Now your changes should be in the repository. It will take 1 second to pull down the repository from the production environment, but before we do that, lets make sure our database schema is upto date.

Updating your Database Schema

Pushing the Changes Live Once you have the sql differences, you can paste import them into the production database through your method of choice. Soon after that, you need to update your production enviroments subversion by running

svn up

This will prompt you for a password. You can prevent it from asking you for a password everytime by setting up ssh without a password. But I leave it in because I find it more intentional. It gives me a chance to think about what I am doing and confirm that I really want to update the live environment.

Thats it! Most websites only need to manage the code and database. Sometimes though, you may do some things that require auto-maintenance. For example, on a couple websites, I have crons that run which pull xml feeds and populate the database and also fetch images. In this situation, I prefer to run the crons on the development server, connect to the live database from the development server and sync the images to the production server. To do this, I have a folder example.com/cron_images I add a symbolic link from example.com/html/img to example.com/cron_images If I have any new images, the cron will run: rsync -avz /home/user/example.com/cron_images cronman@www.example.com:/sites/example.com/cron_images This will ensure the files on the production server are up to date.

I hope this helps you avoid rookie mistakes that took me a long time to learn. Good luck with your websites!

File Resources: download zipdev-setup.zip

This file contains tools to setup a proper development/production environment. It contains a DB class which logs mysql errors, config generator script for php and apache configuration on development and production servers. Lastly it contains a script to compare the schema between the development and production environment to further minimize errors on the production side.

Listed Under:

Web Development Development Environments PHP/MySQL Development Production Environments Scalable Web Design Principles System Administration

Keywords

php/mysql development environment, php/mysql production environment, professional php/mysql system configuration, professional php/mysql environments, scalable php/mysql server solutions

Comments

Add Comment