Defining roles
Here we will construct our three roles, one each for our base server configuration, database server, and web server. Each role will have a set of recipes to run, with the base server providing the user accounts, SSH keys, and other common components, and then the others providing configuration data for PostgreSQL and nginx, respectively.
Creating the base server role
The key bits that are of interest in our base server role are the run list and the configuration data that specify which group to populate users for. If you look at the file roles/base_server.json
, you will see that we have defined one group of users to pull from our data bags:
"override_attributes": { "shell_users": { "group": "webapp" } }
And then, the recipe we want to use that will populate the users on the host is in the run list:
"run_list": [ "users::shell_users" ],
In order to load the role into Chef, you can issue a from file
command:
knife role from file base_server.json Updated Role base _server!
You can verify that the role was created with a simple role list
command:
[user]% knife role list base_server
Creating the database server role
Let's take a look at some portions of our database server role, as defined in roles/postgresql_server.json
. This file contains the description of our PostgreSQL server as modeled earlier in the chapter. What is of interest in this file is our override_attributes
section; these are settings we want to use in place of the default values provided by our postgresql
cookbook. As mentioned before, you will want to look at the documentation and the default attributes.rb
file to find out what attributes you can set for a given cookbook and its recipes.
The PostgreSQL recipes use a postgresql
configuration section that contains a config
section for server-specific configuration and properties, and pg_hba
for the authentication data. Looking at the postgresql
section, we can see that we want to install Version 9.3, and we want it to listen on all addresses (0.0.0.0
) on port 5432
:
"version": "9.3", "config": { "listen_addresses": "0.0.0.0", "port": "5432" },
In addition, the pg_hba
section contains an array of JSON objects that describes which users have access to the service, by what mechanism they are able to authenticate themselves (MD5, trusted, local ident service, and so on), and from where they can connect. This is coded into our configuration, but the recipes can be extended to use data bags to determine this information as well. It is too long to include all of it here, but if you look at the pg_hba
data, you will see that there are three entries: one for the user webuser
to connect from anywhere using an MD5 password, and two for local users to access the default template database, and for the postgres
user itself to modify the webapp
database.
In addition to the configuration data, there is a run list—this tells Chef what recipes this role will include. You can see from this example that we will be installing the PostgreSQL server and then provisioning our webapp-specific user and database (found in cookbooks/pythonwebapp/recipes/database.rb
):
"run_list": [ "postgresql::server", "pythonwebapp::database" ],
In order to use this, we want to load our JSON file into Chef to define our database server role:
knife role from file postgresql_server.json Updated Role postgresql_server!
You can check that the role was created with a role list
command:
[user]% knife role list base_server postgresql_server
Creating the web server role
Our web application role is located in the roles/web_server.json
file and contains the required information for our web server. If you take a look at the JSON file, you will see that the run list contains four entries:
"run_list": [ "python", "python::virtualenv", "supervisor", "pythonwebapp::webapp" ],
Because our application relies on Python, we want to install the required version of Python on our hosts as well as build a Python virtualenv
tool for our application. In addition, we will be using supervisord as the process monitor that is responsible for ensuring that our web service starts and stays running. We also need to install our web application once we have met our prerequisites.
Similar to how we loaded the PostgreSQL role from our JSON file, we can repeat the process for our web server role:
knife role from file web_server.json Updated Role web_server!
Again, you can check that the role was created with a simple role list
command:
[user]% knife role list base_server postgresql_server web_server