Fork me on GitHub

Capistrano is an open source tool for running scripts on multiple servers. It’s primary use is for easily deploying applications. While it was built specifically for deploying Rails apps, it’s pretty simple to customize it to deploy other types of applications. This project is a deployment recipes collection that works with both symfony and Symfony2 applications.

1. Install script

First, install capifony itself with RubyGems:

$> gem install capifony

2. Setup project

Setup initial deployment configuration for your project:

$> cd to/symfony1/or/Symfony2/project/path
$> capifony .

This will create a Capfile in your project root & a deploy.rb config file in config/ (for symfony1 projects) or app/config/ (for Symfony2 projects).

3. Configure

Fill up your config/deploy.rb (or app/config/deploy.rb) with your server connection data. But first, you must choose your deployment strategy.

a) deployment → scm → production

The first strategy involves deployment to a production server via an intermediate git repository server. In this case, the production server must have access to your git repository (remote or not) and be able to issue a "pull" from it. You must have ssh access to the production server from wherever you're deploying from: deployment strategy a

# deploy.rb

set   :application,   "My App"
set   :deploy_to,     "/var/www/my-app.com"
set   :domain,        "my-app.com"

set   :scm,           :git
set   :repository,    "ssh-gitrepo-domain.com:/path/to/repo.git"

role  :web,           domain
role  :app,           domain
role  :db,            domain, :primary => true

set   :use_sudo,      false
set   :keep_releases, 3

In this case, on every cap deploy, capifony will:

  1. ssh to production (my-app.com)
  2. create a new release path (/var/www/my-app.com/releases/...)
  3. clone the latest project version from the remote git repo (ssh-gitrepo-domain.com)
  4. copy the source code, pulled from git, into the release path
  5. run deployment hooks (cache:warmup, cc, etc.)

b) deployment → production (via copy)

The second strategy involves deployment to a production server right from your deployment machine via a copy. In this case, the deployment server (which may just be your local computer) must have access to the git repository (remote or not) and be able to pull from it. The deployment server must also have ssh access to the production server: deployment strategy a

# deploy.rb

set   :application,   "My App"
set   :deploy_to,     "/var/www/my-app.com"
set   :domain,        "my-app.com"

set   :scm,           :git
set   :repository,    "file:///Users/deployer/sites/my-app"
set   :deploy_via,    :copy

role  :web,           domain
role  :app,           domain
role  :db,            domain, :primary => true

set   :use_sudo,      false
set   :keep_releases, 3

In this case, on every cap deploy, capifony will:

  1. ssh to production (my-app.com)
  2. create a new release path (/var/www/my-app.com/releases/...)
  3. clone the latest project version from the local git repo
  4. copy the source code, pulled from git, onto the production server via wires
  5. run deployment hooks (cache:warmup, cc, etc.)

Of course, copying the whole project on every deploy is very expensive and slow. Fortunately, you can optimize things with the capistrano_rsync_with_remote_cache gem:

$> gem install capistrano_rsync_with_remote_cache

Now, change your deployment strategy in deploy.rb:

set :deploy_via, :rsync_with_remote_cache

In this case, rsync will create a cache on your production server and will push only files that have changed between deploys.

4. Setup server

Now, you can start the deployment process! To get your server setup with the directory structure that Capistrano expects, CD to your local project directory and run:

$> cap deploy:setup

(You'll only have to run this once!)

This command will create the following approximate directory structure on your server. The exact structure will depend on if you're deploying a symfony1 or Symfony2 application:

`-- /var/www/my-app.com
  |-- current → /var/www/my-app.com/releases/20100512131539
  |-- releases
    |-- 20100512131539
    |-- 20100509150741
    `-- 20100509145325
  `-- shared
    |-- log
    |-- config
      `-- databases.yml
    `-- web
      `-- uploads
        

The folders in the releases directory will be the actual deployed code, as timestamped directories. In a symfony1 application, for example, Capistrano symlinks your log & web/uploads directories from your app to the directories in the shared folder so that it doesn’t get erased when you deploy a new version of your code.

5. Deploy!

To deploy your application, simply run:

$> cap deploy

Depending on your setup, you may need to ssh onto your server to setup additional, shared files after your first deployment (e.g. app/config/parameters.ini if you're using Symfony2 with the deployment recipe listed below).

Something went wrong???

$> cap deploy:rollback

Symfony2 Deployment

If you're deploying a Symfony2 application, then this section is probably for you. This section explains how to configure capifony to deploy an application that uses the bin/vendors file to manage vendor libraries and the app/config/parameters.ini file for server-specific configuration (like database connection information).

First, add the following to your app/config/deploy.rb file so that the parameters.ini file is shared between all deployments:

set :shared_files,      ["app/config/parameters.ini"]

Next, share the vendor directory between all deployments to make deploying faster:

set :shared_children,     [app_path + "/logs", web_path + "/uploads", "vendor"]

Finally, each time you deploy, capistrano must run ./bin/vendors so that all of the vendor libraries are updated. Add the following code to deploy.rb to make this happen:

set :update_vendors, true

Now, each time you deploy, the vendors will be fully updated. This functionality is new in capifony 2.0.8

The final step is to configure your app/config/parameters.ini file. The best way to do this is to create this file in shared folder on server manually:

$> ssh your_deploy_server
$> mkdir -p /var/www/my-app.com/shared/app/config
$> vim /var/www/my-app.com/shared/app/config/parameters.ini

Once your parameters.ini file is correctly configured, you should be able to test your deployed application. On every subsequent deploy, that same app/config/parameters.ini file will by symlinked into your application, meaning you only need to configure after the initial deploy.

Configuration Reference

Capifony is highly configurable, and any option that exists for capistrano also exists for capifony

By default, capifony will ssh with your current system user, but you can change this behavior with set :user parameter:

set :user, "deployer"

If you’re using your own private keys for git, you might want to tell Capistrano to use agent forwarding (which means that the production server uses your local keys to pull from git):

ssh_options[:forward_agent] = true

You can also tell cap the exact branch to pull from during deployment:

set :branch, "v0.2.0"

If you’re using git submodules, you must tell cap to fetch them:

set :git_enable_submodules, 1

If you connect to your production server using a non-traditional port, set the port manually:

ssh_options[:port] = "22123"

symfony configuration parameters

All symfony tasks (both symfony 1.4 and Symfony2) run using the default php binary on the production server. You can change this via:

set :php_bin, "/path/to/php"

All symfony tasks (both symfony 1.4 and Symfony2) also run inside the prod environment on production server. You can change this via:

set :symfony_env_prod, "staging"

By default, capifony will try to configure your config/databases.yml on every symfony 1.4 project deployment (if it's not present) on production. You can turn this behavior off with:

set :use_orm, false

If you want to use a shared symfony library instead of one bundled inside a symfony 1.4 project, define the path to it with:

set :symfony_lib, "/path/to/symfony"

If your app or web paths in Symfony2 differ from default the default paths, you can specify them with:

set :app_path, "my_app"
set :web_path, "my_web"

If you use AsseticBundle with Symfony2, then you probably want to dump assets on every deploy. Turn the next option off to *disable* the automatic dumping of assetic assets on every deploy:

set :dump_assetic_assets, true
knpLabs product