Introduction

Open-Xchange is happy to release a first set of infrastructure cookbooks for the Chef automation platform. These cookbooks will help you to automate the configuration, deployment and management of your OX components across your network.

Install Requirements

For this tutorial we are assuming that you are running a Debian based Linux distribution. If your Operation System isn't Debian based the installation instructions will differ slightly depending on the package manager of your Operating System but you should still be able to follow and understand the overall approach.

The demo deployment covered in this tutorial neither reflects our deployment recommendations nor does it result in a supported installation of OX App Suite but its merely a convenient vehicle to show you how to use the provided infrastructure cookbooks for different deployment scenarios.

Before we can see the new cookbooks in action we have to provide some required tooling to fetch and use the cookbooks to automatically set up a new demo OX App Suite in a virtualized environment.

VirtualBox

VirtualBox is a hypervisor that allows the creation and management of guest virtual machines running Linux, Windows or other operating systems. We will use it to quickly generate virtual machines based on Debian Jessie or CentOS 7 which are supported platforms of OX App Suite.

+marens@openxchange:~$ sudo apt-get install virtualbox

Vagrant

Vagrant is a kind of wrapper around virtualization solutions like VirtualBox or VMware that presents a uniform interface for managing virtual machines. In our setup it will be used to create, configure and destroy the machines that are needed to set up the OX App Suite showcases or in general to work with chef/kitchen to test our cookbooks.

+marens@openxchange:~$ sudo apt-get install vagrant

ChefDK

The Chef Development Kit is a handy collection of tools that we'll need to make use of the cookbooks provided by Open-Xchange and set up a demo App Suite. Later on you can use it to develop your own specialized deployment cookbooks which are tailored to your needs.

To install it please go to www.chef.io and download/install the appropriate chef-dk for your operating system.

+marens@openxchange:~$  sudo dpkg -i chefdk_0.10.0-1_amd64.deb

Then verify the installation

+marens@openxchange:~$ chef verify
Running verification for component 'berkshelf'
Running verification for component 'test-kitchen'
Running verification for component 'tk-policyfile-provisioner'
Running verification for component 'chef-client'
Running verification for component 'chef-dk'
Running verification for component 'chef-provisioning'
Running verification for component 'chefspec'
Running verification for component 'generated-cookbooks-pass-chefspec'
Running verification for component 'rubocop'
Running verification for component 'fauxhai'
Running verification for component 'knife-spork'
Running verification for component 'kitchen-vagrant'
Running verification for component 'package installation'
Running verification for component 'openssl'
Running verification for component 'inspec'
.......
---------------------------------------------
Verification of component 'test-kitchen' succeeded.
Verification of component 'chef-dk' succeeded.
Verification of component 'chefspec' succeeded.
Verification of component 'rubocop' succeeded.
Verification of component 'knife-spork' succeeded.
Verification of component 'openssl' succeeded.
Verification of component 'berkshelf' succeeded.
Verification of component 'chef-client' succeeded.
Verification of component 'fauxhai' succeeded.
Verification of component 'inspec' succeeded.
Verification of component 'tk-policyfile-provisioner' succeeded.
Verification of component 'kitchen-vagrant' succeeded.
Verification of component 'chef-provisioning' succeeded.
Verification of component 'generated-cookbooks-pass-chefspec' succeeded.
Verification of component 'package installation' succeeded.

You see that we installed several new components with the chef-dk. Some of them will be used in the upcoming steps of this tutorial: test-kitchen, kitchen-vagrant and berkshelf so let's make the new tools known to our running shell.

eval "$(chef shell-init bash)"

If you don't want to do this manually every time you want to work with chef/kitchen you can add this to the startup scripts of your shell, see the chef docs for more infos.

+marens@openxchange:~$ echo 'eval "$(chef shell-init bash)"' >> ~/.profile

Git

Our infrastructure and deployment cookbooks are versioned via git so you'll need a working git installation to check out the cookbooks.

+marens@openxchange:~$ sudo apt-get install git

Deployment showcases as cookbooks

Get from git

+marens@openxchange:~$ git clone https://code.open-xchange.com/git/deployment/showcase

Update from git

When future changes from our side modify cookbook dependencies you should ensure that you are using the latest cookbooks (and dependencies) specified in the showcase deployment after pulling from git. The later point Kitchen details will explain what berks does and where exactly it comes into effect.

+marens@openxchange:~$ cd showcase
+marens@openxchange:~$ git pull 
+marens@openxchange:~$ berks update

Available showcases

+marens@openxchange:~$ cd showcase
+marens@openxchange:singlenode$ kitchen list
Instance                      Driver   Provisioner  Verifier  Transport  Last Action
showcase-customer-centos-7        Vagrant  ChefSolo     Busser    Ssh        <Not Created>
showcase-customer-debian-jessie   Vagrant  ChefSolo     Busser    Ssh        <Not Created>
showcase-community-centos-7       Vagrant  ChefSolo     Busser    Ssh        <Not Created>
showcase-community-debian-jessie  Vagrant  ChefSolo     Busser    Ssh        <Not Created>

The list of available showcases is built from the available suites and platforms configured in kitchen.yaml.vagrant.

platforms:
  - name: centos-7
    driver:
      box: centos/7
  - name: debian-jessie
    driver:
      box: debian/jessie64

The platform images are automatically downloaded from atlas.hashicorp.com to ~/.vagrant.d/boxes/ on your workstation. At atlas.hashicorp.com you can search for other images in case one of those mentioned in this showcase is too outdated or no longer available.

Customer showcase

This showcase consists of the following components:

  1. Postfix
  2. Dovecot
  3. Mysql
  4. OX App Suite
  5. OX Documents
  6. OX Guard

To use this you'll have to edit/create a local config

+marens@openxchange:~$ vim config/local.rb

and add

$oxconfig.ldb_login = "your_login"
$oxconfig.ldb_password = "your_password"

This file is part of .gitignore so that passwords won't be added to your git when start developing your own deployments based on our infrastructure cookbooks.

Community showcase

Use this if you don't have a valid license key for Open-Xchange products and simply want to install the free components of OX App Suite. Compared to the customer showcase you'll be missing a working documentconverter so there won't be any document previews, thumbnails or conversion from proprietary document formats but otherwise the same stack of components will be installed and configured.

Deploy

We will use a two step approach here:

  1. Create the VM, done via kitchen create
  2. Deploy and configure OX App Suite in that VM, done via kitchen converge

for now we'll focus on the debian platform but feel free to retry the steps outlined here with centos. Depending on your choice you'll have to use either showcase-community-debian-jessie or showcase-customer-debian-jessie as last parameter of the kitchen command line tool.

Create showcase VM

This will take a while for the first run as vagrant will have to download the debian-jessie image which will be used as base for the virtual machine we want to install our showcase in.

+marens@openxchange:singlenode$ kitchen create showcase-community-debian-jessie

-----> Creating <showcase-community-debian-jessie>...
      Bringing machine 'default' up with 'virtualbox' provider...
      ==> default: Box 'debian/jessie64' could not be found. Attempting to find and install...
          default: Box Provider: virtualbox
          default: Box Version: >= 0
      ==> default: Loading metadata for box 'debian/jessie64'
          default: URL: https://atlas.hashicorp.com/debian/jessie64
      ==> default: Adding box 'debian/jessie64' (v8.5.0) for provider: virtualbox
          default: Downloading: https://atlas.hashicorp.com/debian/boxes/jessie64/versions/8.5.0/providers/virtualbox.box
==> default: Successfully added box 'debian/jessie64' (v8.5.0) for 'virtualbox'!
      ==> default: Importing base box 'debian/jessie64'...
==> default: Matching MAC address for NAT networking...
      ==> default: Checking if box 'debian/jessie64' is up to date...
      ==> default: Setting the name of the VM: kitchen-singlenode-showcase-community-debian-jessie_default_1466692684380_68718
      ==> default: Clearing any previously set network interfaces...
      ==> default: Preparing network interfaces based on configuration...
          default: Adapter 1: nat
      ==> default: Forwarding ports...
          default: 80 => 8080 (adapter 1)
          default: 443 => 8443 (adapter 1)
          default: 22 => 2222 (adapter 1)
      ==> default: Running 'pre-boot' VM customizations...
      ==> default: Booting VM...
      ==> default: Waiting for machine to boot. This may take a few minutes...
          default: SSH address: 127.0.0.1:2222
          default: SSH username: vagrant
          default: SSH auth method: private key
          default: 
          default: Vagrant insecure key detected. Vagrant will automatically replace
          default: this with a newly generated keypair for better security.
          default: 
          default: Inserting generated public key within guest...
          default: Removing insecure key from the guest if it's present...
          default: Key inserted! Disconnecting and reconnecting using new SSH key...
      ==> default: Machine booted and ready!


Kitchen create.png


You instructed kitchen to create a new VM for our showcase-community-debian-jessie demo deployment.

Deploy to showcase VM

Now let's use the bare debian VM and install OX App Suite on it. Again this is done via kitchen.

+marens@openxchange:singlenode$ kitchen converge showcase-community-debian-jessie
-----> Converging <showcase-community-debian-jessie>...
       Preparing files for transfer
       Preparing dna.json
       Resolving cookbook dependencies with Berkshelf 4.0.1...
       Removing non-cookbook files before transfer
       Preparing data_bags
       Preparing environments
       Preparing roles
       Preparing solo.rb
-----> Installing Chef Omnibus (install only if missing)
       Downloading https://www.chef.io/chef/install.sh to file /tmp/install.sh
       Trying wget...
       Download complete.
       Downloading Chef  for debian...
       downloading https://www.chef.io/chef/metadata?v=&prerelease=false&nightlies=false&p=debian&pv=8.2&m=x86_64
         to file /tmp/install.sh.1170/metadata.txt
       trying wget...
       Installing Chef 
       installing with dpkg...
       Selecting previously unselected package chef.
(Reading database ... 30461 files and directories currently installed.)
       Preparing to unpack .../chef_12.5.1-1_amd64.deb ...
       Unpacking chef (12.5.1-1) ...
       Setting up chef (12.5.1-1) ...
       Thank you for installing Chef!
       Transferring files to <showcase-community-debian-jessie>
       Starting Chef Client, version 12.5.1
       Compiling Cookbooks...
       ...
       ...
       Chef Client finished, 261/418 resources updated in 15 minutes 10 seconds
       Finished converging <showcase-community-debian-jessie> (21m48.67s).

After the kitchen converge run finished successfully we have a working OX App Suite setup as show below.

The chef client:

  • installed the required backend services
  • installed the ox middleware including ox documents
  • set up the ox guard server against the middleware
  • set up the apache http server/proxy in front of our middleware components


Kitchen converge.png

Login

SSH

You can easily login via ssh to take a look at the configured system.

+marens@openxchange:singlenode$ kitchen login showcase-community-debian-jessie

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have mail.
Last login: Mon Nov 30 16:03:34 2015 from 10.0.2.2
vagrant@singlenode:~$ sudo su
root@singlenode:/home/vagrant#

HTTP

As we forwarded the ports 80 and 443 from the VM to ports 8080 and 8443 on our host you can easily login to your new OX App Suite with your browser via http or https. For https you'll have to manually trust the certificate we automatically created during the kitchen converge phase.

Some demo logins are:

  • user1@context1.example.com
  • user2@context1.example.com
  • user3@context1.example.com
  • user4@context1.example.com

They all share the password: secret


FirstLogin.png


Destroy

To remove the machine we just deployed simply use

 +marens@openxchange:singlenode$ kitchen destroy showcase-customer-debian-jessie

Kitchen details

We already saw that Kitchen offers a nice level of abstraction that lets you easily create environments to execute and automatically test your cookbooks without too much manual preparation but what happened behind the scenes during the kitchen converge run?

  1. A dna.json file gets created. This file is based on the entries of the matching showcase entry in .kitchen.yml. It acts a starting point for the chef client as the run list entry contains all needed infos to configure a machine into our desired state. Additionally this file may contain further entries like e.g. the ldb credentials for our customer showcase.
  2. Berkshelf takes a look at the cookbook dependencies specified in Berksfile and metadata.rb, builds a dependency graph and downloads the missing dependencies. Those can be other open-xchange cookbooks from git or other third party cookbooks.
  3. Data Bags needed for our deployment are collected. Data Bags are general purpose data containers that are indexed for fast lookups.
  4. Environments specified to represent different workflows are collected. In the directory environments you'll find separate environments for our customer and community showcases.
  5. The Roles we have defined for our deployments are collected. Roles are a way to assign attributes and features to a machine in our deploymnet environment. When you look into 'roles/singlenode_showcase.rb' you can inspect the role that we are using for our showcases. These define e.g. that the target machine will be running ox documents and guard in addition tothe default groupware components.
  6. A file called solo.rb is created. This is the main configuration file for the chef client. It tells him where to find the cookbooks dependencies that Berkshelf computed, the Data Bags, Environments and Roles we defined.
  7. The chef client is downloaded and installed.
  8. All needed files mentioned above are transferred onto the target machine into the directories configured in solo.rb.
  9. The chef client is started on the target machine and begins its run with the first element of the run_list defined in dna.json.

You can follow all the details when running

+marens@openxchange:~$ kitchen converge -l debug showcase-community-debian-jessie | tee debug.log

Cookbooks

Deployment cookbooks

You can find our freely available deployment cookbooks at https://code.open-xchange.com under /deployment/development

singlenode

The singlenode deployment cookbook used in this tutorial describes our simple deployment showcases that should help you understand how deployment and infrastructure cookbooks work together and give you an example how our infrastructure cookbooks are used in detail.

I'll briefly explain the deployment cookbook before i let you dive into the code itself to start exploring and experimenting.

  1. As already explained above the first thing that the chef client needs to get started is the run_list entry from dna.json. This run_list instructs the client that the machine should be assigned the role role[singlenode_showcase]
  2. Looking into roles/singlenode_showcase.rb you find yet another run_list containing several recipes that should be executed. After they are executed successfully the machine will fulfill the associated role. The format of those recipe entries is cookbook_name::recipe_name
  3. As example recipe[singlenode::documents] instructs the client to run the recipe located at cookbooks/singlenode/recipes/documents.rb which then causes the OX Documents feature to be installed by including further recipes open-xchange-documents::default and singlenode::default

Let's have a quick look at the cookbooks/singlenode/recipes/default.rb

=begin
#<
Default recipe that takes care of installing core components.
This covers:
  * Webserver
  * Database
  * Mailservers (IMAP, SMTP)
  * OX Frontend and Backend
and provisions the specified contexts/users.
#>
=end

include_recipe 'hostname'
include_recipe 'singlenode::data_bag_check'

# Generate SSL cert and key if desired
if node['open-xchange-apache']['ssl']['enable']
    cert = ssl_certificate 'ox-apache' do
      namespace node['ox-apache']
    end
    node.default['open-xchange-apache']['ssl']['cert'] = cert.cert_path
    node.default['open-xchange-apache']['ssl']['key'] = cert.key_path
end

include_recipe 'open-xchange-singlenode::webserver'
include_recipe 'open-xchange-singlenode::database'
include_recipe 'open-xchange-singlenode::mailstore'

# Use updated hostname for postfix main.cf template
begin
    r = resources(template: "#{node['postfix']['conf_dir']}/main.cf")
    r.variables r.lazy {
        node.default['postfix']['main']['mydomain'] = (node['domain'] || node['hostname']).to_s.chomp('.')
        node.default['postfix']['main']['myhostname'] = (node['fqdn'] || node['hostname']).to_s.chomp('.')
        { :settings => node['postfix']['main'] }
    }
end

include_recipe 'open-xchange-singlenode::default'
include_recipe 'open-xchange-singlenode::provisioning'

You'll notice a pattern where configuration attributes for this machine or node are read

if node['open-xchange-apache']['ssl']['enable']

or set

node.default['open-xchange-apache']['ssl']['cert'] = cert.cert_path

These attributes can be set before the chef client run depending on your needs and how your infrastructure is set up. We did this for our showcases via environments. If you have a look at e.g. environments/community.rb you'll find

...
default_attributes 'set_fqdn' => 'singlenode.example.com',
  'open-xchange' => {
  ...
  },
  'open-xchange-apache' => { 'allowedwebservices' => 'all', 'ssl' => { 'enable' => true } }
...

where we specified that we wanted to enable ssl for our apache installation that is now reachable via https

There are many of those attributes that can influence the outcome of your deployment run. Each of these properties should be listed and documented in the README.md of the associated cookbok.

Have a look at the README.md of the open-xchange-apache infrastructure cookbook. There you'll find the attribute documented as:

node['open-xchange-apache']['ssl']['enable']
Whether to enable SSL. If you enable it you must take care that the attributes for cert and key contain the correct absolute paths to the according files when apache is configured.

The documentation of the singlenode cookbook can be found at https://code.open-xchange.com/#contentPanel;1dOjgsn6qB;null;cookbooks/singlenode/README.md;content

Infrastructure cookbooks

Our infrastructure cookbooks are freely available via https://code.open-xchange.com at /infrastructure/cookbook/ox. Below you'll find a quick overview of the infrastructure cookbooks used in this demo deployment with direct links to the configuration attributes.

open-xchange-apache

This cookbook provides a complete Apache configuration as webserver for Open-Xchange. Its definitions and recipes reduce the necessary deployment wrapper cookbook code to its minimum.

Direct link to README: https://code.open-xchange.com/#contentPanel;6VOgDCL4bE;null;README.md;content

open-xchange-backend-core

Can be used to install packages selected via attributes and subsequently modifies the OX App Suite config files. Furthermore it can be used to register servers, filestores and databases.

Direct link to README: https://code.open-xchange.com/#contentPanel;BhOg6voVu9;null;README.md;content

open-xchange-core

Core package to bundle tooling for all open-xchange modules. Currently contains definitions for gem installations and modification of our properties files.

Direct link to README: https://code.open-xchange.com/#contentPanel;6gP1zr0PK1;null;README.md;content

open-xchange-documents

Marks the OX Documents packages for installation and adds the needed permission properties.

Direct link to README: https://code.open-xchange.com/#contentPanel;FaOikSCZc3;null;README.md;content

open-xchange-frontend-core

Installs the OX App Suite or OX6 packages depending on your attribute choices

Direct link to README: https://code.open-xchange.com/#contentPanel;5WOheggxs5;null;README.md;content

open-xchange-guard

Is used to first adapt the OX middleware with the rest interface that guard needs and second to install OX Guard.

Direct link to README: https://code.open-xchange.com/#contentPanel;DmPGX6xkk5;null;README.md;content

open-xchange-repository

Builds proper OX repo URLs enables those repos for your Linux distribution. Furthermore contains definitions for package installation

Direct link to README: https://code.open-xchange.com/#contentPanel;44Oig9OOa1;null;README.md;content

open-xchange-singlenode

Bundles recipes that can be reused for various single node deployments like postfix-, dovecot- and apache configuration and user provisioning for OX App Suite.

Direct link to README: https://code.open-xchange.com/#contentPanel;50Okd9tl2C;null;README.md;content

Local cookbooks

If you want to start developing your own infrastructure cookbooks or want to modify our existing cookbooks you can do so by e.g. checking out one of our infrastructure cookbooks from code.open-xchange.com and making it know to Berkshelf. As explained above Berkshelf will automatically pull our infrastructure cookbooks from code.open-xchange.com for you. This is configured in Berksfile

oxconfig.cookbooks.each do |name, values|
  location = $oxconfig.cookbook_locations[name]
  case location
  when "git"
    cookbook name, git: values["git"], tag: values["git_tag"]
  when "path"
    cookbook name, path: values["path"]
  when "site"
    raise "not yet implemented"
  else
    raise "unknown location \"#{location}\""
  end 
end

We see that currently we are able to work with cookbooks from git or from path.

The config details for the cookbooks can be found in config/default.rb

$oxconfig.cookbooks = { 
  "open-xchange-backend-core" => {
    "path"     => File.expand_path("../../../../infrastructure/open-xchange-backend-core", __FILE__),
    "git"      => "https://code.open-xchange.com/git/infrastructure/cookbook/ox/open-xchange-backend-core",
    "git_tag"  => "0.9.7"
  },
...
# Define the location per cookbook to use, defaults to git
# Available: path, git, site
$oxconfig.cookbook_locations = { 
  "open-xchange-backend-core" => "git",
  "open-xchange-core"         => "git",
...

If you you wanted to modify e.g. open-xchange-backend-core you'd have to:

  1. Clone it from git (best into the relative path already defined in config/default.rb so you don't have to do additional modifications)
  2. Tell Berkshelf about it by overriding the location from git to path in config/local.rb
$oxconfig.cookbook_locations["open-xchange-core"] = "path"

and updating your Berkshelf

berks update

From then on the modified cookbook will be uploaded to your vagrant virtual machine and used during your next kitchen converge run. The same approach can be used for additional cookbooks you might want to create for your deployment scenarios.