Capistrano is a command line utility for deploying web applications to one or more servers. It was primarily developed for Ruby on Rails applications, but applicable to all sorts of web applications these days, including of course WordPress. Honestly, I discovered Capistrano a couple of weeks ago during Mark Jaquith’s talk at WordCamp San Francisco 2011 so I decided to give it a go.
I’m not a Capistrano expert (yet) and in this post I’ll try to give you an overview how to set it up and how to deploy WordPress applications (websites) in seconds. We’ll work with only one server today but the principles in deploying to two or more are pretty much the same. I’ll probably write a few follow up posts on this topic as I get better, so stay tuned ;)
First of all I’d like to thank Mark Jaquith for his wonderful presentation at WordCamp San Francisco 2011, for his follow-up interview and for doing a quick review of this post before it went public. Thanks Mark! And now back to Capistrano…
What is Capistrano?
As mentioned in the introduction of this post, Capistrano is a command line tool for deploying websites. A typical web application resides in a version control repository (Git, Mercurial or perhaps Subversion). It’s being worked on locally (on one or many computers) and when the time comes, you access your production server, typically via SSH, and then pull or checkout the new stuff from the repository — i.e. you deploy your application.
If you’re doing things this way, you’re on the right track, since you can always checkout to a previous tag or commit (rollback) if something goes wrong. If you’re not, then you should be.
Capistrano wraps the whole deployment process in a few commands which are easy to understand and memorize, so in a few minutes you won’t be SSH’ing and Git pull’ing anymore, you’ll simply do cap deploy and you’re ready to go, the rest is done for you. Capistrano makes rolling back as easy as deploying with cap deploy:rollback. With Capistrano you can also manage multiple servers and multiple stages and the most exciting part is that you can (and should) write your own deployment scripts!
That should give you a basic overview of what Capistrano is and how it works, so let’s move over to the next part.
Installing Capistrano
First things first, since Capistrano is written in Ruby you’ll have to get Ruby working in your local environment. Note that Capistrano sits and works from your local (or development) computer and not at the production web server, so most of the stuff you’ll do today is going to be local. You should get a little familiar with Ruby at some point, but copy pasting your way through will work.
Ruby is pre-installed on some linux distributions, on others you can get it from the software manager. For Windows and Mac OS X I’ll recommend the following:
- RubyInstaller for Windows
- Ruby One-Click Installer for OS X (works in Lion)
Ruby comes bundled with a package manager called gem so to install Capistrano, type the following gem commands in your terminal:
sudo gem install capistrano
sudo gem install railsless-deploy
sudo gem install capistrano-ext
The first package is Capistrano itself, the second package allows deploying non-rails applications with Capistrano and the third package bundles some great Capistrano extensions, like staging, etc. You won’t really need the extensions for this tutorial but you’ll probably need them later on.
Getting Ready to Capify WordPress
I’ll make a few assumptions before we go ahead. We talked about version control earlier, so I’ll make the assumption that you’re using Git. We talked about SSH access and although Capistrano can ask your for your SSH username and password, you’ll be better off with public and private SSH keys.
I’ll also assume that you’re using RSA keys to access your Git repository, so at no point you should be asked to enter a password. Last assumption that I’m going to make is that your whole WordPress directory is in your Git repository, not only your theme or plugin files or directories. This includes your WordPress configuration which we’ll talk about later, but doesn’t include your wp-content/uploads directory since that would be a little crazy. To wrap up on the assumptions:
- You’re using Git and have access to a remote Git repository
- You have SSH access to your production server via RSA keypair
- You have RSA keypair access to your Git repository
- Your whole WordPress directory is under version control
The RSA keys part is perhaps the most difficult here, so here are some links to tutorials about that:
- Setting up SSH keys for Github
- Howto: SSH & Public Keys on Ubuntuforums
- SSH keys on Windows on Github
Also note that for your Git repository, both your local and production environment have to have public key access, meaning that you should be able to carry out a git pull on your production server without being asked for a password.
WordPress Configuration
Your WordPress configuration should be under source control as well and this doesn’t mean that your database credentials should be identical on your local computer and on your production server, in fact that would be quite insecure. So how do you have one wp-config.php file for both? Well Mark Jaquith suggested to structure your configuration file like this:
if ( file_exists( dirname( __FILE__ ) . '/local-config.php' ) ) {
include( dirname( __FILE__ ) . '/local-config.php' );
} else {
define( 'DB_NAME', 'production_db' );
define( 'DB_USER', 'production_user' );
define( 'DB_PASSWORD', 'production_password' );
define( 'DB_HOST', 'production_db_host' );
}
This means that whenever there is a file called local-config.php sitting next to wp-config.php it’ll include that file which will provide the database settings for your local environment and if there isn’t one, define the values for production. You then ignore the local-config.php file from your Git repo using .gitignore to make sure it doesn’t end up on your production server.
While this approach works, I like to take a different one which might be a little bit more complicated but allows staging, like this:
if ( file_exists( dirname( __FILE__ ) . '/../env_local' ) ) {
// Local Environment
define('WP_ENV', 'local');
define('WP_DEBUG', true);
define('DB_NAME', 'local_db_name');
define('DB_USER', 'local_db_user');
define('DB_PASSWORD', 'local_db_password');
define('DB_HOST', 'local_db_host');
} elseif ( file_exists( dirname( __FILE__ ) . '/../env_playground' ) ) {
// Playground Environment
define('WP_ENV', 'playground');
define('WP_DEBUG', true);
// ... playground db constants
} else {
// Production Environment
define('WP_ENV', 'production');
define('WP_DEBUG', false);
// ... production db constants
}
Now this may seem a little crazy at first (I also stripped a bunch of defines for brevity) but it really is simple. Note that my whole website installation is in a directory called application so the config file resides in application/wp-config.php.
So I first look for a file called env_local in a directory one level up from wp-config.php (which is application) and if it’s there, define the database settings for the local environment. If it doesn’t exist I look for one called env_playground (this is how I called the testing/staging server) and define the database settings for my testing server. If none of the two exist I assume that it’s the production server, so I define the production database parameters.
Hope this isn’t too weird ;) Anyhow, you should put env_local, env_playground and env_production into .gitignore and make sure none of them get inside your repository. You’ll create one locally to work and we’ll get Capistrano to create the production file when deploying. Staging might be a follow-up tutorial ;)
You’re almost done, final step is to check how things work by manually doing a git clone, checkout or pull on your production environment and make sure the configuration file is okay and that everything works as expected. Ready for action? Capify!
Capify WordPress
Let’s revisit our repository and website structure, assuming your website is called project:
projectis under source controlproject/applicationis where WordPress livesproject/application/wp-config.phpis your WordPress configuration fileproject/env_localexists only in your local environmentproject/application/wp-content/uploadsis not under source control
Great! Now fire up your command line or terminal, create a new directory somewhere in your local environment, not necessarily your project directory, in fact your Capistrano files shouldn’t be in your project’s source at all, otherwise it can create a chicken-egg situation, so my suggestion is to keep all Capistrano files in a totally different directory tree and you can put them under source control as a different project, perhaps /home/user/deployments/project_name/. And now, type this:
capify .
That’s capify followed by a space and a dot. Congratulations, you have capified WordPress! But don’t rush to deploy yet, we’ve still got some Capistrano configuration to do. If you browse the directory you just capified (let’s call it your deployments directory) you’ll now see a file called Capfile and a directory called config. Since Capistrano was built for Ruby on Rails, we’re going to do some (almost) heavy modifications to fit our needs.
Open the Capfile first and remove all it’s contents. Yes, remove everything there’s written and pump in the following:
require 'railsless-deploy'
load 'config/deploy'
The first line loads the railsless-deploy module that will be used when not dealing with rails applications and the second line will load the deploy.rb file inside our config directory, so let’s take a look at that right now. You’ll see some pre-written template, which again is for rails applications, so remove everything and type in the following:
set :application, "your-application-name"
set :repository, "git@github.com:you/your-project.git"
set :scm, :git
set :deploy_to, "/home/path/to/project/"
set :deploy_via, :remote_cache
set :copy_exclude, [".git", ".DS_Store", ".gitignore", ".gitmodules"]
server "example.org", :app
It’s quite easy to follow along, even if you don’t know Ruby/DSL. First few lines set some variables required by Capistrano, deploy_to sets the directory where your application will be deployed. We let Capistrano know about our application and repository. The :deploy_via option is set to :remote_cache which means that a remote git checkout will be cached on each server for faster deploys. The :copy_exclude makes sure you don’t deploy your git and annoying OS X files.
The last line sets the host for your server for the :app role. You don’t have to worry about roles yet, just keep in mind that this line represents the host to which Capistrano will connect via SSH to deploy your application.
Don’t rush to set your deploy_to path to a real target, but rather create a directory which doesn’t necessarily has to be live, you’ll just see what’s going on inside it via SSH. You’ll be able to change these configs any time, so make sure you’re comfortable with them before going live. So here’s where we’re at:
projectis under source controlproject/applicationthis is WordPressdeployments/my_project/Capfilethis is the Capistrano capfiledeployments/my_project/config/deploy.rbthis is the deployment script
And now you’re ready to carry out your first deployment task.
Your First Capistrano Deployment
Capistrano tasks all start with cap and you have to be somewhere in your deployments directory tree since Capistrano will need to find your Capfile to carry out your tasks. So in theory, with the structure and the configuration that you have created, issuing a cap deploy command would result in a deployment task on your production server, inside the deploy_to path that you have set.
This means that Capistrano will log on to your example.org server, browse to the /home/path/to/project/ directory and clone the HEAD commit from your Git repository.
So, let’s see if this works, from the command line type:
cap deploy
You should see a lot of verbose things from Capistrano, it’s basically telling you what it’s doing at each and every stage. If at the end of it all you see a transaction: commit message, this means that your deployment has been successful. If not, something has gone wrong…
Let’s now connect to our server via SSH and see what the deploy has really done. Inspect the /home/path/to/project/ directory and you’ll see two things — a releases directory and a current symlink. This is the nature of Capistrano so you should get familiar with it (although the names can be changed if needed). Every release is deployed inside the releases directory under a unique name and if the transaction was successful, the current symlink will point to that release.
By now you should have figured out that you need to point your web server (Apache or nginx) to the /home/path/to/project/current/application directory to reach WordPress. Right? Try and make some changes, commit and push them to your repository and deploy again, you’ll see that the current symlink now points to a different release — your newest one.
Rolling Back & Cleaning Up
So what if things have gone wrong? Try it out:
cap deploy:rollback
This is a very fast task which will simply make your current symlink point to the previous release. Then cap deploy to move forward again. Pretty simple, eh? Right, Capistrano will store every deployment in it’s own folder under releases and it might get huge if you forget to:
cap deploy:cleanup
That will leave the latest 5 releases (or whatever the default setting is) for you to roll back to and get rid of the older ones. If for some reason the clean up didn’t work and you’ve seen a sudo-related message, this means that Capistrano has tried to use the sudo command to get rid of the old releases. You can either set up password-less sudo, which is not very secure, or just add the following to your deploy configuration file.
set :use_sudo, false
There are many more cap commands (or tasks) that you can try out and you can even write your own, but this is out of scope of this tutorial. To get a list of all available tasks you can use the following command:
cap -T
Capistrano & Shared Files
Now that Capistrano is set up to deploy and rollback your application you’ll need to somehow manage shared files across releases. I’m talking about the wp-content/uploads directory primarily. The uploads directory is ignored in your Git repository (which is correct) so Capistrano won’t deploy it. Let’s create a shared directory on your production environment and an uploads directory inside it. Here’s what you should have on your production server:
/home/path/to/project/releases/is where your releases are/home/path/to/project/current/is a symlink to your current release/home/path/to/project/current/application/is your directory root (that is set up on Apache or nginx)/home/path/to/project/shared/is the shared data across all the releases/home/path/to/project/shared/uploads/is your new uploads folder
For Apache or nginx to access your uploads, you’ll need a symlink in current/application/wp-content/uploads that will point to shared/uploads and the uploads directory in shared should be writable by the Apache/nginx user (typically www-data) so that new files can be written inside.
You can easily do this while you’re in SSH with the ln command in the current/application/wp-content directory, but beware that your next cap deploy will erase all your changes and you’ll be left without your uploads again, so this has to be done with Capistrano and it’s quite easy to do so.
Assuming that you have created the shared/uploads directory, go back to your local environment and edit the deployment configuration file and right after the server command add the following snippet:
namespace :myproject do
task :symlink, :roles => :app do
run "ln -nfs #{shared_path}/uploads #{release_path}/application/wp-content/uploads"
end
end
after "deploy:symlink", "myproject:symlink"
Save and close, and then run cap deploy again. If everything goes well you can peek inside the current/application/wp-content directory and see that there’s now a symlink pointing to the shared uploads folder that you have created, great!
The above snippet shows how you can easily create your very own tasks and execute them during certain events (after deploy:symlink in our case). The task itself simply runs an ln command to create the symlink and once you understand how that works, it’s really easy to do other stuff, like create that env_production file I talked about earlier, you can do it in the same task for brevity, right after the first run:
run "touch #{release_path}/env_production"
And voila. An empty env_production file will be created when deploying to your production server, so your configuration file should now work as expected, hopefully it does. It’s now time to point your Apache or nginx configuration to your new directory — the current/application folder. And that brings us to an end for this tutorial.
Conclusion
Today you (should) have learned about Capistrano, installing and configuring it for production. Of course Capistrano itself is much more powerful than simple single-server deploys. You can get it to deploy to multiple servers, you can get it to stage your deploys and you can even get it to migrate your databases. The most difficult is the first step though, so hopefully this tutorial has shown you how easy it to deploy WordPress like a pro.
I’ll maybe write a series of follow-up tutorials on working with WordPress and Capistrano, but it really depends on your feedback. Do let us know if this was clear enough, whether there are some things I should clarify and were you at all able to follow along. Tell us how you feel now that you’re deploying with Capistrano.
Use the comments section below to leave your thoughts and don’t forget to follow our RSS feed! Thank you for reading!
Wait, there’s more! Please proceed to the next part of this tutorial: Deploying WordPress with Capistrano Part 2: Staging Servers, Tagging & Database Security.



A series would be great! I’d really like to learn more about deploying to multiple servers and migrating databases.
Cool, thanks for your feedback Dave!
Good tutorial. One modification I’d suggest: its generally a good practice not to store DB (or any) credentials in your source control. If you take your idea, and Mark’s, and leverage Capistrano’s shared folder, you can create a pretty good work around. Create a file in in the shared folder with your DB settings in it, then setup Capistrano to copy it into the project on deploy. Using Mark’s method, you can simply include the file in your config and you’re off and running with no DB credentials in source control.
Hey Adam, that’s a very good point indeed, especially if more than one person has access to the source code. Thanks!
I watched Mark’s SF WordCamp 2011 video today, so this is EXACTLY what I needed. I’m having some issues still, but hopefully with this article everything will be worked out.
Paul
Hey Paul, thanks for your comment. Yeah this should get you kick-started and watch out for other follow-up posts on Capistrano around here, we’re still exploring that area too :)
So I can get the deploy to occur: releases folder on server contains releases, each of which contain WP files/folders and the current symlink. But when I navigate to my URL, I get a forbidden, and when I navigate to url.com/wp-admin I get a not found.
I didn’t setup my SSH keys since I had to enter a password upon deploy, but that shouldn’t make a difference, should it?
I should mention that I used pieces of this tut http://ryanflorence.com/deploying-with-capistrano-without-rails/ for setting up the deploy.rb file
Have you pointed your web server’s document root to the current symlink? Use a pastebin to show me your server configuration file and tell us the directory structure as well, where the current symlink is, where the releases are, and where the WordPress index.php file is located, I’ll try to help you out :)
SSH keys vs password shouldn’t make any difference in your case, as long as the deploys were successful.
I didn’t realize that you had to point to current, I thought the server saw the symlink and took over from there.
Here’s where I have releases/current /var/www/vhosts/example.com/domain/
I’m not overly familiar with server setups so I’m trying to find the proper httpd.conf (which I’m assuming is the server configuration file) to point to current. I’m on a DV with MediaTemple, so I’m kinda guessing there’s a config file within each virtual host. I’m going to figure this out first and see if that doesn’t solve my problem.
You mention location of a WordPress index.php. The only location that I have index.php is within each release. Do I need an index.php file within domain/?
Thanks for the help, especially with so many different variables going on.
Hey no problem. If you’re using Apache your vhost configuration is probably somewhere in
/etc/apache2/sites-available/and you have to restart/reload Apache for your changes to apply. Let me try and explain this one more time. Suppose your structure is like this:/home/paul/mysite.org/— your working directory/home/paul/mysite.org/releases/— the releases directory/home/paul/mysite.org/current/— the symlink to one of the releases/home/paul/mysite.org/current/wp-config.php— your configuration file/home/paul/mysite.org/current/index.php— your WordPress index fileThen you should point your document root to:
That’s the
DocumentRootdirective in Apache and therootdirectory if you’re using nginx.Hope this helps. Cheers!
Steps I just took to no avail
- Created vhost.conf in /var/www/vhosts/paul.com/conf/
- Within vhost.conf added the line “DocumentRoot /var/www/vhosts/paul.com/httpdocs/current/”
- Restarted Apache
Still nada. As I mentioned, I’m not genius when it comes to server setups, but this seems right to me…
Either way, I hope this is of use to someone down the road. I’m going to keep at it and see if I can’t fix it :)
Paul, this definitely is an apache configuration problem, I doubt that it’s caused by Capistrano. Shoot me a message on Skype I’ll be glad to help you figure it out, especially since you run Media Temple, although I would suggest you try their (ve) service next time, not (dv). My Skype name is kovshenin feel free to poke me whenever you see me online.
Cheers!
thanks for the tutorial!
also, just learned about this plugin:http://markmaunder.com/2011/08/19/deploymint-a-staging-and-deployment-system-for-wordpress/
Wow, sweet Paul, thanks for the heads up! Will definitely give it a spin :)
excellent tutorial Konstantin! Quick question – does Capistrano allow you to set file permissions? I normally setup separate home accounts for each site I deploy and set file ownership to specific accounts. It simplifies file upload permissions and improves overall security. Curious as to whether you had any issues with this?
Ed
Hi Ed, thanks for your comment! Capistrano allows you to do anything you could normally do with SSH so I don’t think there will be any problems setting file permissions. You could though face one when trying to do stuff you’re not allowed to in SSH that would usually require
sudo. Although you can set up password-lesssudoon your server, I highly don’t recommend that.What I would do instead is deploy using the correct account from the very beginning, i.e. if you’re deploying to
/home/example/www/use theexampleusername with Capistrano. Hope this makes sense. It might also be tricky configuring multiple RSA keys for password-less SSH access to different accounts but I can’t tell for sure since I have never tried it myself.Thanks again for your comment and have a good day!
Nice write up Konstantin. By the way, have you ever tried wp-cap?
Hi William, not really but I definitely will, thanks for the heads up!
so if I’m developing themes and plugins, wouldn’t it be better to source control them separately instead of having one repository for the whole WP install?
They should be in a separate repository yes, one made especially for that particular plugin, or you can use WordPress plugin hosting which provides you with a Subversion repo. Unless of course your plugin is exclusive to your project, in that case you can manage it’s development inside the main project repository like it’s simply part of it (like functions.php), but keep in mind that at some point you might decide to release the plugin to the public and that’s when you’ll have to move out :)
Actually it’s up to you on how comfortable you are and what sort of “rollbacks” you might be expecting. Like having on-going development on 5 different plugins in one repo is not comfortable since you might need to roll back only one of them which will be tricky.
A different approach:
Zane, I do, but the request address is not always localhost since developers tend to set up virtual domains, like example.lo (lo for local) and there’s no way to guess what everybody will use unless the whole team agrees upon one :) Thanks for your comment!
I’m so close to getting this to work, but unfortunately the first commit I did, I forgot to ignore the uploads folder. I later added it to gitignore and did a rm -r on it so that it’s empty and it is not in my remote repository. However, I still get a real uploads folder in wp-content and the uploads symlink under that, so I’ve got wp-content/uploads/uploads (symlink)
any ideas how I can fix this?
Paul, removing the uploads folder from your local computer is one thing but if it still exists in the git repository it’s there. Try and clone the git repo somewhere locally and look at what it creates, my guess is that it creates that upload folder but you can’t manage it through git because it’s ignored. I think that what you should have done is
git rminstead ofrm -rand then commit changes.Show me a gist of your Capistrano config file and I’ll try to give you more details :) Cheers and good luck!
The git ignore file is not retro active.
You’ll have to do the following:
1. copy the folder
2. delete the original
3. commit the deletion of the original
4. rename the backup to the original name
thanks for all your suggestions, actually it looks ok now. I removed the folder from versioning with git rm
the problem is I’m on shared hosting and I can’t do a cap deploy:cleanup because it tries to do a sudo command and I can’t issue sudo commands as I don’t have root access, so I have a bunch of release versions now.
I’m thinking of trying out Rackspace
Paul, have you tried setting use_sudo to false in your Capistrano config?
cool! thanks Konstantin that worked.
ok, so now to get the actual site to work, do I set the domain (subdomain) to point to the current symlink?
any idea on how to do that?
Paul, cool. If the symlink is being created then you should try walk around the control panel your hosting account provides you with, you should be able to set the document root for your domain somewhere. Give it a go with subdomains to test things out before breaking your production site :)
Oh and even if everything works well, you should still get a VPS. I can recommend MediaTemple’s (ve) hosting, starts at $30/mo.
I use the (ve) account on (mt) and love it! BUT I wouldn’t recommend it unless your are a expert/advanced unix user, since you’ll have to build the server from the command line.
The (dv) account is $50 and has CP.
If you can handle, it thought, I’d say (ve)…you’ll learn alot
Zane,
I agree that (ve) can be complicated, but not that you need to be a linux pro to use it. There are a bunch of tutorials out there to help you get started with Apache/nginx, php and MySQL and yes, the (ve) servers are a great opportunity to learn. Sooner or later we will all have to, won’t we? :) Thanks for your comment!
so how can I tell capistrano to set all folder permissions to 755 and files to 644?
would something like this work:
Not sure why you’re setting permissions like that, besides, 777 is dangerous for your public folder and suitable for your uploads folder only (in most cases). My guess is that a chown to www-data/www-data or whoever is running Apache, should solve all the permissions trouble :)
ok, finally got it to work!
one thing: I get a message that this syntax is deprecated
and do you know a way to keep the databases synced?
Not sure which part you’re referring to, maybe the find part. You can also try something like this:
Anyhow, I think it’s easy enough to sync databases too but haven’t yet tried it out myself. I surely will and I’ll write about it in part 3 :)
the cap deploy:cleanup tasks outputs this message:
F:\deployments\wptemplate>cap deploy:cleanup
[Deprecation Warning] Naming tasks with before_ and after_ is deprecated, please
see the new before() and after() methods. (Offending task name was after_update
_code)
Does the “after_” make it run after “cleanup:update_code”? If so I think you can do something like the following (not tested):
Not sure I got the naming right though.
If your talking about a Stage DB vs. Production DB why would you do that?
If need be, maybe rsync, with a mysqldump.
well if I want to keep content, menus and widgets synchronized.
Paul, I’m not sure about widgets and other data that is serialized (which perhaps will be partially fixed by 3.3) but perhaps you could write a Capistrano task of it’s own that would mysqldump some of the local tables (like wp_posts), upload them to your server and run an import there after a search and replace with sed or something. Quite risky with wp_options, wp_users and wp_comments though.
have you tried RAMP? http://crowdfavorite.com/wordpress/ramp/
Paul, I agree with Konstantin on widgets being partially fixed by 3.3. and I think there’s still a bug for importing the same menu as it will duplicate your menus.
Here’s what I’d do:
1. Update your widget code to include an import/export option.
2. If you have in house developers have them do it
3. If your using 3rd party ones I’d request the author add that feature.
If your in option 3…then I’d revisit using capistrano or using your the widgets you use.
Here’s a long version:
Capistrano seems to be for medium sized sites and is a tool to easier deploy your code. Therefore if your using capistrano we can assume your running a medium sized site, like not a “hobby site” thats glued together with free plugins and themes and if your running a medium sized site then you shouldn’t be using 3rd party widgets and such as you dont have control over the code.
Point being that widget code should and must be paramount held to the highest coding standards. Either done by you (if your a developer) or by your in house developers. This way you can act with the agility of world class ballerina and the confidence of tiger wrangler. Fixing bugs and adding features as needed.
No I haven’t but it looks quite interesting, perhaps we should give it a spin. Anyhow, to work with real content we use a read-only slave database that’s replicated from the master. It’s read-only so our data is safe and always the latest.
When we need to experiment with something, like publish a new post or page we switch it to a “playground” one, do all the stuff there and if it’s something we’d need on production we simply copy the SQL queries and then run them on our production database right after deploying. Kinda slow but secure…
Zane,
this is not directed personally :)
in theory I disagree with you. If everyone was coding their own private WordPress functionality privately, because the plugins on the repository are not secure and of bad quality, that wouldn’t be good for our community.
Why not make a free plugin better, more secure to use on your professional site, then give it back to the community.
In practice, you probably have other constraints I don’t know about.
I hear this a lot from experienced developers, and I wonder why they don’t contribute more instead of complaining about poor plugin quality.
No prob, I dont take it personally.
I do help out with the community locally I’ve got 2 plugins in the repo as well, I’m constantly preaching about code ethics and standards. Dont get me wrong the majority of the plugins in the repo are of excellent quality I was trying to emphasis the use of a large (like 20-40) number of plugins/widgets to control your site and sorry for putting you in that category.
But yea, sorry that is the developer dictatorship of side me coming out :D
Hi, great article!
I’m using Mercurial on bitbucket.org for source control. I’ve followed the steps in your tutorial and have got most of the way, but am having trouble on cap deploy. I’m getting this error:
servers: ["91.208.99.6"]
[91.208.99.6] executing command
** [91.208.99.6 :: err] abort: couldn’t find mercurial libraries in [/usr/local/bin /usr/lib/python24.zip /usr/lib/python2.4 /usr/lib/python2.4/plat-linux2 /usr/lib/python2.4/lib-tk /usr/lib/python2.4/lib-dynload /usr/lib/python2.4/site-packages /usr/lib/python2.4/site-packages/gtk-2.0]
** (check your install and PYTHONPATH)
command finished in 255ms
*** [deploy:update_code] rolling back
Would I need to install mercurial on my production server, or is this just a path problem on my local machine? I’m running a WAMP setup locally.
Any help would be greatly appreciated!
Andy, Capistrano runs the version control commands on your server so yes, you should have Mercurial installed there, but having it on both is even better, just in case ;)
Great, thanks Konstantin! I’ll give that a try.
Hey if im using SVN for this instead of git do I just need to change this area here to say svn?:
Paul, yes, you’ll have to make sure your
:repositoryis then set to an existing Subversion repository and put.svnin:copy_exclude. I think that:remote_cachewill work fine with Subversion too. Let me know how it turns out!Pingback: WPNYC Presentation Notes
just deployed with your tips to my sharedhosting, it worked after some tweaks.
To automate further check this guy tips too https://github.com/jestro/wordpress-capistrano
they complement, sometimes i just need simplicity, thanks.
This post is truly a a gem (no pun intended :). One thing I noticed different in your tutorial compared to all the others is that you advocate doing the cap in a separate folder such as users/chris/deployments rather than in /myproject/ when application is located in myproject/application. You mentioned having it in the folder could cause problems but was wondering why that has not been mentioned in other tutorials I’ve read? However with your tutorial it sounds like you recommend to version control myproject/ folder rather than just myproject/application/ which maybe is why the problem doesn’t exist for other tutorials that only git the application folder and cap is in myproject/config. Just looking for best practices and a cap newbie so would love to hear your thoughts and get this setup right from the start. Thanks!
Thanks for this excellent post. I got it up and running in no time. I have a quick question.
What is the rationale for restructuring the wordpress app into:
/project/application
/project/env_local
/project/.git
/project/.gitignore
Wouldnt it be possible to just add a folder env_local into the application folder that would be added to the .gitignore file in the application folder and modify your wp-config.php file to check
if ( file_exists( dirname( __FILE__ ) . ‘/env_local’ ) ) {
I am asking that because if you have a collection of wordpress apps already versioned, you would need to restructure them, recreate the –bare repo on your remote origin, etc…
Thanks!
I have a WordPress install which is under Git version control and deployed with Capistrano very similar to your setup. I like having the entire WordPress directory under version control, core, wp-content and all.
What I would like to know is if there are any know issues having plugins updated locally, committed to the local Git repository, pushed and then deployed to remote staging/production servers? When you do an automatic update, the plugin is disabled, plugin code updated/replaced and then reactivated. Some plugins run updates to database tables, etc upon activation, right? So this works fine locally but what about on staging and production servers? They are getting the updated plugin code from the repository but there is no deactivation/activation of these plugins during capistrano deployment. Couldn’t this cause plugins requiring updates during activation?
I just tried using Capistrano but I got stuck at the deployment stage. I get the following errors,
* executing “rsync -lrpt –exclude=\”.git\” –exclude=\”.DS_Store\” –exclude=\”.gitignore\” –exclude=\”.gitmodules\” /var/www/vhosts/phpcentric.com/shared/cached-copy/ /var/www/vhosts/phpcentric.com/releases/20120111010330 && (echo 23c58c07b23dc96f42d4c4d8328a0ae7310ea18e > /var/www/vhosts/phpcentric.com/releases/20120111010330/REVISION)”
servers: ["phpcentric.com"]
[phpcentric.com] executing command
** [out :: phpcentric.com] rsync: mkdir “/var/www/vhosts/phpcentric.com/releases/20120111010330″ failed: No such file or directory (2)
** [out :: phpcentric.com] rsync error: error in file IO (code 11) at main.c(595) [Receiver=3.0.7]
** [out :: phpcentric.com] rsync: connection unexpectedly closed (9 bytes received so far) [sender]
** [out :: phpcentric.com] rsync error: error in rsync protocol data stream (code 12) at io.c(601) [sender=3.0.7]
command finished in 549ms
*** [deploy:update_code] rolling back
* executing “rm -rf /var/www/vhosts/phpcentric.com/releases/20120111010330; true”
servers: ["phpcentric.com"]
[phpcentric.com] executing command
command finished in 408ms
failed: “sh -c ‘rsync -lrpt –exclude=\”.git\” –exclude=\”.DS_Store\” –exclude=\”.gitignore\” –exclude=\”.gitmodules\” /var/www/vhosts/phpcentric.com/shared/cached-copy/ /var/www/vhosts/phpcentric.com/releases/20120111010330 && (echo 23c58c07b23dc96f42d4c4d8328a0ae7310ea18e > /var/www/vhosts/phpcentric.com/releases/20120111010330/REVISION)’” on phpcentric.com
I have been trying to get to the root of the root of the problem for hours but have not been able to get past it.
I will appreciate some help here.
Dev server Mac OS
Production Ubuntu 10.04
Pingback: Capistrano: Delete Cached Copy - Konstantin Kovshenin
a couple of commands I found useful to ‘debug’ the capistrano deploy script:
cap deploy:check ( this will verify that permission are correct and required folders exist and are accessible)
cap deploy:setup : will create necessary folders (releases / shared)
It’s hard to come by well-informed people on this topic, but you sound like you know what you’re talking about! Thanks
Pingback: Cross-server deployment with servermattic