Deploying a Laravel Application Using Capistrano


So you've just built a fancy web application and you're planning to put it online. This can be done in many ways. In this article I'd like to cover one approach to deploy your backend system to your production server. We'll go through the following steps by example of a Laravel application but this can be applied to any other language or technology.


This article was updated to Capistrano 3. More about the new version can be found on capistrano's website.

The Past

Perhaps you have already put some websites online in the past. Probably you've used a FTP client and uploaded the bits and bytes by hand. Or perhaps you always logged into your server via ssh and pulled the changes manually.

The Idea

Our goal is to simplify this process as much as possible. The idea is to use your code repository as a source for every deploy. The deployment tool, in our case capistrano, will automatically log into your server and build your system right out of your repository.

Software deployment is all of the activities that make a software system available for use. - Wikipedia

What You'll Need...

...on Your Remote Server

Your remote server needs to provide ssh access. It also should have installed all necessary dependencies for your project such as GIT, PHP, MySQL, Composer, ... Besides that, you don't need any extra software on your production server.

...on Your Local Machine

In order to install and use capistrano, you need at least Ruby 1.9 (if you don't have Ruby installed, I recommend installing it using rbenv). To install capistrano, you simply have to run:

$ gem install capistrano

So why capistrano, you may ask. As always, there are many ways to accomplish a task but in my case, capistrano always seemed to be the easiest and most flexible approach. You can configure it to all your needs and there are a lot of plugins out there which simplify your work again.

Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH. It uses a simple DSL (borrowed in part from Rake) that allows you to define tasks, which may be applied to machines in certain roles. It also supports tunneling connections via some gateway machine to allow operations to be performed behind VPN's and firewalls.


Now we have everything we need, so let's setup our deployment settings. But first we have to create a folder on the remote server where all the files should be deployed to. Log into your server with SSH and create a folder. A common place is /var/www/. So let's do this:

$ sudo mkdir /var/www/my-app
$ sudo chown -R username:group /var/www/my-app

That's it. There is nothing more to do on the remote server, so you can close the ssh connection and move on. Go into your project (or any other folder, that doesn't matter right now) and run:

$ cd my-project
$ cap install

This command will create the basic files we need. After that your folder should look like this.

├── Capfile
├── config
│   ├── deploy
│   │   ├── production.rb
│   │   └── staging.rb
│   └── deploy.rb
└── lib
    └── capistrano
        └── tasks

The Capfile is like the mount point for capistrano but for now we'll just need to edit config/deploy.rb and config/deploy/production.rb. The first file is responsible for all the building steps, the second file represents a "stage". You can have several stages like production, staging, testing... In each stage-configuration file you can specify your server(s). Let's open those two files in your favourite text editor and replace the content with the following snippets. We'll go through the code afterwards.

We'll start with config/deploy/production.rb:

role :app, %w{username@123.456.789.123} # EDIT your ssh username and server ip address 

set :ssh_options, {
    auth_methods: %w(password),
    password: "" # EDIT your ssh password

Next we'll modify config/deploy.rb:

set :application, "Your app name"  # EDIT your app name
set :repo_url,  "" # EDIT your git repository
set :deploy_to, "/var/www/my-app" # EDIT folder where files should be deployed to

namespace :deploy do
    desc "Build"
    after :updated, :build do
        on roles(:app) do
            within release_path  do
                execute :composer, "install --no-dev --quiet" # install dependencies
                execute :chmod, "u+x artisan" # make artisan executable

    desc "Restart"
    task :restart do
        on roles(:app) do
            within release_path  do
                execute :chmod, "-R 777 app/storage/cache"
                execute :chmod, "-R 777 app/storage/logs"
                execute :chmod, "-R 777 app/storage/meta"
                execute :chmod, "-R 777 app/storage/sessions"
                execute :chmod, "-R 777 app/storage/views"


You now have to put your data in every line with an #EDIT comment (ip address, git repo, ssh user, password, etc). The :deploy_to variable should be the folder we just created. Your webserver (Apache, Nginx, ...) should point to /var/www/my-app/current/public.

In the namespace :deploy block of the deploy.rb file you specify what actually should happen for each deploy. So there are two tasks. In the build task we install all your PHP dependencies, just like you're used to it during development. After that we make the artisan file executable in order to use it for migrations. In the restart task we fix the permissions for the storage folders.

All those tasks are invoked in the following order. You can hook into each task if you need to but for now we stick with our simple configuration.

deploy:starting    - start a deployment, make sure everything is ready
deploy:started     - started hook (for custom tasks)
deploy:updating    - update server(s) with a new release
deploy:updated     - updated hook
deploy:publishing  - publish the new release
deploy:published   - published hook
deploy:finishing   - finish the deployment, clean up everything
deploy:finished    - finished hook

Every deploy is stored in /var/www/my-app/releases/. The built-in task deploy:publishing creates a symbolic link of the recent deploy to the current folder. This way you can keep older releases and switch versions without going offline for a second. When this task ran, your newest version is online.

You can easily add your own tasks if your build process requires some extra steps. For more detailed information, I recommend you reading the official documentation.

After these basic configurations steps we are prepared for our first deploy.


So that's the moment you were waiting for. The hardest part is done. For now on every time you want to deliver your application updates, you just have to run the following magical command. Capistrano will read your config/deploy.rb config/deploy/production.rb files and run each task. If a task fails, the deploy will stop and the old version is still online.

$ cap production deploy

You will see a bunch of text output and after little time (depending on your server) everything should be complete. That was easy, wasn't it?

Note: For now we just setup our production stage, but you could replace production with another stage, for example your testing server and run $ cap staging deploy.

Further Thoughts


Perhaps you might be a little worried if you have to put your plaintext password in the configuration file. I just choosed that way to make the demonstration as straight forward as possible, but in the real world you might want to use a SSH key. You can import one like this:

set :ssh_options, {
    keys: %w("/path/to/your/key.pem"), # EDIT your ssh key
    auth_methods: %w(publickey)


For now we have just focused on deploying the actual files to their new home but in many scenarios you might also do something with your database. Laravel has a perfect tool for that: migrations. You could just add a new step where you run these migrations. After that our build task might look like this:

desc "Build"
after :updated, :build do
    on roles(:app) do
        within release_path  do
            execute :composer, "install --no-dev --quiet" # install dependencies
            execute :chmod, "u+x artisan" # make artisan executable
            execute :php, "artisan migrate" # run migrations

You also have to add this task in the transaction block of the update task. Now everytime you deploy, the database will be updated to your latest migrations.


Sometimes you deploy a non-working version of your application and you need to undo these changes. Capistrano has a built-in feature for that called "rollback". Just run:

$ cap production deploy:rollback


You've just learned a very simple way of deploying your application to your production server(s) with Capistrano. Once the configuration work is done, it just takes one command to deploy your latest version in seconds. But as mentioned earlier, this is not the only way to do this.

You should also check out the task runner grunt which suits perfectly for building and deploying JavaScript applications. A complete different approach takes docker which acts like a lightweight VM. The idea here is to deploy your whole environment as a virtual machine. Check them out!

Related Posts
  • Code
    Web Development
    Easily Deploy Redis Backed Web Apps With DockerDocker wide retina preview
    Learn how to setup and deploy a Redis powered Python web app using Docker.Read More…
  • Code
    An Introduction To Deploying WordPress with MinaImage400
    As a PHP application, WordPress is usually deployed by a very old method: uploading files via FTP. We have some deployment tools, but they often requires some type of Ruby skill. For example, one popular, powerful tool is Capistrano, but it's also very heavy with many Ruby/Rails related features. I also think that it's little bit tricky to install Capistrano for a PHP developer without any Ruby knowledge. So what options do we have as WordPress developers? In this tutorial, I will introduce you Mina: A small, light tool aims to fast deployment and server automation.Read More…
  • Computer Skills
    How to Use a Raspberry Pi as a Local Web ServerThumb
    In this tutorial I will show you how to set up a Raspberry Pi to be used as a Local Web Server with SSH and FTP functionality.Read More…
  • Code
    Coding With KodingCoding with koding retina preview
    Cloud IDEs have been around for a little while now, and they have been pretty good for things like pair programming, or cases where you want to code consistently no matter where you are. Koding just came out of private beta, and they would like to take this notion a couple steps further, with their "cloud ecosystem". In this article we will take a look at what Koding is, as-well as some of the benefits you can get from using it.Read More…
  • Code
    Authentication With Laravel 4Laravel 4 auth retina preview
    Authentication is required for virtually any type of web application. In this tutorial, I'd like to show you how you can go about creating a small authentication application using Laravel 4. We'll start from the very beginning by creating our Laravel app using composer, creating the database, loading in the Twitter Bootstrap, creating a main layout, registering users, logging in and out, and protecting routes using filters. We've got a lot of code to cover, so let's get started!Read More…
  • Code
    25 Laravel Tips and TricksCode
    There was a period of time, not too long ago, when PHP and its community were, for lack of better words, hated. Seemingly, the headline joke of every day was one that related to how terrible PHP was. Let's see, what new PHP-slamming blog article will be posted today?Read More…