Chef can also be used to deploy applications from code repositories. It combines one of the most complete, feature rich, and complicated Chef resources available—the deploy
resource—and the various powerful and popular cookbooks, such as the database
cookbook. We'll show you how to deploy a simple WordPress application right from the GitHub repository, creating a dedicated database and user as well as all the required dependencies. This builds on what has already been done previously, but the resources and cookbook shown here are made to be reusable anywhere.
To step through this recipe, you will need:
As we're going to deploy an application for MySite (maybe an engineering blog for the MySite company), let's call this recipe mysite::deploy
. Create the recipe like this from chef-repo
:
$ chef generate recipe cookbooks/mysite deploy
Our next steps will be to include the Apache and MySQL dependencies, configure everything on MySQL so that WordPress can be installed, and finally deploy the WordPress code from GitHub.
A WordPress installation needs at least an HTTP server and a database. Start by including the known dependencies to the service we already have: an Apache virtual host and MySQL. Include them in deploy.rb
:
include_recipe 'apache::virtualhost' include_recipe 'mysite::mysql'
Before we deploy anything, we need to create a database on our already running MySQL server with a dedicated WordPress user. There's a wonderful cookbook meant just for this: the database
cookbook. We'll reuse this one very often. It gives access to many helpers for most use cases and most types of databases. According to the documentation, we'll need to deploy a gem named mysql2_chef_gem
, which fortunately comes with a dedicated cookbook as well. And finally, as we're using MySQL, let's make sure we depend on its official cookbook. Let's include all of this information in our mysite
cookbook's metadata.rb
:
depends 'database' depends 'mysql2_chef_gem', '~> 1.1' depends 'mysql', '~> 8.1'
To build the mysql2
gem using the cookbook's new mysql2_chef_gem
resource, we'll need the MySQL development package named mysql-community-devel
. Let's add the following to our deploy.rb
recipe:
package 'mysql-community-devel' mysql2_chef_gem 'default' do action :install end
The database cookbook created, among others, two useful resources for us: mysql_database
and mysql_database_user
. As we can guess by their names, they respectively help create MySQL databases and MySQL users. Let's create the MySQL connection information variable so it can be reused in our two resources:
mysql_connection_info = { host: '127.0.0.1', username: 'root', password: 'super_secure_password' }
Now we can create our database named wordpress
using the mysql_database
resource:
mysql_database 'wordpress' do connection mysql_connection_info action :create end
Also, create a wordpress_user
MySQL user with the password changeme
. This will create the user and grant all the privileges to it:
mysql_database_user 'wordpress_user' do connection mysql_connection_info password 'changeme' database_name 'wordpress' host '%' privileges [:all] action [:create, :grant] end
At this point, we should have everything we need related to the database.
Now on to application deployment! We know we want to deploy from git
. Let's make sure git
is installed:
package 'git'
The deploy_revision
resource is the most complex of all. It has a multitude of options, and a full chapter about it wouldn't be enough. Let's keep it simple here and refer to the complete online documentation for more complex uses. Let's keep it simple here, and please refer to the very complete online documentation for more complex uses—because this resource is absolutely powerful and does wonders when properly manipulated. We know the following:
HEAD
) and keep the last five revisions to allow rollbacksapache
user/var/www/#{node['sitename']}
)The deploy_revision
resource is modeled after Capistrano and therefore comes from the Ruby on Rails world. But the concepts still apply to most languages, and it's a good practice in production to create shared folders and symlinks for long-lasting configurations and files. It includes certificates, database configuration files, local assets, and so on. However, to keep the current deployment simple, we won't use these right now, even though you'll probably start looking into it as soon as you'll need it. We'll include the symlinks configuration and initialize them to nothing so the code is already present when the time arises. Here's how all this ties together:
deploy_revision 'wordpress' do repo 'https://github.com/WordPress/WordPress' revision 'HEAD' user 'apache' deploy_to "/var/www/#{node['sitename']}" keep_releases 5 symlinks({}) symlink_before_migrate({}) migrate false action :deploy end
Once the code is applied, the /var/www/mysite
(or whatever name you may have overridden) structure will change a little:
$ ls /var/www/mysite/ current index.html releases shared
There's a current
, releases
, and shared
folder. The shared
folder contains everything that will last through the releases, including a cached copy of the current code. The releases
folder contains all the stored releases. The current
folder is itself a symlink to a specific release, which is the git commit SHA on GitHub (72606bed348e61b6f98318cf920684765aa08b37
). Each subsequent release will be identified by its SHA indicating its unique identification and symlinked to current
at the end of the deployment process. The number of kept releases is set by the keep_releases
integer:
$ ls -ld /var/www/mysite/current lrwxrwxrwx. 1 apache root 65 Nov 17 02:18 /var/www/mysite/current -> /var/www/mysite/releases/72606bed348e61b6f98318cf920684765aa08b37
Once this code is applied to our node, if we navigate to http://<node_ip>/current/
, we'll see the WordPress setup page:
To check whether the connection to the database is working correctly, type in all of the information from our Chef code:
And, job done! The WordPress installer says, All right, sparky! You’ve made it through this part of the installation. WordPress can now communicate with your database. If you are ready, time now to... run the installer!.
We're now basically able to deploy any WordPress installation from scratch, at will, and in seconds, again and again.
With Puppet, there is no deploy resource. However, Puppet Labs is providing a useful module—vcsrepo
. With this module, we will be able to deploy a WordPress site from git.
Let's reuse our Vagrant LAMP example in Chapter 6, Fundamentals of Managing Servers with Chef and Puppet. We just need to add the vcsrepo
module to Puppetfile
(do not forget to run r10k puppetfile install
):
mod 'puppetlabs/vcsrepo', '1.4.0'
Now we are ready to modify the main manifest of the box, namely web.pomes.pro
, to include the WordPress deployment. First, install the git
package:
package {'git': ensure => installed, }
Then, create a database for WordPress:
mysql::db {'wordpress': user => 'wordpress_user', password => 'changeme', host => '%', grant => 'ALL', }
Also, update our virtual definition to change DocumentRoot
:
apache::vhost { 'web.pomes.pro': website => 'web.pomes.pro', docroot => '/var/www/wordpress', }
And finally, install WordPress from git
and give rights to Apache:
vcsrepo {'/var/www/wordpress': ensure => latest, provider => git, source => 'https://github.com/WordPress/WordPress', revision => 'master', } file {'/var/www/wordpress': ensure => directory, owner => 'www-data', group => 'www-data', recurse => true, }
deploy
resource documentation at https://docs.chef.io/resource_deploy.htmlvcsrepo
module at https://forge.puppet.com/puppetlabs/vcsrepo3.22.77.63