Vagrant for a PHP project

    Impressed by article 5 of Easy Ways to Get Started with PHP on Vagrant, I want to share my way of using Vagrant for a PHP project.

    What I wanted to achieve:
    • Only Vagrant and VirtualBox are installed on the developer's machine;
    • Virtual machine settings are stored in the project repository, allowing the developer to quickly deploy it, as well as flexibly configure it to the needs of the project and share these settings with team members;

    These goals were achieved with the help of Chef-Solo. The result was a certain preparation both for creating new projects based on it, and for integrating existing projects into it: vagrant-php .



    The scenario of working with such a project for a new member of the team is very simple:

    1. You need to install Vagrant and VirtualBox , as well as several Vagrant plugins:
      $ vagrant plugin install vagrant-librarian-chef-nochef vagrant-omnibus
      
    2. Download project from repository:
      $ git clone repo path
    3. Copy Vagrantfile and start the virtual machine:
      $ cd path
      $ cp .chef/Vagrantfile Vagrantfile
      $ vagrant up
      

    That's it, the virtual machine has deployed, the packages have been installed, the application is working!

    The vagrant-librarian-chef-nochef plugin is designed to load Chef's external cookbooks and manage their dependencies without installing Chef itself on the local machine. This plugin allows you not to store external cookbooks in your repository, but to load them the first time you turn on the virtual machine.

    The vagrant-omnibus plugin allows you to specify a specific version of Chef that will be installed in the virtual machine (this allows you to use almost any image from vagrantcloud.com , and also allows you to fix the version of Chef).

    What's inside?


    • Ubuntu Trusty 14.04 (32 bit, current);
    • Nginx (latest version from Nginx PPA);
    • PHP 5.6 (from ondrej PPA), Composer;
    • Memcached (from the standard Ubuntu repository);
    • MySQL 5.5 (from the standard Ubuntu repository);
    • PostgreSQL 9.3 (from PostgreSQL PPA).

    It should be noted that, if desired, any of these components can be replaced. The concept itself is universal.

    How to integrate this environment with your PHP project?


    If there is an existing PHP project, then you need to download the project from the repository:
    $ git clone repo path
    

    If you need to start a new project, you must first create a directory for it:
    $ mkdir path
    

    Then you need to copy the ".chef" directory to the project directory and make the necessary settings in the ".chef / nodes / 10.2.2.10.json" file (see below about the structure of the json file) and ".chef / Vagrantfile".

    Now all that remains is to copy the ".chef / Vagrantfile" file to the root of the project and start the virtual machine:
    $ cd path
    $ cp .chef/Vagrantfile Vagrantfile
    $ vagrant up
    

    If you are creating a new project, you need to log in to the virtual machine via SSH under the application user (see below for SSH access), install the project using Composer, and then upload the contents of the project from the virtual machine to the local directory:
    $ composer create-project --prefer-dist yiisoft/yii2-app-basic /home/php-app/www
    

    It is also advisable to add the line "/ Vagrantfile" to the project ".gitignore" file. This will allow the developer to make local changes to the settings of the virtual machine (for example, to reduce the size of RAM), without reflecting these changes in VCS.

    After that, you should check the operability of the project in a virtual environment, and if the project is operational, you can commit the project directory (to a new or existing repository).

    Ssh access


    There are two ways to access a virtual machine through SSH:
    • As an administrator:
      $ vagrant ssh
    • As the user under whom the application is deployed:
      $ ssh php-app@10.2.2.10 -i '.chef/files/id_rsa'

    By default, password entry is disabled (parameter ["openssh"] ["server"] ["password_authentication"]), therefore, the keys specified in the parameter ["php-app"] ["ssh"] [ "Authorized_keys"]. This array lists the full paths to the files in the virtual machine. Since the ".chef" directory is mounted in the "/ tmp" directory of the virtual machine, the paths look like this: "/tmp/.chef/files / ...". By default, the public key is "id_rsa.pub", the private key for which lies right there under the name "id_rsa".

    Directory structure ".chef"


    • files / - directory for storing files used in the php-app recipe (these files are available inside the virtual machine by the path "/tmp/.chef/files/");
    • nodes / - directory for storing virtual machine settings;
    • cookbooks / - directory for storing downloaded external cookbooks (created automatically);
    • site-cookbooks / - directory for storing internal cookbooks of the project itself;
    • tmp / - temporary directory (created automatically);
    • Cheffile - dependencies for internal cookbooks (needed for "librarian-chef");
    • Cheffile.lock - fixed versions of cookbooks (the file is created automatically);
    • solo.rb - settings file for Chef-Solo, launched inside the virtual machine;
    • Vagrantfile - a template file with Vagrant settings (this file will be used by other team members as a sample).

    The structure of the json file with the settings of the virtual machine


    The run_list parameter lists the recipes that will be executed when the machine is deployed and the environment is prepared. All other parameters are the settings of the respective cookbooks.

    The ".chef / nodes" directory has several ready-made examples for applications based on the Yii2 framework:
    • yii2_advanced.json - settings for deploying the advanced Yii2 application template;
    • yii2_basic.json - settings for deploying the basic Yii2 application template.

    The environment itself is not tied to Yii2 in any way, but these settings can be used as an example.

    The php-app cookbook is local (located in ".chef / site-cookbooks" and commits to the project repository) and is designed to deploy the application on the server. It performs the following actions:
    1. Creation of a separate system user for the application (parameters ["php-app"] ["user"] and ["php-app"] ["group"]);
    2. Creation of necessary directories (parameters ["php-app"] ["project_dir"] and ["php-app"] ["log_dir"]);
    3. Creating separate php-fpm pools for the application (parameter ["php-app"] ["php"] ["pools"]);
    4. Creating Nginx virtual hosts (parameter ["php-app"] ["vhosts"]);
    5. Adding entries to the local hosts file of the virtual machine (parameter ["php-app"] ["hosts"]);
    6. Creation of databases (parameters ["php-app"] ["mysql"] and ["php-app"] ["pgsql"]);
    7. Downloading a project from a git repository (if necessary, see the section on project location);
    8. Install Composer and all project dependencies (parameter [“php-app”] [“composer”]);
    9. Execution of arbitrary commands (parameter ["php-app"] ["init_commands"]).

    This script is described in the file ".chef / site-cookbooks / php-app / recipes / default.rb" and provided with comments. In the process of developing the application, this scenario may be supplemented by new actions.

    If your PHP project uses Composer, then in the json file you need to fill in the parameter ["php-app"] ["composer"] ["github_auth_token"], otherwise the project dependencies will not be installed due to Github API restrictions. You can generate this token in the settings of your Github account .

    A complete list of the possible settings for the php-app cookbook can be seen in the file ".chef / site-cookbooks / php-app / attributes / default.rb".

    Setting up a project directory


    The location of the project directory in the virtual machine is controlled by the parameter ["php-app"] ["project_dir"]. Usually, along with this parameter, you need to change the parameter ["php-app"] ["vhosts"] ["variables"] ["root"] so that the virtual host points to the correct directory.

    Options for the location of the project directory:
    • The project is located in the shared directory (in the "/ vagrant" directory of the virtual machine, which is equal to the local directory of the project);
    • The project is located outside the shared directory (for example, in "/ home / php-app / www").

    If the project is located in a shared directory, then the virtual machine works with the same files as the developer.

    The disadvantages of this option are:
    • In the general directory, all files use the same access mode on the side of the virtual machine (by default, “777”);
    • The shared directory is not case sensitive (if Windows is used on the local machine);
    • To create symbolic links in the shared directory, you need to run virtual machines with administrator privileges of the local machine (if Windows is used on the local machine);
    • If the developer uses Linux on the local machine, then disk operations with the shared directory will be extremely slow (this problem can be solved by configuring access to the shared directory through NFS in Vagrantfile).

    The location of the project outside the shared directory (for example, in "/ home / user / www") allows you to get closer to the conditions of a real server, but also has some disadvantages:
    • The developer needs to take care of the synchronization of files between the local and virtual machine (switching between the project branches will also have to be done twice - in the local project directory and inside the virtual machine);
    • Local git commits will not be available in the virtual machine.

    If the project will be located outside the shared directory, then in the json-file you need to fill in the parameter ["php-app"] ["git"] ["repository"] to load the project when preparing the virtual machine. To access the repository, the private key specified in the [“php-app”] [“ssh”] [“deployment_key”] parameter will be used.

    The PhpStorm / IDEA IDE has the ability to configure a deployment server. In this case, changes to the local project files will be automatically uploaded to the virtual machine.

    To do this, add the deployment server (using the “Add” button in the “File - Settings - Deployment” menu) with the following settings (some settings depend on the settings in the json file):
    • Type: SFTP
    • SFTP host: 10.2.2.10
    • Port: 22
    • Root path: / home / php-app / www
    • User name: php-app
    • Auth type: Key pair (OpenSSH)
    • Private key file: project_root / .chef / files / id_rsa
    • Passphrase:
    • Web server root URL: demo.local
    • Deployment path on server: /
    • Web path on server: /

    Then, you need to set the added server as the default server (using the “Use as Default” button in the “File - Settings - Deployment” menu) and set the “Upload changed files automatically to the default server” parameter to “Always” or “On explicit save action "(in the" File - Settings - Deployment - Options "window).

    MySQL server setup


    To configure the MySQL server, an external mysql cookbook is used, therefore, to change the standard settings, you must use the mysql key in the json file. By default, the MySQL server is available for external connections on the standard port.

    In the ["php-app"] ["mysql"] ["root_connection"] parameter, you must specify access parameters for the database administrator. The administrator password is set in the parameter ["mysql"] ["server_root_password"].
    The list of created databases must be specified in the key ["php-app"] ["mysql"] ["databases"]:
    {
        ...
        "php-app": [
            ...
            "mysql": {
                "root_connection": {
                    "host": "127.0.0.1", 
                    "username": "root", 
                    "password": "" 
                },
                "databases": [
                    {
                        "name": "yii2advanced", 
                        "username": "root", 
                        "password": "", 
                        "encoding": "utf8", 
                        "collation": "utf8_general_ci"
                    },
                    {
                        "name": "yii2_advanced_tests", 
                        "username": "root", 
                        "password": "", 
                        "encoding": "utf8", 
                        "collation": "utf8_general_ci"
                    }
                ]
            }
            ...
        ],
        ...
    }
    

    Setting up a PosgtreSQL server


    To configure the PosgtreSQL server, an external cookbook “postgresql” is used, therefore, to change the standard settings, you must use the “postgresql” key in the json file. By default, the PostgreSQL server is available for external connections on the standard port.

    In the ["php-app"] ["pgsql"] ["root_connection"] parameter, you must specify access parameters for the database administrator. The administrator password is set in the parameter ["postgresql"] ["password"] ["postgres"]. This password must not be blank.

    The list of created databases must be specified in the key ["php-app"] ["pgsql"] ["databases"]:
    {
        ...
        "php-app": [
            ...
            "pgsql": {
                "root_connection": { 
                    "host": "127.0.0.1", 
                    "username": "postgres", 
                    "password": "password" 
                },
                "databases": [
                    {
                        "name": "yii2advanced", 
                        "username": "yii2advanced", 
                        "password": "", 
                        "encoding": "UTF8", 
                        "collation": "en_US.UTF-8"
                    },
                    {
                        "name": "yii2_advanced_tests", 
                        "username": "yii2advanced", 
                        "password": "", 
                        "encoding": "UTF8", 
                        "collation": "en_US.UTF-8"
                    }
                ]
            }
            ...
        ],
        ...
    }
    

    Debug Setup in PhpStorm / IDEA


    To be able to debug the application running inside the virtual machine, you need to add a PHP server (using the "Add" button in the "File - Settings - PHP - Servers" menu) with the following settings:
    • Name: demo.local
    • Host: demo.local
    • Port: 80
    • Debugger: Xdebug
    • Use path mappings: Enabled (the project directory must match the directory ["php-app"] ["project_dir"])

    Then you need to create a configuration with the type “PHP Web application” (via the menu item “Run - Edit configurations”), specifying the created PHP server.

    Conclusion


    The resulting environment turned out to be quite flexible, all software settings are completely transparent and customizable. Using Chef-Solo allows you to deploy the project on virtually any machine (not necessarily virtual) in minutes, without requiring any additional actions from the developer.

    I will be glad to hear your comments.

    Also popular now: