Skip to main content

Deploying WordPress with capistrano

So I decided to manage my wordpress site using version control (i.e. git) and deploy it with capistrano. I’ve been following the excellent tutorials by Konstantin Kovshenin at theme.fm. It comes in three parts and covers the configuration and setup of staging and production servers and how to setup the directories with automatic symlinking and other handy tasks like sql backups and such. Mark Jaquith also talks about deploying with capistrano and has created some nice starting points like WP_Stack and WordPress-Skeleton.

While I finally managed to get everything sorted out, I did end up hitting a couple of snags along the way that wasn’t mentioned in the articles. I want to write down how I fixed it both in case other people are faced with the same problems, and also for myself as a reference for the future.

I am jumping straight in here where I already managed to setup some things. I made a git repo ready on bitbucket where I can push and pull my code. And I installed Capistrano and the other gems on my local machine. The server was waiting, ready for deployment. Since I don’t have a staging server at the moment, it’s straight to production for me. Now I only needed to get everything to talk to each other.

Use ssh-agent forwarding #

My first bump was the case with ssh keys. This is a topic that can be quite confusing but when setup properly, using ssh keys will enable you to log in to your server without typing your password every time. In the tutorial, Konstantin suggests that you check that things are working by manually ssh’ing into your server and use git pull or clone to checkout your repository from there and see that everything is working. This was a no go for me.

While I have keys setup so I can connect from my local machine to both bitbucket and the deployment server, I could not connect directly from one remote server to another. Instead of generating a new key pair and storing a secret key on the server, turns out I can add this to the deploy.rb file:

set :ssh_options, {:forward_agent => true}

This will make Capistrano use your local keys for deployment. So while I still can’t pull from the remote server manually, the cap deploy runs fine.

500 server error – fix the file permissions #

So now cap deploy works, I can ssh into my production server and see the files but when I try to visit my site in the browser I get a 500 Internal Server error. Bummer. Time to hunt the server error logs. Turns out that capistrano will make all files group writable, and the security settings of my hosting provider simply refuses to execute a file with group write permissions on. Which probably is a good thing. So let’s make a task to set new permissions on the files

namespace :myproject do 
    desc "Fix file permissions" 
    task :fix_file_permissions, :roles => [ :app, :db, :web ] do 
        run "chmod -R g-w #{release_path}" 
    end 
end 
after "deploy:symlink", "myproject:fix_file_permissions"

Since I am running multisite, the uploads directory is called blogs.dir and also needs to be outside versioning. I just treated is the same as the uploads folder in the tutorials, adding it to the .gitignore file and then letting capistrano create a symlink to the shared directory.

The final thing is that I wanted to have separate htaccess files on my local machine and the live site, so I set that up with also having the htaccess in the shared directory and adding symlink to it on deployment. Basically, treat it the same as the blogs.dir. So the task looks like this:

namespace :myproject do 
    task :symlink, :roles => :app do 
        run "ln -nfs #{shared_path}/blogs.dir #{release_path}/application/wp-content/blogs.dir" 
        run "ln -nfs #{shared_path}/.htaccess #{release_path}/application/.htaccess" 
    end 
end 
after "deploy:symlink", "myproject:symlink"

That’s it! Now I can update my site with

$ git push origin master 
$ cap deploy

Goodbye ftp client. Hello version control. Me like.