9.10.16

Laravel: configurando la máquina Homestead desde Windows

Una de las cosas que más me fastidian de los manuales es cuando dan por supuesto que todo el mundo sabe lo suficiente como para no necesitar manuales y omiten pasos.

Algo así es lo que me pasó a la hora de configurar el entorno Vagrant para trabajar con Laravel. Así que como nota personal y antes de que me olvide apunto esto por aquí y tal vez sirva a alguna gente más.

Partimos de la base del manual oficial y sobre ella os comento las dificultades que he ido encontrando y cómo las he solucionado.

En primer lugar, para instalar el entorno oficial de desarrollo llamado Homestead vamos a necesitar algunas cosillas.


Software necesario

Homestead es una máquina virtual que han compilado los responsables de Laravel y es, en teoría, la mejor forma de desarrollar. Se trata de máquinas fácilmente desechables y reconstruibles en un momento si algo fallase. Esta máquina virtual se configura a partir del entorno Vagrant.

Otro software que es necesario es la última versión de Virtualbox. Vagrant descargará despues un disco duro virtual desde los servidores de Laravel y a partir de él configurará la máquina virtual. No tenéis que crearla con Virtualbox. De hecho, para generar la máquina y utilizarla no es necesario arrancar Virtualbox en ningún momento. Vagrant se ocupa de todo.

Para poder conectarnos a esta MV vamos a requerir de la generación de claves SSH. Esto no va a ser posible desde la mayor parte de los sistemas Windows. Para ello vamos a descargar una herramienta llamada GitBash, que usaremos además para otras cosas. El manual en ningún momento te habla de ella, pero asume que la tienes y que sabes usarla.

Una vez instalados estos tres productos pasamos a la instalación propiamente dicha.


Bajando el entorno Homestead

Vamos a abrir una consola de windows pulsando inicio y escribiendo cmd. Debes asegurarte de estar posicionado en c:\users\tuusuario. Desde allí ejecutamos

vagrant box add laravel/homestead

Este comando hará que Vagrant se conecte a sus repositorios y comience a bajarse el disco duro virtual y algunos otros archivos necesarios. No hace falta que diga que es necesario tener conexión a internet. Con una conexión lenta va a tardar mucho ya que se baja algo más de un giga de datos. Aunque no es necesario que lo sepais la máquina se descarga en esta ruta: C:\Users\tuusuario\.vagrant.d\boxes\laravel-VAGRANTSLASH-homestead\0.5.0\virtualbox.


Instalando Homestead

Una vez bajado hay que instalarlo.

Entramos en GitBash y nos vamos a nuestro directorio home (en windows C:\users\tusuario) y clonamos el repositorio Homestead

cd ~

git clone https://github.com/laravel/homestead.git Homestead

Nuevamente descargará datos, pero no será un proceso tan lento como el anterior. Una vez termina la descarga entramos en el directorio Homestead y lanzamos init.sh. Este script va a generar un fichero llamado VagrantFile que luego modificaremos y un homestead.yaml que necesitaremos configurar.

cd Homestead 
bash init.sh laravel/homestead

Con esto la instalación debería estar concluida


Configurando Homestead


Aunque normalmente el fichero yaml está bien configurado hay algunas cosillas que podemos comprobar. Abrimos el fichero con nuestro editor de texto favorito (recomiendo Notepad++) en la siguiente ruta: C:\Users\tuusuario\.homestead\Homestead.yaml

Lo único que tuve que modificar del fichero fueron las rutas, que en mi caso quedaron así:


folders:
    - map: ~/Code
      to: /home/vagrant/Code

sites:
    - map: homestead.app
      to: /home/vagrant/Code/Laravel/public

Teóricamente esto debe configurar carpetas compartidas, de forma que puedas trabajar en tu equipo y sin embargo se ejecute en Homestead. Recordad que ~/Code equivale a c:\users\tuusuario\Code.

Lo siguiente es generar las claves ssh. Esta parte no aparece en el manual pero es necesario para poder conectarnos. Desde GitBash hay que utilizar el siguiente comando

ssh-keygen -t rsa -C "your@email.com"

Esto va a generar las claves que necesitamos. En mi caso las generó en el directorio desde el que lancé el comando (podéis verlo con el comando pwd) y tuve que crearme una carpeta C:\Users\tuusuario\.ssh a la que desplazar los dos ficheros generados (id_rsa y id_rsa.pub). Esta es la carpeta que espera vagrant ya que está definida en el fichero yaml

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

Ya casi está. El siguiente paso es configurar una URL, que también aparece en el fichero yaml, dentro del etchosts de windows. Se trata de editar el siguiente fichero: C:\Windows\System32\drivers\etc\hosts y añadir la línea indicada por el manual

192.168.10.10  homestead.app

Esto permitirá que luego podamos acceder a nuestra aplicación homestead.app desde el navegador.

Arranquemos la máquina con el comando desde el directorio c:\users\tuusuario\Homestead

vagrant up

 

Si lo hice todo bien, ¿por qué no funciona?


Me pasó la primera vez y resultó que el clonado del Homestead bajó una versión del repositorio que no era correcta. Las siguientes líneas corrigen parte de los problemas pero no conseguí hacer funcionar nginx. De todas formas lo dejo por si alguien se atasca en algo parecido, para que pueda avanzar algo. Al fnal pongo un ejemplo de Vagrantfile correcto.


En mi caso siguiendo el manual me conectaba vía ssh a nuestra máquina (con Putty, por ejemplo) a la dirección y puertos especificados: 127.0.0.1, puerto 2222 y usuario vagrant/vagrant. Y todo va bien

Pero cuando al conectarme a MySQL (con HeidiSQL, por ejemplo) me daba un error 10061. ¿Qué puede fallar? Había probado a configurar la conexión con usuario vagrant y contraseña secret. Había  puesto el puerto 33060 y no había manera de que la cosa funcione desde la URL 127.0.0.1 que nos indica el manual claramente.

La pista está aquí:
 
 ... 
 default: Forwarding ports...
 default: 22 (guest) to 2222 (host) (adapter 1)
 default: Booting VM...
 default: Waiting for machine to boot. This may take a few minutes...
 ... 

Como podéis ver sólo se está redireccionando el puerto SSH del 22 (dentro de la MV) a 2222 (desde fuera). Por eso funciona la conexión desde Putty.

Así que hay que modificar el VagrantFile y añadir las redirecciones que faltan. Esta es la ruta al fichero: C:\Users\tuusuario\Homestead\Vagrantfile. Buscáis "forwarded" para posicionaros en el lugar correcto y añadimos estas dos líneas.

config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 3306, host: 33060

Y ya que estamos, podemos ver si hay problemas con las carpetas sincronizadas. Buscamos "synced" y añadimos si falta

config.vm.synced_folder "../Code", "/home/vagrant/Code"

Si queremos hacer un reboot (será necesario para tomar en cuenta cambios en la configuración) utilizaríamos

vagrant reload

Y ahora ya vemos que la traza es diferente

 default: Forwarding ports...
    default: 80 (guest) to 8080 (host) (adapter 1)
    default: 3306 (guest) to 33060 (host) (adapter 1)
    default: 22 (guest) to 2222 (host) (adapter 1)
(...)
 default: Mounting shared folders...
    default: /vagrant to C:/Users/tuusuario/Homestead
    default: /home/vagrant/Code => C:/Users/tuusuario/Code


Si hacéis la prueba veréis que vuestras carpetas sincronizan y que HeidiSQL ya se conecta al MySQL de Homestead


Ejemplo de Vagrantfile correcto. Si algo falla hay que ver si tiene este formato. Si aparece con el formato un formato distinto probad a bajarlo de nuevo o a utilizar este como base para el vuestro.


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

require 'json'
require 'yaml'

VAGRANTFILE_API_VERSION ||= "2"
confDir = $confDir ||= File.expand_path("~/.homestead")

homesteadYamlPath = confDir + "/Homestead.yaml"
homesteadJsonPath = confDir + "/Homestead.json"
afterScriptPath = confDir + "/after.sh"
aliasesPath = confDir + "/aliases"

require File.expand_path(File.dirname(__FILE__) + '/scripts/homestead.rb')

Vagrant.require_version '>= 1.8.4'

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    if File.exist? aliasesPath then
        config.vm.provision "file", source: aliasesPath, destination: "~/.bash_aliases"
    end

    if File.exist? homesteadYamlPath then
        settings = YAML::load(File.read(homesteadYamlPath))
    elsif File.exist? homesteadJsonPath then
        settings = JSON.parse(File.read(homesteadJsonPath))
    end

    Homestead.configure(config, settings)

    if File.exist? afterScriptPath then
        config.vm.provision "shell", path: afterScriptPath, privileged: false
    end

    if defined? VagrantPlugins::HostsUpdater
        config.hostsupdater.aliases = settings['sites'].map { |site| site['map'] }
    end
end