The definitive guide of Symfony 1.2

16.5. Deploying Applications

Symfony offers shorthand commands to synchronize two versions of a website. These commands are mostly used to deploy a website from a development server to a final host, connected to the Internet.

16.5.1. Freezing a Project for FTP Transfer

The most common way to deploy a project to production is to transfer all its files by FTP (or SFTP). However, symfony projects use the symfony libraries, and unless you develop in a sandbox (which is not recommended), or if the symfony lib/ and data/ directories are linked by svn:externals, these libraries are not in the project directory. Whether you use a PEAR installation or symbolic links, reproducing the same file structure in production can be time-consuming and tricky.

That's why symfony provides a utility to "freeze" a project — to copy all the necessary symfony libraries into the project data/, lib/, and web/ directories. The project then becomes a kind of sandbox, an independent, stand-alone application.

> php symfony project:freeze symfony_data_dir

The symfony_data_dir argument is the path to the symfony data directory (if you installed symfony via Subversion or an archive, this directory is in the same directory as symfony lib; if you installed the symfony PEAR package, this directory is located in the PEAR data directory).

Once a project is frozen, you can transfer the project directory into production, and it will work without any need for PEAR, symbolic links, or whatever else.

[tip] Various frozen projects can work on the same server with different versions of symfony without any problems.

To revert a project to its initial state, use the project:unfreeze task. It erases the data/symfony/, lib/symfony/, and web/sf/ directories.

> php symfony project:unfreeze

Note that if you had symbolic links to a symfony installation prior to the freeze, symfony will remember them and re-create the symbolic links in the original location.

16.5.2. Using rsync for Incremental File Transfer

Sending the root project directory by FTP is fine for the first transfer, but when you need to upload an update of your application, where only a few files have changed, FTP is not ideal. You need to either transfer the whole project again, which is a waste of time and bandwidth, or browse to the directories where you know that some files changed, and transfer only the ones with different modification dates. That's a time-consuming job, and it is prone to error. In addition, the website can be unavailable or buggy during the time of the transfer.

The solution that is supported by symfony is rsync synchronization through an SSH layer. Rsync (http://samba.anu.edu.au/rsync/) is a command-line utility that provides fast incremental file transfer, and it's open source. With incremental transfer, only the modified data will be sent. If a file didn't change, it won't be sent to the host. If a file changed only partially, just the differential will be sent. The major advantage is that rsync synchronizations transfer only a small amount of data and are very fast.

Symfony adds SSH on top of rsync to secure the data transfer. More and more commercial hosts support an SSH tunnel to secure file uploads on their servers, and that's a good practice to avoid security breaches.

The SSH client called by symfony uses connection settings from the config/properties.ini file. Listing 16-19 gives an example of connection settings for a production server. Write the settings of your own production server in this file before any synchronization. You can also define a single parameters setting to provide your own rsync command line parameters.

Listing 16-19 - Sample Connection Settings for a Server Synchronization, in myproject/config/properties.ini

[symfony]
  name=myproject
 
[production]
  host=myapp.example.com
  port=22
  user=myuser
  dir=/home/myaccount/myproject/

Note Don't confuse the production server (the host server, as defined in the properties.ini file of the project) with the production environment (the front controller and configuration used in production, as referred to in the configuration files of an application).

Doing an rsync over SSH requires several commands, and synchronization can occur a lot of times in the life of an application. Fortunately, symfony automates this process with just one command:

> php symfony project:deploy production

This command launches the rsync command in dry mode; that is, it shows which files must be synchronized but doesn't actually synchronize them. If you want the synchronization to be done, you need to request it explicitly by adding the --go option.

> php symfony project:deploy production --go

Don't forget to clear the cache in the production server after synchronization.

Tip As of symfony 1.1, the php.yml configuration file has been removed.

The only setting you will have to check by hand is log_errors, which was set to on by php.yml.

php.yml is replaced by the check_configuration.php utility you can find in he data/bin folder. It checks your environment against symfony requirements. You can launch it from anywhere:

$ php /path/to/symfony/data/bin/check_configuration.php

Even if you can use this utility from the command line, it's strongly recommended to launch it from the web by copying it under your web root directory as PHP can use different php.ini configuration files for the command line interface and the web.

16.5.3. Ignoring Irrelevant Files

If you synchronize your symfony project with a production host, a few files and directories should not be transferred:

  • All the version control directories (.svn/, CVS/, and so on) and their content are necessary only for development and integration.
  • The front controller for the development environment must not be available to the final users. The debugging and logging tools available when using the application through this front controller slow down the application and give information about the core variables of your actions. It is something to keep away from the public.
  • The cache/ and log/ directories of a project must not be erased in the host server each time you do a synchronization. These directories must be ignored as well. If you have a stats/ directory, it should probably be treated the same way.
  • The files uploaded by users should not be transferred. One of the good practices of symfony projects is to store the uploaded files in the web/uploads/ directory. This allows you to exclude all these files from the synchronization by pointing to only one directory.

To exclude files from rsync synchronizations, open and edit the rsync_exclude.txt file under the myproject/config/ directory. Each line can contain a file, a directory, or a pattern. The symfony file structure is organized logically, and designed to minimize the number of files or directories to exclude manually from the synchronization. See Listing 16-20 for an example.

Listing 16-20 - Sample rsync Exclusion Settings, in myproject/config/rsync_exclude.txt

.svn
/cache/*
/log/*
/stats/*
/web/uploads/*
/web/frontend_dev.php

Note The cache/ and log/ directories must not be synchronized with the development server, but they must at least exist in the production server. Create them by hand if the myproject/ project tree structure doesn't contain them.

16.5.4. Managing a Production Application

The command that is used most often in production servers is cache:clear. You must run it every time you upgrade symfony or your project (for instance, after calling the project:deploy task), and every time you change the configuration in production.

> php symfony cache:clear

Tip If the command-line interface is not available in your production server, you can still clear the cache manually by erasing the contents of the cache/ folder.

You can temporarily disable your application — for instance, when you need to upgrade a library or a large amount of data.

> php symfony project:disable APPLICATION_NAME ENVIRONMENT_NAME

By default, a disabled application displays the $sf_symfony_lib_dir/exception/data/unavailable.php page, but if you create your own unavailable.php file in your project's config/ directory, symfony will use it instead.

The project:enable task reenables the application and clears the cache.

> php symfony project:enable APPLICATION_NAME ENVIRONMENT_NAME