Book Image

Creating Development Environments with Vagrant

By : MICHAEL KEITH PEACOCK
Book Image

Creating Development Environments with Vagrant

By: MICHAEL KEITH PEACOCK

Overview of this book

Table of Contents (17 chapters)
Creating Development Environments with Vagrant Second Edition
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Creating the Puppet manifests


Let's start by creating some folders for our Puppet modules and manifests by executing the following commands:

mkdir provision
cd provision
mkdir modules
mkdir manifests

For each of the modules we want to create, we need to create a folder within the provision/modules folder for the module. Within this folder, we need to create a manifests folder, and within this, our Puppet manifest file, init.pp. Structurally, this looks something like the following:

|-- provision
|   |-- manifests
|   |   `-- vagrant.pp
|   `-- modules
|       |-- our module
|           |-- manifests
|               `-- init.pp
`-- Vagrantfile

Installing Nginx

Let's take a look at what is involved to install Nginx through a module and manifest file provision/modules/nginx/manifests/init.pp. First, we define our class, passing in a variable so that we can change the configuration file we use for Nginx (useful for using the same module for different projects or different environments such as staging and production environments), then we need to ensure that the nginx package is installed:

class nginx ($file = 'default') {

  package {"nginx":
    ensure => present
  }

Tip

Note that we have not closed the curly bracket for the nginx class. That is because this is just the first snippet of the file; we will close it at the end.

Because we want to change our default Nginx configuration file, we should update the contents of the Nginx configuration file with one of our own (this will need to be placed in the provision/modules/nginx/files folder; unless the file parameter is passed to the class, the file default will be used):

file { '/etc/nginx/sites-available/default':
      source => "puppet:///modules/nginx/${file}",
      owner => 'root',
      group => 'root',
      notify => Service['nginx'],
      require => Package['nginx']
}

Finally, we need to ensure that the nginx service is actually running once it has been installed:

service { "nginx":
    ensure => running,
    require => Package["nginx"]
  }
}

This completes the manifest. We do still, however, need to create a default configuration file for Nginx, which is saved as provision/modules/nginx/files/default. This will be used unless we pass a file parameter to the nginx class when using the module. The sample file here is a basic configuration file, pointing to the public folder within our synced folder. The server name of lemp-stack.local means that Nginx will listen for requests on that hostname and will serve content from our projects folder:

server {
    listen   80;

    root /var/www/project/public;
    index index.php index.html index.htm;

    server_name lemp-stack.local;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        #fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SERVER_NAME $host;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }

    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
        access_log off;
        expires max;
    }

    location ~* \.svgz {
        add_header Content-Encoding "gzip";
    }
}

Tip

Because this configuration file listens for requests on lemp-stack.local, we need to add a record to the hosts file on our host machine, which will redirect traffic from lemp-stack.local to the IP address of our virtual machine.

Installing PHP

To install PHP, we need to install a range of related packages, including the Nginx PHP module. This would be in the file provision/modules/php/manifests/init.pp.

On more recent (within the past few years) Linux and PHP installations, PHP uses a handler called php-fpm as a bridge between PHP and the web server being used. This means that when new PHP modules are installed or PHP configurations are changed, we need to restart the php-fpm service for these changes to take effect, whereas in the past, it was often the web servers that needed to be restarted or reloaded.

To make our simple PHP Puppet module flexible, we need to install the php5-fpm package and restart it when other modules are installed, but only when we use Nginx on our server. To achieve this, we can use a class parameter, which defaults to true. This lets us use the same module in servers that don't have a web server, and where we don't want to have the overhead of the FPM service, such as a server that runs background jobs or processing:

class php ($nginx = true) {

If the nginx parameter is true, then we need to install php5-fpm. Since this package is only installed when the flag is set to true, we cannot have PHP and its modules requiring or notifying the php-fpm package, as it may not be installed; so instead we need to have the php5-fpm package subscribe to these packages:

    if ($nginx) {
        package { "php5-fpm":
          ensure => present,
          subscribe => [Package['php5-dev'], Package['php5-curl'], Package['php5-gd'], Package['php5-imagick'], Package['php5-mcrypt'], Package['php5-mhash'], Package['php5-pspell'], Package['php5-json'], Package['php5-xmlrpc'], Package['php5-xsl'], Package['php5-mysql']]
        }
    }

The rest of the manifest can then simply be the installation of the various PHP modules that are required for a typical LEMP setup:

    package { "php5-dev":
        ensure => present
    }

    package { "php5-curl":
        ensure => present
    }

    package { "php5-gd":
        ensure => present
    }

    package { "php5-imagick":
        ensure => present
    }

    package { "php5-mcrypt":
        ensure => present
    }

    package { "php5-mhash":
        ensure => present
    }

    package { "php5-pspell":
        ensure => present
    }

    package { "php5-xmlrpc":
        ensure => present
    }

    package { "php5-xsl":
        ensure => present
    }

    package { "php5-cli":
        ensure => present
    }

    package { "php5-json":
        ensure => present
    }
}