Una máquina virtual lista para PHP+Symfony2+XDebug

Charlando con algunos amigos desarrolladores php surgió un tema que les estaba resultando complicado, así que decidí poner mi pequeño granito de arena (para ellos y para otros que tal vez estén pasando por lo mismo).

Ya habíamos hablado del por qué usar una máquina virtual para proyectos PHP. Ya estaba claro que usar un framework es más conveniente que no usarlo (independientemente de cuál fuera) y les había comentado sobre mis herramientas favoritas de automatización (Ansible y Vagrant).

Todos estábamos de acuerdo «en la teoría», pero a la hora de pasar a la práctica se veían algo frustrados por no poder lograr tener una máquina virtual que fuese fácil de usar y que soportara, entre otras cosas, el uso de XDebug.

Lo que te voy a mostrar a continuación son los archivos de configuración que yo usé en el último proyecto que hice en php:

El archivo playbook.yml:

---
- hosts: all
 sudo: true
 tasks:

- name: create /var/www
 file: path=/var/www state=directory

- name: create site symlink
 file: src=/vagrant dest=/var/www/site state=link
 notify: restart apache

- name: install misc packages
 apt: name={{ item }} state=latest update_cache=true
 with_items:
 - ruby2.0
 - ruby2.0-dev
 - git
 - curl
 - unzip
 - vim

- name: Symlink exists for Ruby 2.0
 file: src=/usr/bin/ruby2.0 dest=/usr/local/bin/ruby state=link

- name: Symlink exists for Ruby Gems 2.0
 file: src=/usr/bin/gem2.0 dest=/usr/local/bin/gem state=link

- name: install language packs for locale support
 apt: name={{ item }} state=latest
 with_items:
 - language-pack-de-base
 - language-pack-es-base

# Apache2

- name: ensure apache is installed
 apt: name=apache2 state=present

- name: make sure apache is running
 action: service name=apache2 state=started enabled=true

- file: src=/etc/apache2/mods-available/rewrite.load dest=/etc/apache2/mods-enabled/rewrite.load state=link
 notify: restart apache

- file: src=/etc/apache2/mods-available/headers.load dest=/etc/apache2/mods-enabled/headers.load state=link
 notify: restart apache

- copy: src=/vagrant/ansible/templates/site.conf dest=/etc/apache2/sites-available/site.conf remote_src=true
 notify: restart apache

- file: src=/etc/apache2/sites-available/site.conf dest=/etc/apache2/sites-enabled/site.conf state=link
 notify: restart apache

- file: path=/etc/apache2/sites-enabled/000-default.conf state=absent
 notify: restart apache

- file: path=/etc/apache2/conf.d state=directory

- copy: src=/vagrant/ansible/templates/fqdn.conf dest=/etc/apache2/conf.d/fqdn.conf remote_src=true
 notify: restart apache

- copy: src=/vagrant/ansible/templates/nosendfile.conf dest=/etc/apache2/conf.d/nosendfile.conf remote_src=true
 notify: restart apache

# MySQL

- name: install MySQL
 apt: name={{ item }} state=latest
 with_items:
 - mysql-server
 - mysql-client
 - python-mysqldb

- name: add mysql user
 mysql_user: name=vagrant
 host={{ item }}
 password=vagrant priv=*.*:ALL,GRANT
 login_user=root
 login_password=
 with_items:
 - '%'
 - localhost

- name: create mysql databases
 mysql_db: name={{ item }}
 state=present
 with_items:
 - site_development
 - site_development_stats
 - site_testing
 - site_testing_stats

- file: path=/etc/mysql/conf.d state=directory
 - name: Set MySQL number of connections
 copy: src=/vagrant/ansible/templates/max_connections.cnf dest=/etc/mysql/conf.d/max_connections.cnf remote_src=true
 notify: restart mysql

- name: Install mysql command line client configuration file
 copy: src=/vagrant/ansible/templates/my.cnf dest=/home/vagrant/.my.cnf owner=vagrant group=vagrant remote_src=true

# PHP

- name: add php5.6 ppa
 apt_repository: repo='ppa:ondrej/php'

- name: install PHP5.6 packages
 apt: name={{ item }} state=latest
 with_items:
 - php5.6
 - libapache2-mod-php5.6
 - php5.6-cli
 - php5.6-dev
 - php5.6-mysql
 - php-pear
 - php5.6-mcrypt
 - php5.6-gd
 - php5.6-curl
 - php5.6-xdebug
 - php5.6-memcache
 - php5.6-memcached
 - php5.6-readline
 - php5.6-xml
 - php5.6-mbstring
 - php5.6-zip

- file: path=/etc/php5.6/conf.d state=directory
 - file: path=/etc/php5.6/cli/conf.d state=directory
 - file: path=/etc/php5.6/apache2/conf.d state=directory

- copy: src=/vagrant/ansible/templates/php-site.ini dest=/etc/php5.6/conf.d/php-site.ini remote_src=true
 notify: restart apache

- name: configure xdebug
 copy: src=templates/xdebug.ini dest=/etc/php/5.6/mods-available/xdebug.ini
 notify: restart apache

- name: symlink common php configuration for cli handler
 file: src=/etc/php5.6/conf.d/php-site.ini dest=/etc/php5.6/cli/conf.d/php-site.ini state=link
 notify: restart apache

- name: symlink common php configuration for apache2 handler
 file: src=/etc/php5.6/conf.d/php-site.ini dest=/etc/php5.6/apache2/conf.d/php-site.ini state=link
 notify: restart apache

# phpmyadmin

- name: install phpmyadmin
 apt: name=phpmyadmin state=latest

# Assets compilation

- name: add nodejs ppa
 apt_repository: repo='ppa:chris-lea/node.js'

- name: install nodejs
 apt: name=nodejs state=latest

# Set up site

- file: src=/vagrant dest=/var/www/site state=link
 - file: path={{ item }} owner=vagrant group=vagrant mode=0777 state=directory
 with_items:
 - /var/cache/site
 - /var/cache/site/cache
 - /var/cache/site/clockwork
 - /var/cache/site/logs
 - /var/cache/site/meta
 - /var/cache/site/sessions
 - /var/cache/site/views

- name: ensure once more that 000-default.conf is deleted
 file: path=/etc/apache2/sites-enabled/000-default.conf state=absent
 notify: restart apache

- name: ensure that phpmyadmin's stock config is deleted
 file: path=/etc/apache2/conf.d/phpmyadmin.conf state=absent

- name: set proper permissions for app/reports directory
 file: path=/vagrant/app/reports group=www-data owner=vagrant mode=0775 state=directory

# Common stuff

- name: Install Composer
 shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer creates=/usr/local/bin/composer

handlers:
 - name: restart apache
 action: service name=apache2 state=restarted
 - name: restart mysql
 action: service name=mysql state=restarted
 - name: restart beanstalkd
 action: service name=beanstalkd state=restarted

Los archivos templates (deben estar en el directorio ansible/templates dentro de tu proyecto):

site.conf:

<VirtualHost *:80>
 ServerName myApp
 DocumentRoot /var/www/site/web

<Directory />
 Options FollowSymLinks
 AllowOverride None
 </Directory>

<Directory /var/www/site/web>
 DirectoryIndex app_dev.php
 Options Indexes FollowSymLinks MultiViews
 AllowOverride All
 Order allow,deny
 allow from all
 </Directory>

ErrorLog /var/log/apache2/error.log
 LogLevel warn
 CustomLog /var/log/apache2/access.log combined

## enable phpmyadmin

Alias /phpmyadmin /usr/share/phpmyadmin

<Directory /usr/share/phpmyadmin>
 Options FollowSymLinks
 DirectoryIndex index.php

<IfModule mod_php5.c>
 AddType application/x-httpd-php .php

php_flag magic_quotes_gpc Off
 php_flag track_vars On
 php_flag register_globals Off
 php_admin_flag allow_url_fopen Off
 php_value include_path .
 php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp
 php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/
 </IfModule>

</Directory>
</VirtualHost>

fqdn.conf

ServerName Localhost

nosendfile.conf

EnableSendfile off

max_connections.cnf

[mysqld]
max_connections = 400

my.cnf

[client]
user=vagrant
password=vagrant

php-site.ini

max_execution_time = 30000
memory_limit = 512M
display_errors = On
disable_functions =

xdebug.ini

zend_extension=xdebug.so
xdebug.remote_enable=On
xdebug.remote_connect_back=On

Para iniciar el proyecto, basta con copiar y pegar esto en un archivo llamado Vagrantfile (en la raíz de tu proyecto):

# -*- mode: ruby -*-
 # vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
 # configures the configuration version (we support older styles for
 # backwards compatibility). Please don't change it unless you know what
 # you're doing.
 Vagrant.configure("2") do |config|
 # The most common configuration options are documented and commented below.
 # For a complete reference, please see the online documentation at
 # https://docs.vagrantup.com.

# Every Vagrant development environment requires a box. You can search for
 # boxes at https://atlas.hashicorp.com/search.
 config.vm.box = "ubuntu/trusty64"

# Disable automatic box update checking. If you disable this, then
 # boxes will only be checked for updates when the user runs
 # `vagrant box outdated`. This is not recommended.
 # config.vm.box_check_update = false

# Create a forwarded port mapping which allows access to a specific port
 # within the machine from a port on the host machine. In the example below,
 # accessing "localhost:8080" will access port 80 on the guest machine.
 config.vm.network "forwarded_port", guest: 80, host: 8080

# Create a private network, which allows host-only access to the machine
 # using a specific IP.
 config.vm.network "private_network", ip: "192.168.33.10"

# Create a public network, which generally matched to bridged network.
 # Bridged networks make the machine appear as another physical device on
 # your network.
 # config.vm.network "public_network"

# Share an additional folder to the guest VM. The first argument is
 # the path on the host to the actual folder. The second argument is
 # the path on the guest to mount the folder. And the optional third
 # argument is a set of non-required options.
 # config.vm.synced_folder "../data", "/vagrant_data"

# Provider-specific configuration so you can fine-tune various

# backing providers for Vagrant. These expose provider-specific options.
 # Example for VirtualBox:
 #
 config.vm.provider "virtualbox" do |vb|
 # # Display the VirtualBox GUI when booting the machine
 # vb.gui = true
 #
 # # Customize the amount of memory on the VM:
 vb.memory = "2048"
 end
 #
 # View the documentation for the provider you are using for more
 # information on available options.

# Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
 # such as FTP and Heroku are also available. See the documentation at
 # https://docs.vagrantup.com/v2/push/atlas.html for more information.
 # config.push.define "atlas" do |push|
 # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
 # end

# Enable provisioning with a shell script. Additional provisioners such as
 # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
 # documentation for more information about their specific syntax and use.
 # config.vm.provision "shell", inline: <<-SHELL
 # apt-get update
 # apt-get install -y apache2
 # SHELL

#
 # Run Ansible from the Vagrant Host
 #
 config.vm.provision "ansible" do |ansible|
   ansible.playbook = "ansible/playbook.yml"
   ansible.verbose = "vv"
 end

# Symfony needs to be able to write to it's cache, logs and sessions directory in var/
 config.vm.synced_folder "./var", "/vagrant/var",
   :owner => 'vagrant',
   :group => 'www-data',
   :mount_options => ["dmode=777","fmode=777"]
 end

y ejecutar el comando (Obviamente, habiendo instalado Vagrant previamente…):

 vagrant up

Y comienza la magia 🙂

Un ratito después (Dependiendo de la conexión que tengas) vas a tener una máquina lista para desarrollar tu aplicación basada en Symfony2.

Y ahora… ¡a codear!

¿Me olvidé de algo? ¡Avisame en los comentarios!

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a acceder mercados y clientes más sofisticados y exigentes

1 comentario

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.