Deploying Php Web Apps With Capistrano
I only recently completed building a project i was extremely keen on - Schoollogue, a wordplay on “School Catalogue” - after which i deployed it (of course) but there was a but to it, it actually is my first stuff to go online - ok, i lied ; my portfolio site is -, but you get the gist right ?.
Which made me write this blog post for first-timers and obviously confused folks like i was.
With that said, moving the project online would be my first and i had to spend a lot of time on google, quora and stackoverflow - reading good old questions - looking for how to move this online. I already knew my best bet was an IAAS platform, since i have come to know and understand the perils of shared hosting since it just does not scale and isn’t not developer-friendly but there was something i didn’t just get.
Of course, i knew i could throw it (the files) at the server and “just let it flow” but it’s a project i do want to iterate on, add new features and remove obsolete or unneccessary features - some would call it a start-up .coughs - .
How do i add all this up without having to do a lot of manual work when there’s a v2 out ?
I have seen (read actually) deployment strategies involving FTP and others that are essentially time-stamped - or version stamped , then the
index.php file scans through available directories and redirects the user to the most recent directory ; Your users then get stucked with links like
http://sitename.com/v1232/login (assuming v1232 is the most recent directory) -. It works, definitely but i needed something much more modern, simple, predictable - and for a lazy guy like me, a one-liner.
Then i found capistrano, a ruby based deployment software. From the info i found online, it was initially built for Ruby on rails applications but can be streamlined (without pains) to be as useful with other languages - all it needs is SSH and a vcs repository.
- A server.
- Version Control System.
- On your development machine and remote server .
- An online version control repository (a private repository - that’s definitely a no-brainer -)
- Ruby - should be installed on your development machine alone. Do not install ruby on your server except you have got plans to put it into use.
I use Bitbucket since it allows for collaboration among teams and it has a more flexible payment plan than Github. Bitbucket allows for 5 free private repos before you incur your first charge. But i use github for my public activities .
Before we get started, i’d like to take some seconds to describe how capistrano works. It does deployment in a rather elegant and predictable way by SSHing to your remote server, creating a releases and current directory (on first deployment) on the remote server. It then grabs the latest code from your VCS repo (via SSH of course) and places it within a new folder in
current/ is basically a symbolic link to the most recent directory within the
Like Ben Orenstein said ; “bugs love company”. Let’s assume bad code got to the production server, all you have to do is use the
rollback command capistrano offers and it would move the symbolic link on
current/ to that of a previous release. Simple and awesome!.
Like i said before, you would be needing Ruby on your workstation ; so it’s necessary you “pull it down” if you do not have it already installed.
Terminal commands are given out in Ubuntu/Debian style, so be sure to modify them to fit that which your package manager requires - like centOS and redhat uses yum.
Be sure to confirm your installation by running a check on the version (your version may not be similar to what is shown below)
Gem is Ruby’s package manager - Like our (PHP’s) homeboy, Composer.
Up next is to install the deployment tool itself, Capistrano. Like ruby, capistrano should be installed on your development machine alone and you should have no cause to install it on your server.
So we have hunted down our dependencies - ruby and capistrano -, we should get the ball rolling.
We can now configure the project to make use of capistrano. Navigate to the root of your application and run the following command :
The command would create some files ; a
lib/ directory precisely. So it does make a lot of sense to inform your VCS not to track this files.
Capfile, you shouldn’t be doing anything in there except you do understand ruby or you need extra stuffs capistrano offers - which you most likely wouldn’t.
config/ directory is where you should be ;
deploy.rb: This is where you would be spending the most of your time, as it is were the settings for your application deployment would come into.
Open up the
config/deploy.rb file and update the following :
Then update the file with the following :
Large applications would always have a staging (test) server and a production server, but i’d assume we have only a production server. If you do have a test server, open up the
staging.rb file too and update it as appropriate.
Update the file as per what is obtainable below :
production.rbis a file that denotes an environment for your application. You might have a “test” server, in that case, you can make use of the
staging.rbor create a
test.rbfile in the
config/deploydirectory and edit. It is important to know that the
config/deploy.rbconfiguration file contains settings that would applied to all environments - test or production.
You should update your virtual host configuration to point to
/var/www/html/app/current. Remember the symbolic link stuff ?.
Preparing for Lift-off
Phew!!!, we are almost done. We need to set up push our code to the remote VCS repository, SSH authentication between our remote server and vcs repository.
On your development machine, you did do something like this - I use git.
On your remote server, if you do not have SSH authentication already configured, that should be the next thing you should do. If you already do, feel free to skip the following commands
Alternatively, you can log in as the root user before switching to the “username” user to complete the key generation process. It is best practice to actually restrict logging in as the root user though.
You should copy the key that pops up on the terminal and add it to your repository - that to make sure the repository can only be cloned by someone, in this case your server, who has the private key.
If your project makes use of composer, it’s best you gitignore the
vendor/ directory but commit your
composer.lock files, so you can run a
composer install on the server, rather than tracking “huge files” you could easily pull up.
The above requires you having composer installed on your server. You can checkout it’s website for an installation guide.
It is extremely important you commit the
composer.lockfile as it forces composer to install the same version of your dependencies as is on your development machine.
To make capistrano install your composer dependencies without lifting a finger on your remote machine terminal, all you have to do is to append the following to
Be sure to hunt down whatever dependencies your application uses - npm, bower, whatever - else the deployment would fail .
We already came a long way, and thankfully, we are done - yup like “done” - . Roll the drums please.
Navigate to the root of your directory and tell capistrano to do it’s thing.
That one-liner spits a lot of information, all you have to grab a cup of coffee or do something else for some 75 secs - depending on your internet connection, i once was stucked with a bad WiFi network and it took me nearly 10 minutes - .
I have attached a screenshot of the process below.
Haha moment ???
I talked about pushing bad code into production the other time, so how do you rollback and remove the bad code ? It’s a one-liner too!!!
There are features of capistrano that have not been touched, especially the tasks which is one of the most powerful components capistrano offers. The tasks have been talked about a little, for example, the composer installation would run only when the files have been fetched from the repo -
after :updated, :build- . Be sure to read about the available tasks available and use them to fine-grain up your deployment process.
I hope this helps someone.