├── LICENSE
├── README.md
├── Vagrantfile
├── hosts
├── playbook.yml
├── profiling.yml
└── roles
├── database
├── files
│ ├── db.php
│ └── dump.sql
└── tasks
│ ├── .main.yml.swp
│ └── main.yml
├── profiling
├── files
│ ├── apache2
│ │ └── vhosts
│ │ │ └── xhgui.conf
│ ├── mysql
│ │ └── details.sql
│ ├── php
│ │ └── mods-available
│ │ │ ├── xdebug.ini
│ │ │ └── xhprof.ini
│ ├── profiling.php
│ └── xhgui
│ │ └── config.php
├── handlers
│ └── main.yml
└── tasks
│ ├── install_demo.yml
│ ├── install_prerequisites.yml
│ ├── install_xdebug.yml
│ ├── install_xhgui.yml
│ ├── install_xhprof.yml
│ └── main.yml
└── webserver
├── files
└── index.php
└── tasks
└── main.yml
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 qandidate-labs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ansible-lamp-server
2 | ===================
3 |
4 | example code used in:
5 |
6 | [Installing a LAMP server with Ansible playbooks and roles](http://labs.qandidate.com/blog/2013/11/21/installing-a-lamp-server-with-ansible-playbooks-and-roles/)
7 |
8 | [Setting up XHProf/XHGui profiling with Ansible](http://labs.qandidate.com/blog/2013/11/28/setting_up_xhprof_xhgui_profiling_with_ansible/)
9 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5 | VAGRANTFILE_API_VERSION = "2"
6 |
7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8 | # All Vagrant configuration is done here. The most common configuration
9 | # options are documented and commented below. For a complete reference,
10 | # please see the online documentation at vagrantup.com.
11 |
12 | # Every Vagrant virtual environment requires a box to build off of.
13 | config.vm.box = "ansible"
14 |
15 | # The url from where the 'config.vm.box' box will be fetched if it
16 | # doesn't already exist on the user's system.
17 | config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/raring/current/raring-server-cloudimg-amd64-vagrant-disk1.box"
18 |
19 | # Create a forwarded port mapping which allows access to a specific port
20 | # within the machine from a port on the host machine. In the example below,
21 | # accessing "localhost:8080" will access port 80 on the guest machine.
22 | # config.vm.network :forwarded_port, guest: 80, host: 8080
23 |
24 | # Create a private network, which allows host-only access to the machine
25 | # using a specific IP.
26 | config.vm.network :private_network, ip: "10.0.0.10"
27 |
28 | # Create a public network, which generally matched to bridged network.
29 | # Bridged networks make the machine appear as another physical device on
30 | # your network.
31 | # config.vm.network :public_network
32 |
33 | # If true, then any SSH connections made will enable agent forwarding.
34 | # Default value: false
35 | # config.ssh.forward_agent = true
36 |
37 | # Share an additional folder to the guest VM. The first argument is
38 | # the path on the host to the actual folder. The second argument is
39 | # the path on the guest to mount the folder. And the optional third
40 | # argument is a set of non-required options.
41 | # config.vm.synced_folder "../data", "/vagrant_data"
42 |
43 | # Provider-specific configuration so you can fine-tune various
44 | # backing providers for Vagrant. These expose provider-specific options.
45 | # Example for VirtualBox:
46 | #
47 | # config.vm.provider :virtualbox do |vb|
48 | # # Don't boot with headless mode
49 | # vb.gui = true
50 | #
51 | # # Use VBoxManage to customize the VM. For example to change memory:
52 | # vb.customize ["modifyvm", :id, "--memory", "1024"]
53 | # end
54 | #
55 | # View the documentation for the provider you're using for more
56 | # information on available options.
57 |
58 | # Enable provisioning with Puppet stand alone. Puppet manifests
59 | # are contained in a directory path relative to this Vagrantfile.
60 | # You will need to create the manifests directory and a manifest in
61 | # the file ansible.pp in the manifests_path directory.
62 | #
63 | # An example Puppet manifest to provision the message of the day:
64 | #
65 | # # group { "puppet":
66 | # # ensure => "present",
67 | # # }
68 | # #
69 | # # File { owner => 0, group => 0, mode => 0644 }
70 | # #
71 | # # file { '/etc/motd':
72 | # # content => "Welcome to your Vagrant-built virtual machine!
73 | # # Managed by Puppet.\n"
74 | # # }
75 | #
76 | # config.vm.provision :puppet do |puppet|
77 | # puppet.manifests_path = "manifests"
78 | # puppet.manifest_file = "site.pp"
79 | # end
80 |
81 | # Enable provisioning with chef solo, specifying a cookbooks path, roles
82 | # path, and data_bags path (all relative to this Vagrantfile), and adding
83 | # some recipes and/or roles.
84 | #
85 | # config.vm.provision :chef_solo do |chef|
86 | # chef.cookbooks_path = "../my-recipes/cookbooks"
87 | # chef.roles_path = "../my-recipes/roles"
88 | # chef.data_bags_path = "../my-recipes/data_bags"
89 | # chef.add_recipe "mysql"
90 | # chef.add_role "web"
91 | #
92 | # # You may also specify custom JSON attributes:
93 | # chef.json = { :mysql_password => "foo" }
94 | # end
95 |
96 | # Enable provisioning with chef server, specifying the chef server URL,
97 | # and the path to the validation key (relative to this Vagrantfile).
98 | #
99 | # The Opscode Platform uses HTTPS. Substitute your organization for
100 | # ORGNAME in the URL and validation key.
101 | #
102 | # If you have your own Chef Server, use the appropriate URL, which may be
103 | # HTTP instead of HTTPS depending on your configuration. Also change the
104 | # validation key to validation.pem.
105 | #
106 | # config.vm.provision :chef_client do |chef|
107 | # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
108 | # chef.validation_key_path = "ORGNAME-validator.pem"
109 | # end
110 | #
111 | # If you're using the Opscode platform, your validator client is
112 | # ORGNAME-validator, replacing ORGNAME with your organization name.
113 | #
114 | # If you have your own Chef Server, the default validation client name is
115 | # chef-validator, unless you changed the configuration.
116 | #
117 | # chef.validation_client_name = "ORGNAME-validator"
118 | end
119 |
--------------------------------------------------------------------------------
/hosts:
--------------------------------------------------------------------------------
1 | #hosts
2 | 10.0.0.10 ansible_ssh_user=vagrant ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key
3 |
4 |
--------------------------------------------------------------------------------
/playbook.yml:
--------------------------------------------------------------------------------
1 | # playbook.yml
2 | ---
3 | - hosts: all
4 | roles:
5 | - webserver
6 | - database
7 |
--------------------------------------------------------------------------------
/profiling.yml:
--------------------------------------------------------------------------------
1 | # profiling.yml
2 | ---
3 | - hosts: all
4 | roles:
5 | - webserver
6 | - database
7 | - profiling
8 |
--------------------------------------------------------------------------------
/roles/database/files/db.php:
--------------------------------------------------------------------------------
1 | # roles/database/files/db.php
2 | query('SELECT message FROM demo');
6 |
7 | echo $statement->fetchColumn();
8 |
9 |
--------------------------------------------------------------------------------
/roles/database/files/dump.sql:
--------------------------------------------------------------------------------
1 | # roles/database/files/dump.sql
2 | CREATE TABLE IF NOT EXISTS demo (
3 | message varchar(255) NOT NULL
4 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
5 |
6 | INSERT INTO demo (message) VALUES('Hello World!');
7 |
--------------------------------------------------------------------------------
/roles/database/tasks/.main.yml.swp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qandidate-labs/ansible-lamp-server/04e4899dfc416ed7804c42289f2c1c7633b2db5c/roles/database/tasks/.main.yml.swp
--------------------------------------------------------------------------------
/roles/database/tasks/main.yml:
--------------------------------------------------------------------------------
1 | # roles/database/tasks/main.yml
2 | ---
3 | - name: 1a. Add APT GPG signing key
4 | apt_key: url=http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xCBCB082A1BB943DB state=present
5 |
6 | - name: 1b. Add APT repository
7 | apt_repository: repo='deb http://ftp.osuosl.org/pub/mariadb/repo/10.0/ubuntu $ansible_distribution_release main' state=present update_cache=yes
8 |
9 | - name: 1c. Install MariaDB server package
10 | apt: name=mariadb-server state=present
11 |
12 | - name: 2. Start Mysql Service
13 | service: name=mysql state=started enabled=true
14 |
15 | - name: Install python Mysql package #required for mysql_db tasks
16 | apt: name=python-mysqldb state=present
17 |
18 | - name: 3. Create a new database
19 | mysql_db: name=demo state=present collation=utf8_general_ci
20 |
21 | - name: 4. Create a database user
22 | mysql_user: name=demo password=demo priv=*.*:ALL host=localhost state=present
23 |
24 | - name: 5a. Copy sample data
25 | copy: src=dump.sql dest=/tmp/dump.sql
26 |
27 | - name: 5b. Insert sample data
28 | shell: cat /tmp/dump.sql | mysql -u demo -pdemo demo
29 |
30 | - name: 6. Install MySQL extension for PHP
31 | apt: name=php5-mysql state=present
32 |
33 |
--------------------------------------------------------------------------------
/roles/profiling/files/apache2/vhosts/xhgui.conf:
--------------------------------------------------------------------------------
1 |
2 | DocumentRoot "/data/xhgui/xhprof_html"
3 | ServerName xhgui.local
4 | ErrorLog "/var/log/apache2/xhgui.localhost-error.log"
5 | CustomLog "/var/log/apache2/xhgui.localhost-access.log" combined
6 |
7 |
8 | AllowOverride All
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/roles/profiling/files/mysql/details.sql:
--------------------------------------------------------------------------------
1 | # taken from xhgui/xhprof_lib/utils/Db/Mysqli.php
2 | CREATE TABLE IF NOT EXISTS `details` (
3 | `id` char(17) NOT NULL,
4 | `url` varchar(255) default NULL,
5 | `c_url` varchar(255) default NULL,
6 | `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
7 | `server name` varchar(64) default NULL,
8 | `perfdata` MEDIUMBLOB,
9 | `type` tinyint(4) default NULL,
10 | `cookie` BLOB,
11 | `post` BLOB,
12 | `get` BLOB,
13 | `pmu` int(11) unsigned default NULL,
14 | `wt` int(11) unsigned default NULL,
15 | `cpu` int(11) unsigned default NULL,
16 | `server_id` char(3) NOT NULL default 't11',
17 | `aggregateCalls_include` varchar(255) DEFAULT NULL,
18 | PRIMARY KEY (`id`),
19 | KEY `url` (`url`),
20 | KEY `c_url` (`c_url`),
21 | KEY `cpu` (`cpu`),
22 | KEY `wt` (`wt`),
23 | KEY `pmu` (`pmu`),
24 | KEY `timestamp` (`timestamp`)
25 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
26 |
--------------------------------------------------------------------------------
/roles/profiling/files/php/mods-available/xdebug.ini:
--------------------------------------------------------------------------------
1 | zend_extension=/usr/lib/php5/20100525/xdebug.so
2 | xdebug.remote_enable=1
3 | xdebug.remote_port=9000
4 | ;xdebug.profiler_enable=1
5 | ;xdebug.profiler_output_dir="/tmp/xdebug"
--------------------------------------------------------------------------------
/roles/profiling/files/php/mods-available/xhprof.ini:
--------------------------------------------------------------------------------
1 | extension=xhprof.so
--------------------------------------------------------------------------------
/roles/profiling/files/profiling.php:
--------------------------------------------------------------------------------
1 | \n";
6 |
7 | require_once '/data/xhgui/external/footer.php';
8 |
--------------------------------------------------------------------------------
/roles/profiling/files/xhgui/config.php:
--------------------------------------------------------------------------------
1 | 'load::',
101 | 'mysql' => 'mysql_'
102 | );
103 |
104 | // For domain-specific configuration, you can use Apache setEnv xhprof_aggregateCalls_include [some_php_file]
105 | if(isset($run_details['aggregateCalls_include']) && strlen($run_details['aggregateCalls_include']) > 1)
106 | {
107 | require_once($run_details['aggregateCalls_include']);
108 | }
109 |
110 | $addIns = array();
111 | foreach($calls as $index => $call)
112 | {
113 | foreach($rules as $rule => $search)
114 | {
115 | if (strpos($call['fn'], $search) !== false)
116 | {
117 | if (isset($addIns[$search]))
118 | {
119 | unset($call['fn']);
120 | foreach($call as $k => $v)
121 | {
122 | $addIns[$search][$k] += $v;
123 | }
124 | }else
125 | {
126 | $call['fn'] = $rule;
127 | $addIns[$search] = $call;
128 | }
129 | unset($calls[$index]); //Remove it from the listing
130 | break; //We don't need to run any more rules on this
131 | }else
132 | {
133 | //echo "nomatch for $search in {$call['fn']}
\n";
134 | }
135 | }
136 | }
137 | return array_merge($addIns, $calls);
138 | }
139 |
--------------------------------------------------------------------------------
/roles/profiling/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: restart apache
3 | service: name=apache2 state=restarted
--------------------------------------------------------------------------------
/roles/profiling/tasks/install_demo.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install demo PHP script
3 | copy: src=profiling.php dest=/var/www/ mode=0644
4 | tags: profiling
5 |
--------------------------------------------------------------------------------
/roles/profiling/tasks/install_prerequisites.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install PECL
3 | apt: pkg=php-pear state=present
4 | tags: profiling
5 |
6 | - name: Install php5-dev for phpize
7 | apt: pkg=php5-dev state=present
8 | tags: profiling
9 |
10 | - name: Install git
11 | apt: pkg=git state=present
12 | tags: profiling
13 |
14 | - name: install Graphviz
15 | apt: name=graphviz state=present
16 | tags: profiling
17 |
--------------------------------------------------------------------------------
/roles/profiling/tasks/install_xdebug.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install xdebug PECL extension
3 | shell: pecl install --soft xdebug
4 | ignore_errors: true
5 | tags: profiling
6 |
7 | - name: Create extension ini file in mods-available
8 | copy: src=php/mods-available/xdebug.ini dest=/etc/php5/mods-available/ owner=root mode=644
9 | tags: profiling
10 |
11 | - name: Enable module
12 | shell: php5enmod xdebug
13 | notify: restart apache
14 | tags: profiling
15 |
--------------------------------------------------------------------------------
/roles/profiling/tasks/install_xhgui.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: clone XHGui
3 | git: repo=https://github.com/preinheimer/xhprof.git dest=/data/xhgui
4 | tags: profiling
5 |
6 | - name: copy config.php
7 | copy: src=xhgui/config.php dest=/data/xhgui/xhprof_lib/ mode=0644
8 | tags: profiling
9 |
10 | - name: Create XHGUI Database
11 | mysql_db: name=xhgui state=present collation=utf8_general_ci
12 | tags: profiling
13 |
14 | - name: Create XHGUI DB User
15 | mysql_user: name=xhgui password=xhgui priv=xhgui.*:ALL host=localhost state=present
16 | tags: profiling
17 |
18 | - name: Provision XHGUI DB (copy dump file)
19 | copy: src=mysql/details.sql dest=/tmp/development.sql
20 | tags: profiling
21 |
22 | - name: Provision XHGUI DB (import dump file)
23 | shell: cat /tmp/development.sql | mysql -u xhgui -pxhgui xhgui
24 | tags: profiling
25 |
26 | - name: copy Apache vhost config
27 | copy: src=apache2/vhosts/xhgui.conf dest=/etc/apache2/sites-available/xhgui.conf
28 | tags: apache
29 |
30 | - name: enable vhost
31 | shell: a2ensite xhgui.conf
32 | notify: restart apache
33 | tags: profiling
34 |
--------------------------------------------------------------------------------
/roles/profiling/tasks/install_xhprof.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install XHProf PECL extension
3 | shell: pecl install --soft xhprof-beta
4 | ignore_errors: true
5 | tags: profiling
6 |
7 | - name: Create extension ini file in mods-available # echo "extension=xhprof.so > xhprof.ini"
8 | copy: src=php/mods-available/xhprof.ini dest=/etc/php5/mods-available/ owner=root mode=0644
9 | tags: profiling
10 |
11 | - name: Enable module
12 | shell: php5enmod xhprof
13 | notify: restart apache
14 | tags: profiling
15 |
--------------------------------------------------------------------------------
/roles/profiling/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - include: install_prerequisites.yml
3 | - include: install_xhprof.yml
4 | - include: install_xhgui.yml
5 | - include: install_xdebug.yml
6 | - include: install_demo.yml
7 |
--------------------------------------------------------------------------------
/roles/webserver/files/index.php:
--------------------------------------------------------------------------------
1 |